#
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.7), 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).

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 waitable objects through `semaphore-wait` or `semaphore-wait/enable-break` (see section 7.4), `channel-put` or `channel-get` (see section 7.5), `object-wait-multiple` or `object-wait-multiple/enable-break` (see section 7.6), or `thread-wait`.8

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

`(thread-resume``` `thread``` [`yoke-to-thread`]`)` resumes the execution of `thread` if it is suspended. If the thread has terminated, `thread-resume` has no effect. Also, if the thread is already running and `yoke-to-thread` is not supplied, `thread-resume` has no effect. If `yoke-to-thread` is supplied, it triggers two additional actions:

- The custodian managing `thread` is changed to be the youngest common superordinate of the custodians currently managing `thread` and `yoke-to-thread` (see section 9.2); the custodian is changed before resuming `thread`.

- Whenever `yoke-to-thread` is resumed from a suspended state in the future, then `thread` is also resumed. (If `thread` is both suspend and yoked to another thread, the other thread is also resumed, an so on.)

`(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. Otherwise, if the current custodian (see section 9.2) does not manage `thread` (and none of its subordinates manages `thread`), the `exn:misc` exception is raised.

All of the MzScheme (and MrEd) primitives are kill-safe and suspend-safe; that is, killing or suspending a thread never interferes with the application of primitives 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-waitable``` `thread``)` returns a waitable object (see section 7.6) that blocks until `thread` has terminated. Unlike using `thread` directly, however, reference to the waitable does not prevent `thread` from being ``garbage collected.''

`(thread-resume-waitable``` `thread``)` returns a waitable object (see section 7.6) that blocks until `thread` is running. (If `thread` has terminated, the waitable will never unblock.) If `thread` runs and is then suspended after a call to `thread-resume-waitable`, the result waitable remains unblocked; after each suspend of `thread` a fresh waitable object is generated to be returned by `thread-resume-waitable`. The unblock result of the waitable is `thread`, but if `thread` is never resumed, then reference to the waitable does not prevent `thread` from being ``garbage collected.''

`(thread-suspend-waitable``` `thread``)` returns a waitable object (see section 7.6) that blocks until `thread` is suspended. (If `thread` has terminated, the waitable will never unblock.) If `thread` is suspended and the resumes after a call to `thread-suspend-waitable`, the result waitable remains unblocked; after each resume of `thread` a fresh waitable object is generated to be returned by `thread-suspend-waitable`.

## 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`.9 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:thread` 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 arbitrarily 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:application:mismatch` 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:misc` 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.

- `(make-semaphore-peek``` `sema``)` creates and returns a new waitable object (for use with ``object-wait-multiple``, for example) that unblocks when `sema` unblocks, but does not decrement `sema`'s internal count.

See also ``object-wait-multiple`` in section 7.6.

## 7.5 Channels

A synchronous channel is a value that is used to synchronize MzScheme threads with a one-way rendevous: 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 waiting is fair: if a thread is blocked on a channel and transaction opportunities for the channel occur arbitrarily often, then the thread eventually participates in a transaction.

For buffered asynchronous channels, see Chapter mz:mzlibasync-channel 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 waitable object (see section 7.6) to receive a value through the channel. The channel can be used with `channel-put` or through the result of `make-channel-put-waitable` 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.

- `(make-channel-put-waitable``` `channel v``)` returns a fresh waitable object for use with `object-wait-multiple` (see section 7.6). The waitable blocks when `(channel-put `channel` `v`)` would block, and the unblock result is the waitable itself.

## 7.6 Synchronizing Multiple Objects with Timeout

`(object-wait-multiple``` `timeout waitable``` `···`1`)` blocks as long as all of the `waitable`s are in a blocking state, as defined below, or until `timeout` seconds have passed. The `timeout` argument can be a real number or `#f`; if `timeout` is `#f`, then ``object-wait-multiple`` does not return until some `waitable` is unblocked.

When at least one `waitable` is unblocked, its unblock result (often `waitable` itself) is returned. If multiple `waitable`s are unblocked at once, one of the `waitable`s is chosen pseudo-randomly for the result. (The `current-wait-pseudo-random-generator` parameter sets the random-number generator that controls this choice; see section 7.7.1.10.)

