#
Chapter 7
Threads

MzScheme supports multiple threads of control within a program. Threads are implemented for all operating systems, even when the operating system does not provide primitive thread support.

`(thread``` `thunk``)` invokes the procedure `thunk` with no arguments in a new thread of control. The ``thread`` procedure returns immediately with a thread descriptor value. When the invocation of `thunk` returns, the thread created to invoke `thunk` terminates.

Example:

    (thread (lambda () (sleep 2) (display 7) (newline))) ; => a thread descriptor
     displays 7 after two seconds pass

Each thread has its own parameter settings (see section 7.9), such as the current directory or current exception handler. A newly-created thread inherits the parameter settings of the creating thread, except

- the ``error-escape-handler`` parameter, which is initialized to the default error escape handler; and

- the ``current-exception-handler`` parameter, which is initialized to the value of ``initial-exception-handler``.

When a thread is created, it is placed into the management of the current custodian (see section 9.2) and added to the current thread group (see section 9.3). A thread can have any number of custodian managers added through `thread-resume`.

A thread that has not terminated can be ``garbage collected'' if it is unreachable and suspended, or if it is unreachable and blocked on a set of unreachable events through `semaphore-wait` or `semaphore-wait/enable-break` (see section 7.4), `channel-put` or `channel-get` (see section 7.5), `sync` or `sync/enable-break` (see section 7.7), or `thread-wait`.16

All constant-time procedures and operations provided by MzScheme are thread-safe because they are atomic. For example, `set!` assigns to a variable as an atomic action with respect to all threads, so that no thread can see a ``half-assigned'' variable. Similarly, ``vector-set!`` assigns to a vector atomically. The ``hash-table-put!`` procedure is not atomic, but the table is protected by a lock; see section 3.14 for more information. Port operations are generally not atomic, but they are thread-safe in the sense that a byte consumed by one thread from an input port will not be returned also to another thread, and procedures like ``port-commit-peeked`` (see section 11.2.1) and `write-bytes-avail` (see section 11.2.2) offer specific concurrency guarantees.

## 7.1 Suspending, Resuming, and Killing Threads

`(thread-suspend``` `thread``)` immediately suspends the execution of `thread` if it is running. If the thread has terminated or is already suspended, `thread-suspend` has no effect. The thread remains suspended (i.e., it does not execute) until it is resumed with `thread-resume`. If the current custodian (see section 9.2) does not manage `thread` (and none of its subordinates manages `thread`), the `exn:fail:contract` exception is raised, and the thread is not suspended.

`(thread-resume``` `thread``` [`thread-or-custodian`]`)` resumes the execution of `thread` if it is suspended and has at least one custodian (possibly added through `thread-or-custodian`, as described below). If the thread has terminated, or if the thread is already running and `thread-or-custodian` is not supplied, or if the thread has no custodian and `thread-or-custodian` is not supplied, then `thread-resume` has no effect. Otherwise, if `thread-or-custodian` is supplied, it triggers up to three additional actions:

- If `thread-or-custodian` is a thread, whenever it is resumed from a suspended state in the future, then `thread` is also resumed. (Resuming `thread` may trigger the resumption of other threads that were previously attached to `thread` through `thread-resume`.)

- New custodians may be added to `thread`'s set of managers. If `thread-or-custodian` is a thread, then all of the thread's custodians are added to `thread`. Otherwise, `thread-or-custodian` is a custodian, and it is added to `thread` (unless the custodian is already shut down). If `thread` becomes managed by both a custodian and one or more of its subordinates, the redundant subordinates are removed from `thread`. If `thread` is suspended and a custodian is added, then `thread` is resumed only after the addition.

- If `thread-or-custodian` is a thread, whenever it receives a new managing custodian in the future, then `thread` also receives the custodian. (Adding custodians to `thread` may trigger adding the custodians to other threads that were previously attached to `thread` through `thread-resume`.)

`(kill-thread``` `thread``)` terminates the specified thread immediately, or suspends the thread if `thread` was created with `thread/suspend-to-kill`. Terminating the main thread exits the application. If `thread` has already terminated, ``kill-thread`` does nothing. If the current custodian (see section 9.2) does not manage `thread` (and none of its subordinates manages `thread`), the `exn:fail:contract` exception is raised, and the thread is not killed or suspended.

Unless otherwise noted, procedures provided by MzScheme (and MrEd) are kill-safe and suspend-safe; that is, killing or suspending a thread never interferes with the application of procedures in other threads. For example, if a thread is killed while extracting a character from an input port, the character is either completely consumed or not consumed, and other threads can safely use the port.

`(thread/suspend-to-kill``` `thunk``)` is like `(`thread` thunk)`, except that ``killing'' the current thread through `kill-thread` or `custodian-shutdown-all` (see section 9.2) merely suspends the thread instead of terminating it.

## 7.2 Synchronizing Thread State

`(thread-wait``` `thread``)` blocks execution of the current thread until `thread` has terminated. Note that `(thread-wait (current-thread))` deadlocks the current thread, but a break can end the deadlock (if breaking is enabled; see section 6.6).

`(thread-dead-evt``` `thread``)` returns a synchronizable event (see section 7.7) that is ready if and only if `thread` has terminated. Unlike using `thread` directly, however, a reference to the event does not prevent `thread` from being ``garbage collected.''

`(thread-resume-evt``` `thread``)` returns a synchronizable event (see section 7.7) that becomes ready when `thread` is running. (If `thread` has terminated, the event never becomes ready.) If `thread` runs and is then suspended after a call to `thread-resume-evt`, the result event remains ready; after each suspend of `thread` a fresh event is generated to be returned by `thread-resume-evt`. The result of the event is `thread`, but if `thread` is never resumed, then reference to the event does not prevent `thread` from being ``garbage collected.''

`(thread-suspend-evt``` `thread``)` returns a synchronizable event (see section 7.7) that becomes ready when `thread` is suspended. (If `thread` has terminated, the event will never unblock.) If `thread` is suspended and then resumes after a call to `thread-suspend-evt`, the result event remains ready; after each resume of `thread` created a fresh event to be returned by `thread-suspend-evt`.

## 7.3 Additional Thread Utilities

`(current-thread``)` returns the thread descriptor for the currently executing thread.

`(thread?``` `v``)` returns `#t` if `v` is a thread descriptor, `#f` otherwise.

