14.7 Custodians

► |  | The Racket Reference

1 | Language Model
2 | Notation for Documentation
3 | Syntactic Forms
4 | Datatypes
5 | Structures
6 | Classes and Objects
7 | Units
8 | Contracts
9 | Pattern Matching
10 | Control Flow
11 | Concurrency and Parallelism
12 | Macros
13 | Input and Output
14 | Reflection and Security
15 | Operating System
16 | Memory Management
17 | Unsafe Operations
18 | Running Racket
| Bibliography
| Index

▼ | 14 | Reflection and Security

14.1 | Namespaces
14.2 | Evaluation and Compilation
14.3 | The racket/ load Language
14.4 | Module Names and Loading
14.5 | Impersonators and Chaperones
14.6 | Security Guards
14.7 | Custodians
14.8 | Thread Groups
14.9 | Structure Inspectors
14.10 | Code Inspectors
14.11 | Plumbers
14.12 | Sandboxed Evaluation
14.13 | The racket/ repl Library
14.14 | Linklets and the Core Compiler

On this page:

custodian?
make-custodian
custodian-shutdown-all
custodian-shut-down?
current-custodian
custodian-managed-list
custodian-memory-accounting-available?
custodian-require-memory
custodian-limit-memory
make-custodian-box
custodian-box?
custodian-box-value

top contents ← prev up next →

#### 14.7`` Custodians🔗ℹ

See Custodians for basic information on the Racket custodian model.

> procedure (custodian? v) → boolean?
> v : any/c

Returns #t if v is a custodian value, #f otherwise.

> procedure (make-custodian [cust]) → custodian?
> | cust |  | : |  | (and/c custodian? (not/c custodian-shut-down?))
> |  |  | = |  | (current-custodian)

Creates a new custodian that is subordinate to cust. When cust is directed (via custodian-shutdown-all) to shut down all of its managed values, the new subordinate custodian is automatically directed to shut down its managed values as well.

> procedure (custodian-shutdown-all cust) → void?
> cust : custodian?

> > > In racket/gui/base, eventspaces managed by cust are also shut down.

Closes all file-stream ports, TCP ports, TCP listeners, and UDP sockets that are managed by cust (and its subordinates), and empties all custodian boxes associated with cust (and its subordinates). It also removes cust (and its subordinates) as managers of all threads; when a thread has no managers, it is killed (or suspended; see thread/suspend-to-kill) If the current thread is to be killed, all other shut-down actions take place before killing the thread.

If cust is already shut down, then custodian-shutdown-all has no effect. When a custodian is shut down and it has subordinate custodians, the subordinates are not only shut down, they no longer count as subordinates.

> procedure (custodian-shut-down? cust) → boolean?
> cust : custodian?

Returns #t if cust has been shut down with custodian-shutdown-all or if it was a subordinate of a custodian that is shut down, #f otherwise.

Added in version 6.11.0.5 of package base.

> parameter (current-custodian) → custodian?
> (current-custodian cust) → void?
> cust : custodian?

> > > Custodians also manage eventspaces from racket/gui/base.

A parameter that determines a custodian that assumes responsibility for newly created threads, file-stream ports, TCP ports, TCP listeners, UDP sockets, and byte converters.

> procedure (custodian-managed-list cust super) → list?
> cust : custodian?
> super : custodian?

Returns a list of immediately managed objects (not including custodian boxes) and subordinate custodians for cust, where cust is itself subordinate to super (directly or indirectly). If cust is not strictly subordinate to super, the exn:fail:contract exception is raised.

If cust has been shut down, the result is '(). If cust was a subordinate of a custodian that was shut down, then it cannot be a subordinate of super.

> procedure (custodian-memory-accounting-available?) → boolean?

> > > Memory accounting is normally available, but not in the CGC implementation.

Returns #t if Racket is compiled with support for per-custodian memory accounting, #f otherwise.