Choosing an unblocked `waitable` may affect the state of `waitable`. For example, if the chosen unblocked `waitable` is a semaphore, then the semaphore's internal count is decremented, just as with ``semaphore-wait``. For any other built-in kind of waitable (such as a port), `waitable`'s state is not modified.

If ``object-wait-multiple`` returns because `timeout` seconds have passed, the return value is `#f`. If the value of `timeout` is `0`, each `waitable` is checked at least once, so a `timeout` value of `0` can be used for polling.

Only certain kinds of values, listed below, are waitable in stand-alone MzScheme. If any other kind of value is provided to ``object-wait-multiple``, the `exn:application:type` exception is raised. An extension or embedding application can extend the set of waitable values. In particular, an eventspace in MrEd is waitable.

- `semaphore` -- a semaphore is in a blocking state when ``semaphore-wait`` (see section 7.4) would block. The unblock result is the semaphore itself.

- `semaphore-peek` -- a semaphore returned by `make-semaphore-peek` to `semaphore` (see section 7.4) is in in a blocking state while `semaphore` is blocking. The unblock result is the `semaphore-peek` itself.

- `input-port` -- an input port is in a blocking state when ``read-char`` would block. The unblock result is the port itself.

- `output-port` -- an output port is in a blocking state if ``write-string-avail`` would block (see section 11.2.2), unless the port contains buffered characters and ``write-string-avail*`` can flush part of the buffer (although ``write-string-avail`` might block). The unblock result is the port itself.

- `tcp-listener` -- a TCP listener is in a blocking state when ``tcp-accept`` (see section 11.4.1) would block. The unblock result is the listener itself.

- `thread` -- a thread is in a blocking state when ``thread-wait`` (see section 7.2) would block. The unblock result is the thread itself.

- `thread-dead-waitable` -- a value returned by `thread-dead-waitable` (see section 7.2) applied to `thread` is in a blocking state until `thread` has terminated. The unblock result is the waitable itself.

- `thread-resume-waitable` -- a value returned by `thread-resume-waitable` (see section 7.2) applied to `thread` is in a blocking state until `thread` subsequently resumes execution (if it was not already running). The unblock result is `thread`.

- `thread-suspend-waitable` -- a value returned by `thread-suspend-waitable` (see section 7.2) applied to `thread` is in a blocking state until `thread` subsequently suspends execution (if it was not already suspended). The unblock result is `thread`.

- `subprocess` -- a subprocess is in a blocking state when ``subprocess-wait`` (see section 15.2) would block. The unblock result is the subprocess itself.

- `will-executor` -- a will executor is in a blocking state when ``will-execute`` (see section 13.2) would block. The unblock result is the will executor itself.

- `udp-waitable` -- a value returned by `udp->send-waitble` or `udp->receive-waitable` (see section 11.4.2) is in a blocking state when a send or receive on the original socket would block, respectively. The unblock result is the waitable itself.

- `waitable-set` -- a value returned by `waitables->waitable-set` (see below) is in a blocking state when all of the `waitable`s supplied to `waitables->waitable-set` are blocking. The unblock result is the unblock result of a randomly chosen unblocked `waitable` in the set.

- `wrapped-waitable` -- a value returned by `make-wrapped-waitable` applied to `waitable` and `proc` is in a blocking state when `waitable` is blocking. The unblock result is obtained by a tail call to `proc` on the unblock result of `waitable`.

- `guard-waitable` -- a value returned by `make-guard-waitable` applied to `thunk` generates a new waitable every time that `guard-waitable` is used with ``object-wait-multiple`` (or whenever it is in a waitable set used with ``object-wait-multiple``, etc.); the generated waitable is the result of calling `thunk` when the wait begins; if `thunk` returns a non-waitable, then `thunk`'s result is replaced with a waitable value that is unblocked and whose result is `guard-waitable`.

  The waitable