`(sleep``` [`x`]`)` causes the current thread to sleep for at least `x` seconds, where `x` is a non-negative real number. The `x` argument defaults to 0 (allowing other threads to execute when operating system threads are not used). The value of `x` can be non-integral to request a sleep duration to any precision, but the precision of the actual sleep time is unspecified.

`(thread-running?``` `thread``)` returns `#t` if `thread` has not terminated and is not suspended, `#f` otherwise.

`(thread-dead?``` `thread``)` returns `#t` if `thread` has terminated, `#f` otherwise.

`(break-thread``` `thread``)` registers a break with the specified thread. If breaking is disabled in `thread`, the break will be ignored until breaks are re-enabled (see section 6.6).

`(call-in-nested-thread``` `thunk``` [`custodian`]`)` creates a nested thread managed by `custodian` to execute `thunk`.17 The current thread blocks until `thunk` returns, and the result of the ``call-in-nested-thread`` call is the result returned by `thunk`. The default value of `custodian` is the current custodian (see section 9.2).

The nested thread's exception handler is initialized to a procedure that jumps to the beginning of the thread and transfers the exception to the original thread. The handler thus terminates the nested thread and re-raises the exception in the original thread.

If the thread created by ``call-in-nested-thread`` dies before `thunk` returns, the `exn:fail` exception is raised in the original thread. If the original thread is killed before `thunk` returns, a break is queued for the nested thread.

If a break is queued for the original thread (with ``break-thread``) while the nested thread is running, the break is redirected to the nested thread. If a break is already queued on the original thread when the nested thread is created, the break is moved to the nested thread. If a break remains queued on the nested thread when it completes, the break is moved to the original thread.

## 7.4 Semaphores

A semaphore is a value that is used to synchronize MzScheme threads. Each semaphore has an internal counter; when this counter is zero, the semaphore can block a thread's execution (through ``semaphore-wait``) until another thread increments the counter (using ``semaphore-post``). The maximum value for a semaphore's internal counter is platform-specific, but always at least 10000.

A semaphore's counter is updated in a single-threaded manner, so that semaphores can be used for reliable synchronization. Semaphore waiting is fair: if a thread is blocked on a semaphore and the semaphore's internal value is non-zero infinitely often, then the thread is eventually unblocked.

- `(make-semaphore``` [`init-k`]`)` creates and returns a new semaphore with the counter initially set to `init-k`, which defaults to `0`. If `init-k` is larger than a semaphore's maximum internal counter value, the `exn:fail:contract` exception is raised.

- `(semaphore?``` `v``)` returns `#t` if `v` is a semaphore created by ``make-semaphore``, `#f` otherwise.

- `(semaphore-post``` `sema``)` increments the semaphore's internal counter and returns void. If the semaphore's internal counter has already reached its maximum value, the `exn:fail` exception is raised.

- `(semaphore-wait``` `sema``)` blocks until the internal counter for semaphore `sema` is non-zero. When the counter is non-zero, it is decremented and ``semaphore-wait`` returns void.

- `(semaphore-try-wait?``` `sema``)` is like ``semaphore-wait``, but ``semaphore-try-wait?`` never blocks execution. If `sema`'s internal counter is zero, ``semaphore-try-wait?`` returns `#f` immediately without decrementing the counter. If `sema`'s counter is positive, it is decremented and `#t` is returned.

- `(semaphore-wait/enable-break``` `sema``)` is like ``semaphore-wait``, but breaking is enabled (see section 6.6) while waiting on `sema`. If breaking is disabled when ``semaphore-wait/enable-break`` is called, then either the semaphore's counter is decremented or the `exn:break` exception is raised, but not both.

- `(semaphore-peek-evt``` `sema``)` creates and returns a new synchronizable event (for use with ``sync``, for example) that is ready when `sema` is ready, but synchronizing the event does not decrement `sema`'s internal count.

- `(call-with-semaphore``` `sema proc``` [`try-fail-thunk arg``` `···`]`)` waits on `sema` using `semaphore-wait`, calls `proc` with all `arg`s, and then posts to `sema`. A continuation barrier blocks full continuation jumps into or out of `proc` (see section 6.3), but escape jumps are allowed, and `sema` is posted on escape. If `try-fail-thunk` is provided and is not `#f`, then ``semaphore-try-wait?`` is called on `sema` instead of `semaphore-wait`, and `try-fail-thunk` is called if the wait fails.

- `(call-with-semaphore/enable-break``` `sema proc``` [`try-fail-thunk arg``` `···`]`)` is like `call-with-semaphore`, except that `semaphore-wait/enable-break` is used with `sema` in non-try mode. When `try-fail-thunk` is provided and not `#f`, then breaks are enabled around the use of ``semaphore-try-wait?`` on `sema`.

See also ``sync`` in section 7.7.

## 7.5 Channels

A synchronous channel is a value that is used to synchronize MzScheme threads: one thread sends a value to another thread, and both the sender and the receiver block until the (atomic) transaction is complete. Multiple senders and receivers can access a channel at once, but a single sender and receiver is selected for each transaction.

Channel synchronization is fair: if a thread is blocked on a channel and transaction opportunities for the channel occur infinitely often, then the thread eventually participates in a transaction.

For buffered asynchronous channels, see Chapter 2 in PLT MzLib: Libraries Manual.

- `(make-channel``)` creates and returns a new channel. The channel can be used with `channel-get`, with `channel-try-get`, or as a synchronizable event (see section 7.7) to receive a value through the channel. The channel can be used with `channel-put` or through the result of `channel-put-evt` to send a value through the channel.

- `(channel?``` `v``)` returns `#t` if `v` is a channel created by `make-channel`, `#f` otherwise.

- `(channel-get``` `channel``)` blocks until a sender is ready to provide a value through `channel`. The result is the sent value.

- `(channel-try-get``` `channel``)` receives and returns a value from `channel` if a sender is immediately ready, otherwise returns `#f`.

- `(channel-put``` `channel v``)` blocks until a receiver is ready to accept the value `v` through `channel`. The result is void.

- `(channel-put-evt``` `channel v``)` returns a fresh synchronizable event for use with `sync` (see section 7.7). The event is ready when `(channel-put `channel` `v`)` would not block, and the event result is itself.

## 7.6 Alarms

An alarm is a synchronizable event (see section 7.7) that is ready only after particular date and time. The time is specified as a real number that is consistent with `current-inexact-milliseconds` (see section 15.1.2).