> > procedure
> > (custodian-require-memory |  | limit-cust |  |  |  |
> > |  | need-amt |  |  |  |
> > |  | stop-cust) |  | → |  | void?
> limit-cust : custodian?
> need-amt : exact-nonnegative-integer?
> stop-cust : custodian?

Registers a required-memory check if Racket is compiled with support for per-custodian memory accounting, otherwise the exn:fail:unsupported exception is raised.

If a check is registered, and if Racket later reaches a state after garbage collection (see Garbage Collection) where allocating need-amt bytes charged to limit-cust would fail or trigger some shutdown, then stop-cust is shut down.

The stop-cust must be a subordinate custodian of limit-cust.

> > procedure
> > (custodian-limit-memory |  | limit-cust |  |  |  |
> > |  | limit-amt |  |  |  |
> > | [ | stop-cust]) |  | → |  | void?
> limit-cust : custodian?
> limit-amt : exact-nonnegative-integer?
> stop-cust : custodian? = limit-cust

Registers a limited-memory check if Racket is compiled with support for per-custodian memory accounting, otherwise the exn:fail:unsupported exception is raised.

If a check is registered, and if Racket later reaches a state after garbage collection (see Garbage Collection) where limit-cust owns more than limit-amt bytes, then stop-cust is shut down.

> > > A custodian’s limit is checked only after a garbage collection, except that it may also be checked during certain large allocations that are individually larger than the custodian’s limit. A single garbage collection may shut down multiple custodians, even if shutting down only one of the custodians would have reduced memory use for other custodians.

For reliable shutdown, limit-amt for custodian-limit-memory must be much lower than the total amount of memory available (minus the size of memory that is potentially used and not charged to limit-cust). Moreover, if individual allocations that are initially charged to limit-cust can be arbitrarily large, then stop-cust must be the same as limit-cust, so that excessively large immediate allocations can be rejected with an exn:fail:out-of-memory exception.

> > > New memory allocation will be accounted to the running thread’s managing custodian. In other words, a custodian’s limit applies only to the allocation made by the threads that it manages. See also call-in-nested-thread for a simpler setup.

Examples:

> > (require racket/async-channel)
> > (define ch (make-async-channel))
> > (parameterize ([current-custodian (make-custodian)])
> (thread-wait
> (thread
> (λ ()
> (with-handlers ([exn:fail:out-of-memory?
> (λ (e) (async-channel-put ch e))])
> (custodian-limit-memory (current-custodian) (* 1024 1024))
> (make-bytes (* 4 1024 1024))
> (async-channel-put ch "Not OK")))))
> (async-channel-get ch))
> (exn:fail:out-of-memory "out of memory" #<continuation-mark-set>)
> > (define cust (make-custodian))
> > (with-handlers ([exn:fail:out-of-memory?
> (λ (e) (error "Caught OOM exn"))])
> (call-in-nested-thread
> (λ ()
> (custodian-limit-memory cust (* 1024 1024))
> (make-bytes (* 4 1024 1024))
> "Not OK")
> cust))
> Caught OOM exn

Non-examples:

> > (parameterize ([current-custodian (make-custodian)])
> (custodian-limit-memory (current-custodian) (* 1024 1024))
> ; Allocation of make-bytes is charged to the current thread’s
> ; managing custodian, not the new custodian.
> (make-bytes (* 4 1024 1024))
> "Not OK")
> "Not OK"

> procedure (make-custodian-box cust v) → custodian-box?
> cust : custodian?
> v : any/c

Returns a custodian box that contains v as long as cust has not been shut down. If cust is already shut down, the custodian box’s value is immediately removed.

A custodian box is a synchronizable event (see Events). The custodian box becomes ready when its custodian is shut down; the synchronization result of a custodian box is the custodian box itself.

> procedure (custodian-box? v) → boolean?
> v : any/c

Returns #t if v is a custodian box produced by make-custodian-box, #f otherwise.

> procedure (custodian-box-value cb) → any
> cb : custodian-box?

Returns the value in the given custodian box, or #f if the value has been removed.
top contents ← prev up next →