- `nack-guard-waitable` -- a value returned by `make-nack-guard-waitable` applied to `proc` generates a new waitable every time that `nack-guard-waitable` is used with ``object-wait-multiple`` (or whenever it is in a waitable set used with ``object-wait-multiple``, etc.); the generated waitable is the result of calling `proc` with a NACK (``negative acknowledgement'') waitable when the wait begins; if `proc` returns a non-waitable, then `proc`'s result is replaced with a waitable value that is unblocked and whose result is `nack-guard-waitable`.

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

- `poll-guard-waitable` -- a value returned by `make-poll-guard-waitable` applied to `proc` generates a new waitable every time that `poll-guard-waitable` is used with ``object-wait-multiple`` (or whenever it is in a waitable set used with ``object-wait-multiple``, etc.); the generated waitable is the result of calling `proc` with a boolean: `#t` if the waitable will be used for a poll, `#f` for a blocking wait.

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

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

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

`(waitables->waitable-set``` `waitable``` `···``)` creates and returns a single waitable value that combines the waitable `waitable`s. Supplying the result to ``object-wait-multiple`` is the same as supplying each `waitable` to the same call.

`(make-wrapped-waitable``` `waitable convert-proc``)` creates a waitable that is in a blocking state when `waitable` is in a blocking state, but whose unblock result is determined by applying `convert-proc` to the unblock result of `waitable`.

`(make-guard-waitable``` `generator-thunk``)` creates a value that behaves as a waitable, but that is actually a waitable generator. For details, see `object-wait-multiple`, above.

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

`(make-poll-guard-waitable``` `generator-proc``)` creates a value that behaves as a waitable, but that is actually a waitable generator; the generator procedure receives a boolean indicating whether the waitable is used for polling. For details, see `object-wait-multiple`, above.

`(object-waitable?``` `v``)` returns `#t` if `v` is a waitable object, `#f` otherwise. See `object-wait-multiple`, above, for the list of waitable object types.

## 7.7 Parameters

A parameter is a thread-specific setting, such a the current output port or the current directory for resolving relative pathnames. A parameter procedure sets and retrieves 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 applying a parameter procedure to a single argument sets the parameter's value in the current thread (and returns void). For example, `(current-output-port)` returns the current default output port, while `(current-output-port `p`)` sets the default output port to `p`.

### 7.7.1 Built-in Parameters

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

#### 7.7.1.1 Current Directory

- `(current-directory``` [`path`]`)` gets or sets a string 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) and converted to an immutable string; expansion and simplification raise an exception if the path is ill-formed. Otherwise, if the given path cannot be made the current directory (e.g., because the path does not exist), the `exn:i/o:filesystem` exception is raised.

#### 7.7.1.2 Ports

- `(current-input-port``` [`input-port`]`)` gets or sets an input port used by ``read``, ``read-char``, `char-ready?`, ``read-line``, ``read-string``, and ``read-string-avail!`` 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``, and ``printf`` 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.5) 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 input ports; see also section 11.2.3. The default value is `#f`.

#### 7.7.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 downcases 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 14.3 for more information. While a module is loaded, the parameter is set to `#f` (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 14.3 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 14.3 for more information.

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

- `(read-accept-compiled``` [`on?`]`)` gets or sets a boolean value that controls parsing pre-compiled input. See section 14.3 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 14.3 and section 14.4 for more information.

- `(read-accept-graph``` [`on?`]`)` gets or sets a boolean value that controls parsing input S-expressions with sharing. See section 14.5 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 14.5 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 14.3 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 14.3 for more information.

#### 7.7.1.4 Printing

- `(print-graph``` [`on?`]`)` gets or sets a boolean value that controls printing S-expressions with sharing. See section 14.5 for more information.

- `(print-struct``` [`on?`]`)` gets or sets a boolean value that controls printing structure values. See section 14.4 for more information.

- `(print-box``` [`on?`]`)` gets or sets a boolean value that controls printing box values. See section 14.4 for more information.

- `(print-vector-length``` [`on?`]`)` gets or sets a boolean value that controls printing vectors. See section 14.4 for more information.

