#
Chapter 30
`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.

`(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`.

`(run-server``` `port-k session-proc session-timeout``)` PROCEDURE

Executes a TCP server on the port inidicated 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., `sesson-proc` returns), the session's custodian is shut down. Consequently, `session-proc` need not close the ports provded 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.

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:application:arity` if `f` cannot accept the provided number of arguments.