#lang scribble/doc
@(require "mz.rkt")

@title[#:tag "memory" #:style 'toc]{Memory Management}

@local-table-of-contents[]

@section[#:tag "weakbox"]{Weak Boxes}

A @deftech{weak box} is similar to a normal box (see
@secref["boxes"]), but when the garbage collector (see
@secref["gc-model"]) can prove that the content value of a weak box is
only reachable via weak references, the content of the weak box is
replaced with @racket[#f]. A @defterm{@tech{weak reference}} is a
reference through a weak box, through a key reference in a weak hash
table (see @secref["hashtables"]), through a value in an ephemeron
where the value can be replaced by @racket[#f] (see
@secref["ephemerons"]), or through a custodian (see
@secref["custodians"]).

@defproc[(make-weak-box [v any/c]) weak-box?]{

Returns a new weak box that initially contains @racket[v].}


@defproc[(weak-box-value [weak-box weak-box?]) any]{

Returns the value contained in @racket[weak-box]. If the garbage
collector has proven that the previous content value of
@racket[weak-box] was reachable only through a weak reference, then
@racket[#f] is returned.}

@defproc[(weak-box? [v any/c]) boolean?]{

Returns @racket[#t] if @racket[v] is a weak box, @racket[#f] otherwise.}

@;------------------------------------------------------------------------
@section[#:tag "ephemerons"]{Ephemerons}

An @deftech{ephemeron} @cite{Hayes97} is a generalization of a
@tech{weak box} (see @secref["weakbox"]). Instead of just containing
one value, an ephemeron holds two values: one that is considered the
value of the ephemeron and another that is the ephemeron's key. Like
the value in a weak box, the value in an ephemeron may be replaced by
@racket[#f], but when the @emph{key} is no longer reachable (except
possibly via weak references) instead of when the value is no longer
reachable.

As long as an ephemeron's value is retained, the reference is
considered a non-weak reference. References to the key via the value
are treated specially, however, in that the reference does not
necessarily count toward the key's reachability. A @tech{weak box} can
be seen as a specialization of an ephemeron where the key and value
are the same.

One particularly common use of ephemerons is to combine them with a
weak hash table (see @secref["hashtables"]) to produce a mapping where
the memory manager can reclaim key--value pairs even when the value
refers to the key.

More precisely,
@itemize[

 @item{the value in an ephemeron is replaced
 by @racket[#f] when the automatic memory manager can prove that
 either the ephemeron or the key is reachable only through weak
 references (see @secref["weakbox"]); and}

 @item{nothing reachable from the value in an ephemeron counts toward
 the reachability of an ephemeron key (whether for the same ephemeron
 or another), unless the same value is reachable through a non-weak
 reference, or unless the value's ephemeron key is reachable through a
 non-weak reference (see @secref["weakbox"] for information on weak
 references).}

]


@defproc[(make-ephemeron [key any/c] [v any/c]) ephemeron?]{

Returns a new @tech{ephemeron} whose key is @racket[key] and whose
value is initially @racket[v].}


@defproc[(ephemeron-value [ephemeron ephemeron?]) any]{

Returns the value contained in @racket[ephemeron]. If the garbage
collector has proven that the key for @racket[ephemeron] is only
weakly reachable, then the result is @racket[#f].}


@defproc[(ephemeron? [v any/c]) boolean?]{

Returns @racket[#t] if @racket[v] is an @tech{ephemeron}, @racket[#f]
otherwise.}

@;------------------------------------------------------------------------
@section[#:tag "willexecutor"]{Wills and Executors}

A @deftech{will executor} manages a collection of values and
associated @deftech{will} procedures
(a.k.a. @deftech{finalizers}). The @tech{will} procedure for each
value is ready to be executed when the value has been proven (by the
garbage collector) to be unreachable, except through weak references
(see @secref["weakbox"]) or as the registrant for other will
executors. A @tech{will} is useful for triggering clean-up actions on
data associated with an unreachable value, such as closing a port
embedded in an object when the object is no longer used.

Calling the @racket[will-execute] or @racket[will-try-execute]
procedure executes a will that is ready in the specified will
executor. Wills are not executed automatically, because certain
programs need control to avoid race conditions. However, a program can
create a thread whose sole job is to execute wills for a particular
executor.

If a value is registered with multiple wills (in one or multiple
executors), the wills are readied in the reverse order of
registration. Since readying a will procedure makes the value
reachable again, the will must be executed and the value must be
proven again unreachable through only weak references before another
of the wills is readied or executed.  However, wills for distinct
unreachable values are readied at the same time, regardless of whether
the values are reachable from each other.

A will executor's register is held non-weakly until after the
corresponding will procedure is executed. Thus, if the content value
of a weak box (see @secref["weakbox"]) is registered with a will
executor, the weak box's content is not changed to @racket[#f] until
all wills have been executed for the value and the value has been
proven again reachable through only weak references.


@defproc[(make-will-executor) will-executor?]{

Returns a new will executor with no managed values.}


@defproc[(will-executor? [v any/c]) boolean?]{

Returns @racket[#t] if @racket[v] is a will executor, @racket[#f]
otherwise.}


@defproc[(will-register [executor will-executor?] [v any/c] [proc (any/c . -> . any)])
         void?]{

Registers the value @racket[v] with the will procedure @racket[proc]
in the will executor @racket[executor]. When @racket[v] is proven
unreachable, then the procedure @racket[proc] is ready to be called
with @racket[v] as its argument via @racket[will-execute] or
@racket[will-try-execute].  The @racket[proc] argument is strongly
referenced until the will procedure is executed.}


@defproc[(will-execute [executor will-executor?]) any]{

Invokes the will procedure for a single ``unreachable'' value
registered with the executor @racket[executor]. The values returned
by the will procedure are the result of the @racket[will-execute]
call.  If no will is ready for immediate execution,
@racket[will-execute] blocks until one is ready.}


@defproc[(will-try-execute [executor any/c]) any]{

Like @racket[will-execute] if a will is ready for immediate
execution. Otherwise, @racket[#f] is returned.}

@;------------------------------------------------------------------------
@section[#:tag "garbagecollection"]{Garbage Collection}

Set the @as-index{@envvar{PLTDISABLEGC}} environment variable (to any
value) before Racket starts to disable @tech{garbage collection}.

@defproc[(collect-garbage) void?]{

Forces an immediate @tech{garbage collection} (unless garbage
collection is disabled by setting @envvar{PLTDISABLEGC}). Some
effectively unreachable data may remain uncollected, because the
collector cannot prove that it is unreachable.

The @racket[collect-garbage] procedure provides some control over the
timing of collections, but garbage will obviously be collected even if
this procedure is never called (unless garbage collection is disabled).}

@defproc[(current-memory-use [cust custodian? #f]) exact-nonnegative-integer?]{

Returns an estimate of the number of bytes of memory occupied by
reachable data from @racket[cust].  This estimate is calculated by the
last garbage colection, and can be 0 if none occurred (or if none occurred
since the given custodian was created).  The @racket[current-memory-use]
function does @italic{not} perform a collection by itself; doing one
before the call will generally decrease the result (or increase it from
0 if no collections happened yet).

If @racket[cust] is not provided, the estimate is a total reachable from
any custodians.

When Racket is compiled without support for memory accounting, the
estimate is the same (i.e., all memory) for any individual custodian;
see also @racket[custodian-memory-accounting-available?].}

@defproc[(dump-memory-stats) any]{

Dumps information about memory usage to the (low-level) standard
output port.}