- `(print-hash-table``` [`on?`]`)` gets or sets a boolean value that controls printing hash tables. See section 14.4 for more information.

#### 7.7.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 `(`read-syntax` name-string)`, where `name-string` corresponds to the current input source.

- `(current-eval``` [`proc`]`)` gets or sets a procedure that takes a syntax object or S-expression and returns its value (or values; see section 2.2). This evaluation handler is called by ``eval``, 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).

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

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

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

#### 7.7.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 file path string 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 14.3). 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 loads a dynamic extension (see section 14.7) 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 file path string 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 pathname 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 pathname is provided to the parameter procedure ``current-load-relative-directory``, it is immediately expanded (see section 11.3.1) and converted to an immutable string; the result must be a complete pathname for an existing directory.

- `(use-compiled-file-kinds``` [`kind-symbol`]`)` gets or sets a symbol, either `'all` or `'none`, indicating whether `load/used-compiled` (and thus `require`) should recognize compiled files. If the value of this parameter is `'all`, then the default handler for ``load/use-compiled`` recognizes compiled files as described in section 14.1. If the value is `'none`, then the default handler for ``load/use-compiled`` ignores compiled files.

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

- `(current-command-line-arguments``` [`string-vector`]`)` gets or sets a vector of strings representing command-line arguments. The stand-alone version of MzScheme (and MrEd) initializes the parameter to contain extra command-line arguments. (The same vector is also installed as the value of the `argv` global.)

#### 7.7.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. 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. If an exception is raised while the error escape handler is executing, an error message is printed using a primitive error printer and the primitive error escape handler is invoked. 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. The default error display handler ``display``s its first argument to the current error port (determined by the ``current-error-port`` parameter), and ignores the second argument. To report a run-time error, use ``raise`` (see section 6.1) or ``error`` (see section 6.2) instead of calling the error display procedure directly. If an exception is raised while the error display handler is executing, an error message is printed using a primitive error printer and the primitive error escape handler is invoked.

- `(error-print-width``` [`k`]`)` gets or sets an 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-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 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;10 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.

- `(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. Only the message field of an `exn:read` or `exn:syntax` structure is affected by the parameter. The default is `#t`.

#### 7.7.1.8 Security

- `(break-enabled``` [`enabled?`]`)` gets or sets a boolean value that controls whether breaks are allowed. See section 6.6 for more information.

- `(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, and UDP sockets.

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

#### 7.7.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.7.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-wait-pseudo-random-generator``` [`generator`]`)` gets or sets a pseudo-random number generator (see section 3.3) used by `object-wait-multiple` and `object-wait-multiple/enable-break` (see section 7.6).

#### 7.7.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 ``char-locale<?``, ``char-locale-upcase``, and ``string-locale<?`` (see section 3.4 and section 3.5). When locale sensitivity is disabled by setting the parameter to `#f`, characters are interpreted 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.11 String and character printing with ``write`` is affected by the parameter, because unprintable characters are printed with escapes (see section 14.4). Case conversion for case-insensitive symbols and regular expression patterns (see section 10) are not affected. The parameter's default value is `""`.

#### 7.7.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.7.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.

The `parameterize` form evaluates an expression with temporarily values installed for a group of parameters. 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 before evaluating the `body-expr`s. All of the `parameter-expr`s are evaluated first (checked with ``check-parameter-procedure``), then all `value-expr`s are evaluated, and then the parameters are set.

After the `body-expr`s are evaluated, each parameter's setting is restored to its original value in the dynamic context of the `parameterize` expression. More generally, the values specified by the `value-expr`s determine initial ``remembered'' values, and whenever control jumps into or out of the `body-expr`s, the value of each parameter is swapped with the corresponding ``remembered'' value.

Examples:

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

    (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)

`(check-parameter-procedure``` `v``)` returns `v` if it is a procedure that can take both 0 arguments and 1 argument, and raises ``exn:application:type`` otherwise. The ``check-parameter-procedure`` procedure is used in the expansion of `parameterize`.

8 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 collectable when the eventspace is unreachable and contains no visible windows or running timers.

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

10 Using the current global port print handler; see section 7.7.1.2.

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