`(alarm-evt``` `msecs-n``)` returns a synchronizable event for use with `sync`. The event is not ready when `(current-inexact-milliseconds)` would return a value that is less than `msecs-n`, and it is ready when `(current-inexact-milliseconds)` would return a value that is more than `msecs-n`.

The `sync` function accepts a timeout argument in addition to alarm events. Unlike the timeout, however, the result of `alarm-evt` can be combined with `wrap-evt` and other event operations.

## 7.7 Synchronizing Events

`(sync``` `evt``` `···`1`)` blocks as long as none of the synchronizable events `evt`s are ready, as defined below. Certain kinds of objects double as events, including ports and threads, and other kinds of objects exist only for their use as events.

`(sync/timeout``` `timeout evt``` `···`1`)` is like ``sync``, but with a timeout. If no `evt` is ready before `timeout` seconds have passed, the result is `#f`. The `timeout` argument can be a real number or `#f`; if `timeout` is `#f`, then ``sync/timeout`` behaves like ``sync``. If `timeout` is `0`, each `evt` is checked at least once, so a `timeout` value of `0` can be used for polling. (See `alarm-evt` in section 7.6 for an alternative timeout mechanism.)

For either ``sync`` or ``sync/timeout``, when at least one `evt` is ready, its result (often `evt` itself) is returned. If multiple `evt`s are ready, one of the `evt`s is chosen pseudo-randomly for the result. (The `current-evt-pseudo-random-generator` parameter sets the random-number generator that controls this choice; see section 7.9.1.10.)

Choosing a ready `evt` may affect the state of `evt`. For example, if the chosen ready `evt` is a semaphore, then the semaphore's internal count is decremented, just as with ``semaphore-wait``. For most kinds of events, however (such as a port), `evt`'s state is not modified.

Only certain kinds of built-in values, listed below, act as events in stand-alone MzScheme. If any other kind of value is provided to ``sync``, the `exn:fail:contract` exception is raised. An extension or embedding application can extend the set of primitive events -- in particular, an eventspace in MrEd is an event -- and new structure types can generate events (see section 4.7).

- `semaphore` -- a semaphore is ready only when ``semaphore-wait`` (see section 7.4) would not block. The semaphore's result as an event is the semaphore itself.

- `semaphore-peek` -- a semaphore returned by `semaphore-peek-evt` applied to `semaphore` (see section 7.4) is ready exactly when `semaphore` is ready. The event's result is itself.

- `channel` -- a channel returned by `make-channel` is ready when `channel-get` would not block (see section 7.5). The channel's result as an event is the same as the `channel-get` result.

- `channel-put` -- an event returned by `channel-put-evt` applied to `channel` is ready when `channel-put` would not block on `channel` (see section 7.5). The event result is itself.

- `input-port` -- an input port is ready as an event when `read-byte` would not block. The port's result as an event is itself.

- `output-port` -- an output port is ready when `write-bytes-avail` would not block (see section 11.2.2) or when the port contains buffered characters and `write-bytes-avail*` can flush part of the buffer (although `write-bytes-avail` might block). The output port's result as an event is itself.

- `progress` -- an event produced by `port-progress-evt` applied to `input-port` is ready after any subsequent read from `input-port`. The event's result is itself.

- `tcp-listener` -- a TCP listener is ready when ``tcp-accept`` (see section 11.4.1) would not block. The listener's result as an event is itself.

- `thread` -- a thread is ready when ``thread-wait`` (see section 7.2) would not block. The thread's result as an event is itself.

- `thread-dead` -- an event returned by `thread-dead-evt` (see section 7.2) applied to `thread` is ready when `thread` has terminated. The event's result is itself.

- `thread-resume` -- an event returned by `thread-resume-evt` (see section 7.2) applied to `thread` is ready when `thread` subsequently resumes execution (if it was not already running). The event's result is `thread`.

- `thread-suspend` -- an event returned by `thread-suspend-evt` (see section 7.2) applied to `thread` is ready when `thread` subsequently suspends execution (if it was not already suspended). The event's result is `thread`.

- `alarm` -- an event returned by `alarm-evt` (see section 7.6) is ready after a particular date and time. The event's result is itself.

- `subprocess` -- a subprocess is ready when ``subprocess-wait`` (see section 15.2) would not block. The subprocess's result as an event is itself.

- `will-executor` -- a will executor is ready when ``will-execute`` (see section 13.3) would not block. The executor's result as an event is itself.

- `udp` -- an event returned by `udp-send-evt` or `udp-receive!-evt` (see section 11.4.2) is ready when a send or receive on the original socket would block, respectively. The event result is itself.

- `choice` -- an event returned by `choice-evt` (see below) is ready when one or more of the `evt`s supplied to `chocie-evt` are ready. If the choice event is chosen, one of its ready `evt`s is chosen pseudo-randomly, and the result is the chosen `evt`'s result.

- `wrap` -- an event returned by `wrap-evt` applied to `evt` and `proc` is ready when `evt` is ready. The event's result is obtained by a call to `proc` (with breaks disabled) on the result of `evt`.

- `handle` -- an event returned by `handle-evt` applied to `evt` and `proc` is ready when `evt` is ready. The event's result is obtained by a tail call to `proc` on the result of `evt`.

- `guard` -- an event returned by `guard-evt` applied to `thunk` generates a new event every time that `guard` is used with ``sync`` (or whenever it is part of a choice event used with ``sync``, etc.); the generated event is the result of calling `thunk` when the synchronization begins; if `thunk` returns a non-event, then `thunk`'s result is replaced with an event that is ready and whose result is `guard`.

