Added SELECT-PORT-CHANNELS.

This commit is contained in:
sperber 2002-11-28 14:31:57 +00:00
parent b01518b4d9
commit 923ada9986
4 changed files with 74 additions and 41 deletions

View File

@ -188,9 +188,9 @@ We manage the project using SourceForge:
checksums. checksums.
** API changes ** API changes
select and select! are supported again. Note however, that we select and select! are supported again.
recommend to use the new select-ports procedure instead whenever Note however, that we recommend to use the new select-ports and
possible. select-port-channels procedures instead whenever possible.
New interface to the uname function. New interface to the uname function.
New direct interface to the directory stream operations New direct interface to the directory stream operations
New structure scheme-with-scsh which combines the exports of the New structure scheme-with-scsh which combines the exports of the

View File

@ -837,22 +837,24 @@ Returns two ports, the read and write end-points of a {\Unix} pipe.
that send requests to multiple alternate servers and discard all that send requests to multiple alternate servers and discard all
but one of them. but one of them.
In any case, the \texttt{select-ports} procedure described below In any case, the \texttt{select-ports} and
is usually a preferable alternative to \texttt{select-port-channels} procedures described below
\texttt{select}/\texttt{select!}: it is much simpler to use, and are usually a preferable alternative to
also has a slightly more efficient implementation.} \texttt{select}/\texttt{select!}: they are much simpler to use, and
also have a slightly more efficient implementation.}
\end{desc} \end{desc}
\defun {select-ports}{timeout port \ldots}{ready-ports} \defun {select-ports}{timeout port \ldots}{ready-ports}
\begin{desc} \begin{desc}
The \ex{select-ports} call will block until at least one of the ports The \ex{select-ports} call will block until at least one of the
passed to it is ready for operation. For an input port this means ports passed to it is ready for operation or until the timeout has
that it either has data sitting its buffer or that the underlying expired. For an input port this means that it either has data
file descriptor has data waiting. For an output port this means sitting its buffer or that the underlying file descriptor has data
that it either has space available in the associated buffer or that waiting. For an output port this means that it either has space
the underlying file descriptor can accept output. available in the associated buffer or that the underlying file
descriptor can accept output.
The \var{timeout} value can be used to force the call to time-out The \var{timeout} value can be used to force the call to time out
after a given number of seconds. A value of \ex{\#f} means to wait after a given number of seconds. A value of \ex{\#f} means to wait
indefinitely. A zero value can be used to poll the ports. indefinitely. A zero value can be used to poll the ports.
@ -861,6 +863,23 @@ Returns two ports, the read and write end-points of a {\Unix} pipe.
before any ports became ready. before any ports became ready.
\end{desc} \end{desc}
\defun {select-port-channels}{timeout port \ldots}{ready-ports}
\begin{desc}
\texttt{Select-port-channels} is like \texttt{select-ports}, except
that it only looks at the operating system objects the ports refer
to, ignoring any buffering performed by the ports.
\remark{\texttt{Select-port-channels} should be used with care: for
example, if an input port has data in the buffer but no data
available on the underlying file descriptor,
\texttt{select-port-channels} will block, even though a read
operation on the port would be able to complete without blocking.
\texttt{Select-port-channels} is intended for situations where the
program is not checking for available data, but rather for waiting
until a port has established a connection---for example, to a
network port.}
\end{desc}
\begin{defundescx}{write-string}{string [fd/port start end]}\undefined \begin{defundescx}{write-string}{string [fd/port start end]}\undefined
This procedure writes all the data requested. This procedure writes all the data requested.

View File

@ -949,7 +949,6 @@
(values n-read-ready n-write-ready 0))))))))) (values n-read-ready n-write-ready 0)))))))))
(define (select-ports timeout . ports) (define (select-ports timeout . ports)
(let ((read-list (filter input-port? ports)) (let ((read-list (filter input-port? ports))
(write-list (filter output-port? ports))) (write-list (filter output-port? ports)))
@ -967,31 +966,46 @@
((structure-ref interrupts enable-interrupts!)) ((structure-ref interrupts enable-interrupts!))
(append any-read any-write)) (append any-read any-write))
;; we need to block (really-select-port-channels timeout read-list write-list)))))
(let ((read-channels (map port/fdes->input-channel read-list))
(write-channels (map port/fdes->output-channel write-list)))
(for-each (lambda (channel) (define (select-port-channels timeout . ports)
(add-pending-channel channel #t)) (let ((read-list (filter input-port? ports))
read-channels) (write-list (filter output-port? ports)))
(for-each (lambda (channel) ((structure-ref interrupts disable-interrupts!))
(add-pending-channel channel #f))
write-channels)
(call-with-values (for-each input-port/fdes-check-unlocked read-list)
(lambda () (for-each output-port/fdes-check-unlocked write-list)
(wait-for-channels read-channels write-channels timeout))
;; re-enables interrupts (really-select-port-channels timeout read-list write-list)))
(lambda (ready-read-channels ready-write-channels)
(append (filter (lambda (read-port) ;; assumes interrupts are disabled and that ports aren't locked
(any (lambda (read-channel)
(eq? read-channel (define (really-select-port-channels timeout read-list write-list)
(port/fdes->input-channel read-port))) (let ((read-channels (map port/fdes->input-channel read-list))
ready-read-channels)) (write-channels (map port/fdes->output-channel write-list)))
read-list)
(filter (lambda (write-port) (for-each (lambda (channel)
(any (lambda (write-channel) (add-pending-channel channel #t))
(eq? write-channel read-channels)
(port/fdes->output-channel write-port)))))
write-list))))))))) (for-each (lambda (channel)
(add-pending-channel channel #f))
write-channels)
(call-with-values
(lambda ()
(wait-for-channels read-channels write-channels timeout))
;; re-enables interrupts
(lambda (ready-read-channels ready-write-channels)
(append (filter (lambda (read-port)
(any (lambda (read-channel)
(eq? read-channel
(port/fdes->input-channel read-port)))
ready-read-channels))
read-list)
(filter (lambda (write-port)
(any (lambda (write-channel)
(eq? write-channel
(port/fdes->output-channel write-port)))))
write-list))))))

View File

@ -221,7 +221,7 @@
read-string!/partial read-string!/partial
select select! select select!
select-ports select-ports select-port-channels
(write-string (proc (:string &opt :value :exact-integer :exact-integer) :unspecific)) (write-string (proc (:string &opt :value :exact-integer :exact-integer) :unspecific))
write-string/partial))) write-string/partial)))