#
Chapter 36
`thread.ss`: Thread Utilities

`(consumer-thread``` `f``` [`init`]`)` PROCEDURE

Returns two values: a thread descriptor for a new thread, and a procedure with the same arity as `f`.10 When the returned procedure is applied, its arguments are queued to be passed on to `f`, and void is immediately returned. The thread created by `consumer-thread` dequeues arguments and applies `f` to them, removing a new set of arguments from the queue only when the previous application of `f` has completed; if `f` escapes from a normal return (via an exception or a continuation), the `f`-applying thread terminates.

The `init` argument is a procedure of no arguments; if it is provided, `init` is called in the new thread immediately after the thread is created.

`(copy-port``` `input-port output-port``` `···`1`)` PROCEDURE

Reads data from `input-port` and writes it back out to `output-port`, returning when `input-port` produces `eof`. The copy is efficient, and without significant buffer delays (i.e., a character that becomes available on `input-port` is immediately transferred to `output-port`, even if future reads on `input-port` must block).

This function is often called from a ``background'' thread to continuously pump data from one stream to another.

If multiple `output-port`s are provided, case data from `input-port` is written to every `output-port`. The different `output-port`s block output to each other, because each quantum of data read from `input-port` is written completely to one `output-port` before moving to the next `output-port`. The `output-port`s are written in the provided order, so non-blocking ports (e.g., to a file) should be placed first in the argument list.

`(dynamic-disable-break``` `thunk``)` PROCEDURE

Invokes `thunk` and returns the result. During the application of `thunk`, breaks are disabled.

`(dynamic-enable-break``` `thunk``)` PROCEDURE

Invokes `thunk` and returns the result. During the application of `thunk`, breaks are enabled.

`(input-port-append``` `close-at-eof? input-port``` `···``)` PROCEDURE

Takes any number of input ports and returns an input port. Reading from the input port draws characters from the given input ports in order. If `close-at-eof?` is true, then each port is closed when an end-of-file is encountered from the port, or when the result input port is closed. Otherwise, data not read from the returned input port remains available for reading in its original input port.

See also `merge-input`, which interleaves data from multiple input ports as it becomes available.

`(make-limited-input-port``` `input-port limit-k``` [`close-orig?`]`)` PROCEDURE

Returns a port whose content is drawn from `input-port`, but where an end-of-file is reported after `limit-k` characters are read. If `close-orig?` is true, then the original port is closed if the returned port is closed.

Characters are consumed from `input-port` only when they are consumed from the returned port. In particular, peeking into the returned port peeks into the original port.

If `input-port` is used directly while the resulting port is also used, then the `limit-k` characters provided by the port need not be contiguous parts of the original port's stream.

`(make-single-threader``)` PROCEDURE

Returns a new procedure that takes any thunk and applies it. When this procedure is applied to any collection of thunks by any collection of threads, the thunks are applied sequentially across all threads.

`(merge-input``` `a-input-port b-input-port``` [`limit-k`]`)` PROCEDURE

Accepts two input ports and returns a new input port. The new port merges the data from two original ports, so data can be read from the new port whenever it is available from either original port. The data from the original ports are interleaved. When EOF has been read from an original port, it no longer contributes characters to the new port. After EOF has been read from both original ports, the new port returns EOF. Closing the merged port does not close the original ports.

The optional `limit-k` argument limits the number of characters to be buffered from `a-input-port` and `b-input-port`, so that the merge process does not advance arbitrarily beyond the rate of consumption of the merged data. A `#f` value disables the limit; the default is `4096`.

See also `input-port-append`, which concatenates input streams instead of interleaving them.

`(run-server``` `port-k session-proc session-timeout``` [`handler-proc listen-proc close-proc accept-proc accept/break-proc`]`)` PROCEDURE

Executes a TCP server on the port indicated by `port-k`. When a connection is made by a client, `session-proc` is called with two values: an input port to receive from the client, and an output port to send to the client.

Each client connection, or session, is managed by a new custodian, and each call to `session-proc` occurs in a new thread (managed by the session's custodian). If the thread executing `session-proc` terminates for any reason (e.g., `session-proc` returns), the session's custodian is shut down. Consequently, `session-proc` need not close the ports provided to it. Breaks are enabled in the session thread if breaks are enabled when `run-server` is called.

If `session-timeout` is not `#f`, then it must be a non-negative number specifying the time in seconds that a session thread is allowed to run before it is sent a break signal. Then, if the thread runs longer than `(* session-timeout 2)` seconds, then the session's custodian is shut down. If `session-timeout` is `#f`, a session thread can run indefinitely.

If `handler-proc` is provided, it is passed exceptions related to connections (i.e., exceptions not caught by `session-proc`, or exceptions that occur when trying to accept a connection). The default handler ignores the exception and returns void.

The `listen-proc`, `close-proc`, `accept-proc` and `accept/break-proc` arguments default to the `tcp-listen`, `tcp-close`, `tcp-accept`, and `tcp-accept/enable-break` procedures, respectively. The `run-server` function calls these procedures without optional arguments. Provide alternate procedures to use an alternate communication protocol (such as SLL) or to supply optional arguments in the use of `tcp-listen`.

The `run-server` procedure loops to serve client connections, so it never returns. If a break occurs, the loop will cleanly shut down the server, but it will not terminate active sessions.

`(with-semaphore``` `s thunk``)` PROCEDURE

Calls `semaphore-wait` on `s`, then invokes `thunk` with no arguments, and then calls `semaphore-post` on `s`. The return value is the result of calling `thunk`.

10 The returned procedure actually accepts any number of arguments, but immediately raises `exn:fail:contract:arity` if `f` cannot accept the provided number of arguments.