- `nack-guard` -- an event returned by `nack-guard-evt` applied to `proc` generates a new event every time that `nack-guard` is used with ``sync`` (or whenever it is part of a choice event used with ``sync``, etc.); the generated event is the result of calling `proc` with a NACK (``negative acknowledgment'') event when the synchronization begins; if `proc` returns a non-event, then `proc`'s result is replaced with an event that is ready and whose result is `nack-guard-evt`.

  If the event from `proc` is not ultimately chosen as the unblocked event, then the NACK event supplied to `proc` becomes ready with a void value. This NACK event becomes ready when the event is abandoned because some other event is chosen, because the synchronizing thread is dead, or because control escaped from the call to ``sync`` (even if `nack-guard`'s `proc` has not yet returned a value). If the event returned by `proc` is chosen, then the NACK event never becomes ready.

- `poll-guard` -- an event returned by `poll-guard-evt` applied to `proc` generates a new event every time that `poll-guard` is used with ``sync`` (or whenever it is part of a choice event used with ``sync``, etc.); the generated event is the result of calling `proc` with a boolean: `#t` if the event will be used for a poll, `#f` for a blocking synchronization.

  If `#t` is supplied to `proc`, if breaks are disabled, if the polling thread is not terminated, and if polling the resulting event produces a result, the event will certainly be chosen for its result.

- `struct` -- a structure whose type has the `prop:evt` property identifies/generates an event through the property; see section 4.7 for further information.

- `always-evt` -- a constant event that is always ready. Its unblock result is itself.

- `never-evt` -- a constant event that is never ready.

`(sync/enable-break``` `evt``` `···`1`)` is like ``sync``, but breaking is enabled (see section 6.6) while waiting on the `evt`s. If breaking is disabled when ``sync/enable-break`` is called, then either all `evt`s remain unchosen or the `exn:break` exception is raised, but not both.

`(sync/timeout/enable-break``` `timeout evt``` `···`1`)` is like ``sync/enable-break``, but with a timeout in seconds (or `#f`, as for ``sync/timeout``).

`(choice-evt``` `evt``` `···``)` creates and returns a single event that combines the `evt`s. Supplying the result to ``sync`` is the same as supplying each `evt` to the same call.

`(wrap-evt``` `evt wrap-proc``)` creates an event that is in a ready when `evt` is ready, but whose result is determined by applying `wrap-proc` to the result of `evt`. The call to `wrap-proc` is `parameterize-break`ed to disable breaks initially. The `evt` cannot be an event created by `handle-evt` or any combination of `choice-evt` involving an event from `handle-evt`.

`(handle-evt``` `evt handle-proc``)` is like `wrap-evt`, except that `handle-proc` is called in tail position with respect to the synchronization request, and without breaks explicitly disabled.

`(guard-evt``` `generator-thunk``)` creates a value that behaves as an event, but that is actually an event generator. For details, see `sync`, above.

`(nack-guard-evt``` `generator-proc``)` creates a value that behaves as an event, but that is actually an event generator; the generator procedure receives an event that becomes ready with a void value if the generated event was not ultimately chosen. For details, see `sync`, above.

`(poll-guard-evt``` `generator-proc``)` creates a value that behaves as an event, but that is actually an event generator; the generator procedure receives a boolean indicating whether the event is used for polling. For details, see `sync`, above.

`always-evt` is a global constant event that is always ready, with itself as its result.

`never-evt` is a global constant event that is never ready.

`(evt?``` `v``)` returns `#t` if `v` is a synchronizable event, `#f` otherwise. See `sync`, above, for the list of built-in types that act as synchronizable events.

`(handle-evt?``` `evt``)` returns `#t` if `evt` was created by `handle-evt` or by `choice-evt` applied to another event for which `handle-evt?` produces `#t`. Such events are illegal as an argument to `handle-evt` or `wrap-evt`, because they cannot be wrapped further. For any other event, `handle-evt?` produces `#f`, and the event is a legal argument to `handle-evt` or `wrap-evt` for further wrapping.

## 7.8 Thread-Local Storage Cells

A thread cell contains a thread-specific value; that is, it contains a specific value for each thread, but it may contain different values for different threads. A thread cell is created with a default value that is used for all existing threads. When the cell's content is changed with `thread-cell-set!`, the cell's value changes only for the current thread. Similarly, `thread-cell-ref` obtains the value of the cell that is specific to the current thread.

A thread cell's value can be preserved, which means that when a new thread is created, the cell's initial value for the new thread is the same as the creating thread's current value. If a thread cell is non-preserved, then the cell's initial value for a newly created thread is the default value (which was supplied when the cell was created).

Within the current thread, the current values of all preserved threads cells can be captured through `current-preserved-thread-cell-values`. The captured set of values can be imperatively installed into the current thread through another call to `current-preserved-thread-cell-values`. The capturing and restoring threads can be different.

- `(make-thread-cell``` `v``` [`preserved?`]`)` creates and returns a new thread cell. Initially, `v` is the cell's value for all threads. If `preserved?` is true, then the cell's initial value for a newly created threads is the creating thread's value for the cell, otherwise the cell's value is initially `v` in all future threads. The default value of `preserved?` is `#f`.

- `(thread-cell?``` `v``)` returns `#t` if `v` is a thread cell created by `make-thread-cell`, `#f` otherwise.

- `(thread-cell-ref``` `cell``)` returns the current value of `cell` for the current thread.

- `(thread-cell-set!!``` `cell v``)` sets the value in `cell` to `v` for the current thread.

- `(current-preserved-thread-cell-values``` [`thread-cell-vals`]`)` when called with no arguments produces a `thread-cell-vals` that represents the current values (in the current thread) for all preserved thread cells. When called with a `thread-cell-vals` generated by a previous call to `current-preserved-thread-cell-values`, the values of all preserved thread cells (in the current thread) are set to the values captured in `thread-cell-vals`; if a preserved thread cell was created after `thread-cell-vals` was generated, then the thread cell's value for the current thread reverts to its initial value.

Examples:

    (define cnp (make-thread-cell '(nerve) #f))
    (define cp (make-thread-cell '(cancer) #t))

    (thread-cell-ref cnp) ; => '(nerve)
    (thread-cell-ref cp) ; => '(cancer)

    (thread-cell-set! cnp '(nerve nerve))
    (thread-cell-set! cp '(cancer cancer))

    (thread-cell-ref cnp) ; => '(nerve nerve)
    (thread-cell-ref cp) ; => '(cancer cancer)

    (define ch (make-channel))
    (thread (lambda ()
              (channel-put ch (thread-cell-ref cnp))
              (channel-put ch (thread-cell-ref cp))
              (channel-get ch) ; to wait
              (channel-put ch (thread-cell-ref cp))))

    (channel-get ch) ; => '(nerve)
    (channel-get ch) ; => '(cancer cancer)

    (thread-cell-set! cp '(cancer cancer cancer))

    (thread-cell-ref cp) ; => '(cancer cancer cancer)
    (channel-put ch 'ok)
    (channel-get ch) ; => '(cancer cancer)

## 7.9 Parameters

A parameter is a setting that is both thread-specific and continuation-specific, such as the current output port or the current directory for resolving relative file paths. A parameter procedure retrieves and sets the value of a specific parameter. For example, the ``current-output-port`` parameter procedure sets and retrieves a port value that is used by ``display`` when a specific output port is not provided. Applying a parameter procedure without an argument obtains the current value of a parameter in the current thread and continuation, and applying a parameter procedure to a single argument sets the parameter's value in the current thread and continuation (returning void). For example, `(current-output-port)` returns the current default output port, while `(current-output-port `p`)` sets the default output port to `p`.

In the empty continuation, each parameter corresponds to a preserved thread cell (see section 7.8); the parameter procedure accesses and sets the thread cell's value (for the current thread). To parameterize code in a continuation-friendly manner, use `parameterize`. The `parameterize` form introduces a fresh thread cell for the dynamic extent of its body expressions. The syntax of `parameterize` is:

    (parameterize ((parameter-expr value-expr) ···) body-expr ···1)

The result of a `parameterize` expression is the result of the last `body-expr`. The `parameter-expr`s determine the parameters to set, and the `value-expr`s determine the corresponding values to install while evaluating the `body-expr`s. All of the `parameter-expr`s are evaluated first (and checked with ``parameter?``), then all `value-expr`s are evaluated, and then the parameters are bound in the continuation to preserved thread cells that contain the values of the `value-expr`s. The last `body-expr` is in tail position with respect to the entire `parameterize` form.

Outside the dynamic extent of a `parameterize` expression, parameters remain bound to other thread cells. Effectively, therefore, old parameters settings are restored as control exits the `parameterize` expression.

If a continuation is captured during the evaluation of `parameterize`, invoking the continuation effectively re-introduces the parameterization. More generally, a continuation's parameter-to-thread-cell mapping is called a parameterization, and a parameterization is associated to a continuation via a continuation mark (see section 6.5) using a private key. The `current-parameterization` procedure returns the current continuation's parameterization. The `call-with-parameterization` procedure takes a parameterization and a thunk; it sets the current continuation's parameterization to the given one, and calls the thunk through a tail call.

When a new thread is created, the parameterization for the new thread's initial continuation is the parameterization of the creator thread. Since each parameter's thread cell is preserved, the new thread ``inherits'' the parameter values of its creating thread. When a continuation is moved from one thread to another, settings introduced with `parameterize` effectively move with the continuation. In contrast, direct assignment to a parameter (by calling the parameter procedure with a value) changes the value in a thread cell, and therefore changes the setting only for the current thread. (Consequently, as far as the memory manager is concerned, the value originally associated with a parameter through `parameterize` remains reachable as long the continuaton is reachable, even if the parameter is mutated.)

Examples:

    (parameterize ([exit-handler (lambda (x) 'no-exit)])
      (exit)) ; => void

    (define p1 (make-parameter 1))
    (define p2 (make-parameter 2))
    (parameterize ([p1 3]
                   [p2 (p1)])
      (cons (p1) (p2))) ; => '(3 . 1)

    (let ([k (let/cc out
               (parameterize ([p1 2])
                 (p1 3)
                 (cons (let/cc k
                         (out k))
                       (p1))))])
      (if (procedure? k)
          (k (p1))
          k)) ; =>  '(1 . 3)

    (define ch (make-channel))
    (parameterize ([p1 0])
      (thread (lambda ()
                (channel-put ch (cons (p1) (p2))))))
    (channel-get ch)  ; => '(0 . 2)

    (define k-ch (make-channel))
    (define (send-k)
      (parameterize ([p1 0])
        (thread (lambda ()
                  (let/ec esc
                    (channel-put ch
                                 ((let/cc k
                                    (channel-put k-ch k)
                                    (esc)))))))))
    (send-k)
    (thread (lambda () ((channel-get k-ch) (let ([v (p1)]) (lambda () v)))))
    (channel-get ch) ; => 1
    (send-k)
    (thread (lambda () ((channel-get k-ch) p1)))
    (channel-get ch) ; => 0

MzScheme parameters correspond to preserved thread fluids in Scsh. See also ``Processes vs. User-Level Threads in Scsh'' by Gasbichler and Sperber (proceedings of the 2002 Scheme Workshop).

### 7.9.1 Built-in Parameters

MzScheme's built-in parameter procedures are listed in the following sections. The ``make-parameter`` procedure, described in section 7.9.2, creates a new parameter and returns a corresponding parameter procedure.

#### 7.9.1.1 Current Directory

- `(current-directory``` [`path`]`)` gets or sets a path that determines the current directory. When the parameter procedure is called to set the current directory, the path argument is expanded and then simplified using ``simplify-path`` (see section 11.3.1); expansion and simplification raise an exception if the path is ill-formed. The path is not checked for existence when the parameter is set.

#### 7.9.1.2 Ports

- `(current-input-port``` [`input-port`]`)` gets or sets an input port used by ``read``, `read-byte`, ``read-char``, etc. when a specific input port is not provided.

- `(current-output-port``` [`output-port`]`)` gets or sets an output port used by ``display``, ``write``, ``print``, ``write-char``, etc. when a specific output port is not provided.

- `(current-error-port``` [`output-port`]`)` gets or sets an output port used by the default error display handler.

- `(global-port-print-handler``` [`proc`]`)` gets or sets a procedure that takes an arbitrary value and an output port. This global port print handler is called by the default port print handler (see section 11.2.7) to ``print`` values into a port.

- `(port-count-lines-enabled``` [`on?`]`)` gets or sets a boolean value that determines whether line counting is enabled automatically for newly created ports; see also section 11.2.1.1. The default value is `#f`.

#### 7.9.1.3 Parsing

- `(read-case-sensitive``` [`on?`]`)` gets or sets a boolean value that controls parsing input symbols. When this parameter's value is `#f`, the reader case-folds symbols (e.g., `hi` when the input is any one of `hi`, `Hi`, `HI`, or `hI`). The parameter also affects the way that ``write`` prints symbols containing uppercase characters; if the parameter's value is `#f`, then symbols are printed with uppercase characters quoted by a backslash (`\`) or vertical bar (|). The parameter's value is overridden by backslash and vertical-bar quotes and the `#cs` and `#ci` prefixes; see section 11.2.4 for more information. While a module is loaded, the parameter is set to `#t` (see section 5.8).

- `(read-square-bracket-as-paren``` [`on?`]`)` gets or sets a boolean value that controls whether square brackets (``['' and ``]'') are treated as parentheses. See section 11.2.4 for more information.

- `(read-curly-brace-as-paren``` [`on?`]`)` gets or sets a boolean value that controls whether curly braces (``{'' and ``}'') are treated as parentheses. See section 11.2.4 for more information.

- `(read-accept-box``` [`on?`]`)` gets or sets a boolean value that controls parsing `#\&` input. See section 11.2.4 for more information.

- `(read-accept-compiled``` [`on?`]`)` gets or sets a boolean value that controls parsing pre-compiled input. See section 11.2.4 for more information.

- `(read-accept-bar-quote``` [`on?`]`)` gets or sets a boolean value that controls parsing and printing a vertical bar (|) in symbols. See section 11.2.4 and section 11.2.5 for more information.

- `(read-accept-graph``` [`on?`]`)` gets or sets a boolean value that controls parsing input with sharing. See section 11.2.5.1 for more information.

- `(read-decimal-as-inexact``` [`on?`]`)` gets or sets a boolean value that controls parsing input numbers with a decimal point or exponent (but no explicit exactness tag). See section 11.2.5.1 for more information.

- `(read-accept-dot``` [`on?`]`)` gets or sets a boolean value that controls parsing input with a dot, which is normally used for literal cons cells. See section 11.2.4 for more information.

- `(read-accept-quasiquote``` [`on?`]`)` gets or sets a boolean value that controls parsing input with a backquote or comma, which is normally used for `quasiquote`, `unquote`, and `unquote-splicing` abbreviations. See section 11.2.4 for more information.

- `(read-accept-reader``` [`on?`]`)` gets or sets a boolean value that controls whether `#reader` is allowed for selecting a parser. See section 11.2.4 for more information.

- `(current-reader-guard``` [`proc`]`)` gets or sets a procedure of one argument that converts or rejects (by raising an exception) a module-path datum following `#reader`. See section 11.2.4 for more information.

- `(current-readtable``` [`readtable-or-false`]`)` gets or sets a readtable that adjust the parsing of S-expression input, or `#f` for the default behavior. See section 11.2.8 for more information.

#### 7.9.1.4 Printing

- `(print-unreadable``` [`on?`]`)` gets or sets a boolean value that controls printing values that have no ``read``able form (using the default reader), including structures that have a custom-write procedure (see section 11.2.10); defaults to `#t`. See section 11.2.5 for more information.

- `(print-graph``` [`on?`]`)` gets or sets a boolean value that controls printing data with sharing; defaults to `#f`. See section 11.2.5.1 for more information.

- `(print-struct``` [`on?`]`)` gets or sets a boolean value that controls printing structure values in vector form; defaults to `#f`. See section 11.2.5 for more information. This parameter has no effect on the printing of structures that have a custom-write procedure (see section 11.2.10).

- `(print-box``` [`on?`]`)` gets or sets a boolean value that controls printing box values; defaults to `#t`. See section 11.2.5 for more information.

- `(print-vector-length``` [`on?`]`)` gets or sets a boolean value that controls printing vectors; defaults to `#t`. See section 11.2.5 for more information.

- `(print-hash-table``` [`on?`]`)` gets or sets a boolean value that controls printing hash tables; defaults to `#t`. See section 11.2.5 for more information.

- `(print-honu``` [`on?`]`)` gets or sets a boolean value that controls printing values in an alternate syntax. See section 19 for more information.

#### 7.9.1.5 Read-Eval-Print

- `(current-prompt-read``` [`proc`]`)` gets or sets a procedure that takes no arguments, displays a prompt string, and returns an expression to evaluate. This prompt read handler is called by the read phase of ``read-eval-print-loop`` (see section 14.1). The default prompt read handler prints ``> '' and returns the result of

      (parameterize ((read-accept-reader #t))
        (read-syntax name-string))

  where `name-string` corresponds to the current input source.

- `(current-eval``` [`proc`]`)` gets or sets a procedure that takes an expression -- in the form of syntax object, S-expression, compiled expression, or compiled expression wrapped in a syntax object -- and returns the expression's value (or values; see section 2.2). This evaluation handler is called by ``eval``, `eval-syntax`, the default load handler, and ``read-eval-print-loop`` to evaluate an expression (see section 14.1). The default evaluation handler compiles and executes the expression in the current namespace (determined by the ``current-namespace`` parameter); if the argument is a syntax object, it is treated like an argument to `eval-syntax` and not given additional context. The default evaluation handler also partly expands expressions to splice the body of top-level `begin` forms into the top level (the compiler is called only on the individual spliced forms, and not the top-level `begin` form), and each spliced top-level form is evaluated before the next one is compiled.

- `(current-compile``` [`proc`]`)` gets or sets a procedure that takes two arguments -- a syntax object and a boolean -- and returns the compiled form of its first argument. This compilation handler is called by ``compile`` (see section 14.3), and indirectly by ``eval``, `eval-syntax`, the default load handler, and ``read-eval-print-loop`` (see section 14.1). The compilation handler's first argument has the lexical content needed for expansion and compilation. The compilation handler's second argument is `#t` if the compiled expression will be used only for immediate evaluation, or `#f` if the compiled form may be saved for later use; the default compilation handler is optimized for the special case of immediate evaluation. The result of a compilation handler must be a compiled expression (see section 14.3).

- `(current-namespace``` [`namespace`]`)` gets or sets a namespace value (see section 8) that determines the namespace used to resolve module and identifier references. The current namespace is used by the default evaluation handler, the ``compile`` procedure, and other built-in procedures that operate on ``global'' bindings.

- `(current-print``` [`proc`]`)` gets or sets a procedure that takes a value to print. This print handler is called by ``read-eval-print-loop`` (see section 14.1) to print the result of an evaluation (and the result is ignored). The default print handler ``print``s the value to the current output port (determined by the ``current-output-port`` parameter) and then outputs a newline, except that it does nothing when the value is void.

- `(compile-allow-set!-undefined` [`on?`]`)` gets or sets a boolean value indicating how to compile a `set!` expression that mutates a global variable. If the value of this parameter is a true value, `set!` expressions for global variables are compiled so that the global variable is set even if it was not previously defined. Otherwise, `set!` expressions for global variables are compiled to raise the `exn:fail:contract:variable` exception if the global variable is not defined at the time the `set!` is performed. Note that this parameter is used when an expression is compiled, not when it is evaluated.

- `(compile-enforce-module-constants``` [`on?`]`)` gets or sets a boolean value indicating how a `module` form should be compiled. When constants are enforced, and when the macro-expanded body of a module contains no `set!` assignment to a particular variable defined within the module, then the variable is marked as constant when the definition is evaluated. Afterward, the variable's value cannot be assigned or undefined through `module->namespace`, and it cannot be defined by redeclaring the module. Enforcing constants allows the compiler to inline some variable values, and it allows the native-code just-in-time compiler to generate code that skips certain run-time checks.

- `(eval-jit-enabled``` [`on?`]`)` gets or sets a boolean value that determines whether the native-code just-in-time compiler (JIT) is enabled for code (compiled or not) that is passed to the default evaluation handler. The default is `#t`, unless the JIT is disabled through the `--no-jit` or `-j` command-line flag to stand-alone MzScheme (or MrEd), or through the `PLTNOMZJIT` environment variable (set to any value).

#### 7.9.1.6 Loading

- `(current-load``` [`proc`]`)` gets or sets a procedure that loads a file and returns the value (or values; see section 2.2) of the last expression read from the file. This load handler is called by `load`, `load-relative`, `load/use-compiled`, and `load/cd`.

  A load handler procedure takes two arguments: a path (see section 11.3.1) and an expected module name. The expected module name is either a symbol or `#f`; see section 5.8 for further information.

  The default load handler reads expressions from the file (with compiled expressions enabled and line-counting enabled) and passes each expression to the current evaluation handler. The default load handler also treats a hash mark on the first line of the file as a comment (see section 11.2.4). The current load directory for loading the file is set before the load handler is called (see section 14.1).

- `(current-load-extension``` [`proc`]`)` gets or sets a procedure that loads a dynamic extension (see section 14.4) and returns the extension's value(s). This load extension handler is called by `load-extension`, `load-relative`, and `load/use-compiled`.

  A load extension handler procedure takes two arguments: a path (see section 11.3.1) and an expected module name. The expected module name is either a symbol or `#f`; see section 5.8 for further information.

  The default load extension handler loads an extension using operating system primitives.

- `(current-load/use-compiled``` [`proc`]`)` gets or sets a procedure that loads a file or a compiled version of the file; see section 14.1 for more information. A load/use-compiled handler procedure takes the same arguments as a load handler. The handler is expected to call the load handler or the load-extension handler. Unlike a load handler or load-extension handler, a load/use-compiled handler is expected to set the current `load-relative` directory.

- `(current-load-relative-directory``` [`path`]`)` gets or sets a complete directory path (see section 11.3.1) or `#f`. This current ``load-relative`` directory is set by `load`, `load-relative`, `load/use-compiled`, ``load/cd``, `load-extension`, and `load-relative-extension` to the directory of the file being loaded. This parameter is used by `load-relative`, `load/use-compiled` and `load-relative-extension` (see section 14.1). When a new path or string is provided to the parameter procedure ``current-load-relative-directory``, it is immediately expanded (see section 11.3.1) and converted to a path. (The directory need not exist.)

- `(current-write-relative-directory``` [`path`]`)` gets or sets a complete directory path (see section 11.3.1) or `#f`. This path is used when writing compiled code that contains source-location pathnames for procedures; paths within this directory (syntactically) are converted to relative paths. When compiled code is read, relative paths are converted back to complete paths using the current load-relative directory (if it is not `#f`).

- `(use-compiled-file-paths``` [`path-list`]`)` gets or sets a list of paths, which defaults to `(`list` (string->path "compiled"))`. It is used by `load/used-compiled` (and thus `require`) as a search path for compiled versions of files. See section 14.1 for more information. When a new list of paths and strings is provided to the parameter procedure, it is converted to an immutable list of paths.

- `(current-library-collection-paths``` [`path-list`]`)` gets or sets a list of complete directory paths (see section 11.3.1) for library collections used by `require`. See Chapter 16 for more information. When a new list of paths and strings is provided to the parameter procedure, it is converted to an immutable list of paths.

- `(use-user-specific-search-paths``` [`on?`]`)` gets or sets a boolean value that determines whether user-specific paths, which are in the directory produced by `(`find-system-path` 'addon-dir)`, are included in search paths for collections, C libraries, etc. For example, `find-library-collection-paths` (see section 16) omits the user-specific collection directory when this parameter's value is `#f`.

- `(current-command-line-arguments``` [`string-vector`]`)` gets or sets a vector of strings representing command-line arguments. When a new vector of strings is provided to the parameter procedure, it is converted to an immutable vector of immutable strings. The stand-alone version of MzScheme (and MrEd) initializes the parameter to contain command-line arguments that are not processed directly by MzScheme and MrEd. (The same vector is also installed as the value of the `argv` global.) If command-line arguments are provided to MzScheme/MrEd as a byte strings, they are converted to strings using the current locale's encoding (see section 1.2.2).

#### 7.9.1.7 Exceptions

- `(current-exception-handler``` [`proc`]`)` gets or sets a procedure that is invoked to handle an exception. See section 6.1 for more information about exceptions.

- `(initial-exception-handler``` [`proc`]`)` gets or sets a procedure that is used as the initial current exception handler for a new thread.

- `(error-escape-handler``` [`proc`]`)` gets or sets a procedure that takes no arguments and escapes from the dynamic context of an exception. See section 6.7 for further information about the error escape handler. The default error escape handler escapes to the start of the current thread, but ``read-eval-print-loop`` (see section 14.1) also sets the escape handler. To report a run-time error, use ``raise`` (see section 6.1) or ``error`` (see section 6.2) instead of calling the error escape procedure directly. Unlike all other parameters, the value of the ``error-escape-handler`` parameter in a new thread is not inherited from the creating thread; instead, the parameter is always initialized to the default error escape handler.

- `(error-display-handler``` [`proc`]`)` gets or sets a procedure that takes two arguments: a string to print as an error message, and a value representing a raised exception. This error display handler is called by the default exception handler with an error message and the exception value (see section 6.1). The default error display handler ``display``s its first argument to the current error port (determined by the ``current-error-port`` parameter) and extracts a stack trace (see section 6.5) to display from the second argument if it is an `exn` value but not an `exn:fail:user` value.18 To report a run-time error, use ``raise`` (see section 6.1) or procedures like ``error`` (see section 6.2) instead of calling the error display procedure directly.

- `(error-print-width``` [`k`]`)` gets or sets an exact integer greater than `3`. This value is used as the maximum number of characters used to print a Scheme value that is embedded in a primitive error message.

- `(error-print-context-length``` [`k`]`)` gets or sets a non-negative, exact integer. This value is used by the default error display handler as the maximum number of lines of context (or ``stack trace'') to print; a single ``...'' line is printed if more lines are available after the first `k` lines. A `0` value for `k` disables context printing entirely.

- `(error-value->string-handler``` [`proc`]`)` gets or sets a procedure that takes an arbitrary Scheme value and an integer and returns a string. This error value conversion handler is used to print a Scheme value that is embedded in a primitive error message. The integer argument to the handler specifies the maximum number of characters that should be used to represent the value in the resulting string. The default error value conversion handler ``print``s the value into a string;19 if the printed form is too long, the printed form is truncated and the last three characters of the return string are set to ``...''.

  If the string returned by an error value conversion handler is longer than requested, the string is destructively ``truncated'' by setting the first extra position in the string to the null character. If a non-string is returned, then the string `"..."` is used. If a primitive error string needs to be generated before the handler has returned, the default error value conversion handler is used.

  Call to an error value conversion handler are `parameterized` to re-install the default error value conversion handler, and to enable printing of unreadable values (see section 7.9.1.4).

- `(error-print-source-location``` [`include?`]`)` gets or sets a boolean that controls whether read and syntax error messages include source information, such as the source line and column or the expression. This parameter also controls the error message when a module-defined variable is accessed before its definition is executed; the parameter determines whether the message includes a module name. Only the message field of an `exn:fail:read`, `exn:fail:syntax`, or `exn:fail:contract:variable` structure is affected by the parameter. The default is `#t`.

#### 7.9.1.8 Security

- `(current-security-guard``` [`security-guard`]`)` gets or sets a security guard (see section 9.1) that controls access to the filesystem and network.

- `(current-custodian``` [`custodian`]`)` gets or sets a custodian (see section 9.2) that assumes responsibility for newly created threads, ports, TCP listeners, UDP sockets, and byte converters.

- `(current-thread-group``` [`thread-group`]`)` gets or sets a thread group (see section 9.3) that determines CPU allocation for newly created threads.

- `(current-inspector``` [`inspector`]`)` gets or sets an inspector (see section 4.5) that controls debugging access to newly created structure types.

- `(current-code-inspector``` [`inspector`]`)` gets or sets an inspector (see section 9.4) that controls debugging access to module bindings and redefinitions.

#### 7.9.1.9 Exiting

- `(exit-handler``` [`proc`]`)` gets or sets a procedure that takes a single argument. This exit handler is called by `exit`. The default exit handler takes any argument and shuts down MzScheme; see section 14.2 for information about exit codes.

#### 7.9.1.10 Random Numbers

- `(current-pseudo-random-generator``` [`generator`]`)` gets or sets a pseudo-random number generator (see section 3.3) used by `random` and `random-seed`.

- `(current-evt-pseudo-random-generator``` [`generator`]`)` gets or sets a pseudo-random number generator (see section 3.3) used by `sync` and `sync/enable-break` (see section 7.7).

#### 7.9.1.11 Locale

- `(current-locale``` [`string-or-#f`]`)` gets or sets a string/boolean value that controls the interpretation of characters for functions such as ``string-locale<?``, and `string-locale-upcase` (see section 1.2.2 and section 3.5). When locale sensitivity is disabled by setting the parameter to `#f`, strings are compared in a fully portable manner, which is the same as the standard procedures; otherwise, they are interpreted according to a locale setting (in the sense of the C library's `setlocale`). The `""` locale is always a synonym for the current machine's default locale; other locale names are platform-specific.20 String or character printing with ``write`` is not affected by the parameter, and neither are symbol case or regular expressions (see section 10). The parameter's default value is `""`.

#### 7.9.1.12 Modules

- `(current-module-name-resolver``` [`proc`]`)` gets or sets a procedure used to resolve module paths. See section 5.4 for more information.

- `(current-module-name-prefix``` [`symbol`]`)` gets or sets a symbol prefixed onto a module declaration when it is evaluated. This parameter is intended for use by a module name resolver; see section 5.4 for more information.

#### 7.9.1.13 Performance Tuning

- `(current-thread-initial-stack-size``` [`k`]`)` gets or sets a positive exact integer; the integer provides a hint about how much space to reserve for a thread's local variables. The actual space used by a computation is affected by just-in-time (JIT) compilation, but it is otherwise platform-independent.

### 7.9.2 Parameter Utilities

`(make-parameter``` `v``` [`guard-proc`]`)` returns a new parameter procedure. The value of the parameter is initialized to `v` in all threads. If `guard-proc` is supplied, it is used as the parameter's guard procedure. A guard procedure takes one argument. Whenever the parameter procedure is applied to an argument, the argument is passed on to the guard procedure. The result returned by the guard procedure is used as the new parameter value. A guard procedure can raise an exception to reject a change to the parameter's value.

`(parameter?``` `v``)` returns `#t` if `v` is a parameter procedure, `#f` otherwise.

`(parameter-procedure=?``` `a b``)` returns `#t` if the parameter procedures `a` and `b` always modify the same parameter, `#f` otherwise.

`(current-parameterization``)` returns the current continuation's parameterization.

`(call-with-parameterization``` `parameterization thunk``)` calls `thunk` (via a tail call) with `parameterization` as the current parameterization.

`(parameterization?``` `v``)` returns `#t` if `v` is a parameterization returned by `current-parameterization`, `#f` otherwise.

16 In MrEd, a handler thread for an eventspace is blocked on an internal semaphore when its event queue is empty. Thus, the handler thread is collectible when the eventspace is unreachable and contains no visible windows or running timers.

17 The nested thread's current custodian is inherited from the creating thread, independent of the `custodian` argument.

18 The default error display handler in DrScheme also uses the second argument to highlight source locations.

19 Using the current global port print handler; see section 7.9.1.2.

20 The `"C"` locale is also always available; setting the locale to `"C"` is the same as disabling locale sensitivity with `#f` only when string operations are restricted to the first 128 characters.