summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2019-04-08 06:21:20 -0400
committerMark H Weaver <mhw@netris.org>2019-06-18 02:05:20 -0400
commitd4df87fd7ab3642d7b083708addeb413bc15fe48 (patch)
tree20ed5e587c930afb7e3cacb378911332e3369649
parentcc73c2ab5deda6257564c675613122da3ee85a7c (diff)
open-pipe*: Improve performance of OPEN_BOTH mode.
* module/ice-9/popen.scm (make-rw-port): Re-implement using R6RS custom binary input/output ports.
-rw-r--r--module/ice-9/popen.scm59
1 files changed, 45 insertions, 14 deletions
diff --git a/module/ice-9/popen.scm b/module/ice-9/popen.scm
index b166e9d0f..f9781c698 100644
--- a/module/ice-9/popen.scm
+++ b/module/ice-9/popen.scm
@@ -1,7 +1,7 @@
;; popen emulation, for non-stdio based ports.
-;;;; Copyright (C) 1998, 1999, 2000, 2001, 2003, 2006, 2010, 2011, 2012,
-;;;; 2013 Free Software Foundation, Inc.
+;;;; Copyright (C) 1998-2001, 2003, 2006, 2010-2013, 2019
+;;;; Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
@@ -19,10 +19,12 @@
;;;;
(define-module (ice-9 popen)
- :use-module (ice-9 threads)
- :use-module (srfi srfi-9)
- :export (port/pid-table open-pipe* open-pipe close-pipe open-input-pipe
- open-output-pipe open-input-output-pipe))
+ #:use-module (rnrs bytevectors)
+ #:use-module (ice-9 binary-ports)
+ #:use-module (ice-9 threads)
+ #:use-module (srfi srfi-9)
+ #:export (port/pid-table open-pipe* open-pipe close-pipe open-input-pipe
+ open-output-pipe open-input-output-pipe))
(eval-when (expand load eval)
(load-extension (string-append "libguile-" (effective-version))
@@ -34,14 +36,43 @@
(pid pipe-info-pid set-pipe-info-pid!))
(define (make-rw-port read-port write-port)
- (make-soft-port
- (vector
- (lambda (c) (write-char c write-port))
- (lambda (s) (display s write-port))
- (lambda () (force-output write-port))
- (lambda () (read-char read-port))
- (lambda () (close-port read-port) (close-port write-port)))
- "r+"))
+ (define (read! bv start count)
+ (let ((result (get-bytevector-some! read-port bv start count)))
+ (if (eof-object? result)
+ 0
+ result)))
+
+ (define (write! bv start count)
+ (put-bytevector write-port bv start count)
+ count)
+
+ (define (close)
+ (close-port read-port)
+ (close-port write-port))
+
+ (define rw-port
+ (make-custom-binary-input/output-port "ice-9-popen-rw-port"
+ read!
+ write!
+ #f ;get-position
+ #f ;set-position!
+ close))
+ ;; Enable buffering on 'read-port' so that 'get-bytevector-some' will
+ ;; return non-trivial blocks.
+ (setvbuf read-port 'block 16384)
+
+ ;; Inherit the port-encoding from the read-port.
+ (set-port-encoding! rw-port (port-encoding read-port))
+
+ ;; Reset the port encoding on the underlying ports to inhibit BOM
+ ;; handling there. Instead, the BOM handling (if any) will be handled
+ ;; in the rw-port. In the current implementation of Guile ports,
+ ;; using binary I/O primitives alone is not enough to reliably inhibit
+ ;; BOM handling, if the port encoding is set to UTF-{8,16,32}.
+ (set-port-encoding! read-port "ISO-8859-1")
+ (set-port-encoding! write-port "ISO-8859-1")
+
+ rw-port)
;; a guardian to ensure the cleanup is done correctly when
;; an open pipe is gc'd or a close-port is used.