Previous: Weak Pairs, Up: Weak References


10.7.2 Ephemerons

An ephemeron is an object with two weakly referenced components called its key and datum. The garbage collector drops an ephemeron's references to both key and datum, rendering the ephemeron broken, if and only if the garbage collector can prove that there are no strong references to the key. In other words, an ephemeron is broken when nobody else cares about its key. In particular, the datum holding a reference to the key will not in itself prevent the ephemeron from becoming broken; in contrast, See Weak Pairs. Once broken, ephemerons never cease to be broken; setting the key or datum of a broken ephemeron with set-ephemeron-key! or set-ephemeron-datum! has no effect. Note that an ephemeron's reference to its datum may be dropped even if the datum is still reachable; all that matters is whether the key is reachable.

Ephemerons are considerably heavier-weight than weak pairs, because garbage-collecting ephemerons is more complicated than garbage-collecting weak pairs. Each ephemeron needs five words of storage, rather than the two words needed by a weak pair. However, while the garbage collector spends more time on ephemerons than on other objects, the amount of time it spends on ephemerons scales linearly with the number of live ephemerons, which is how its running time scales with the total number of live objects anyway.

— procedure: ephemeron? object

Returns #t if object is a ephemeron; otherwise returns #f.

— procedure: make-ephemeron key datum

Allocates and returns a new ephemeron, with components key and datum.

— procedure: ephemeron-broken? ephemeron

Returns #t if the garbage collector has dropped ephemeron's references to its key and datum; otherwise returns #f.

— procedure: ephemeron-key ephemeron
— procedure: ephemeron-datum ephemeron

These return the key or datum component, respectively, of ephemeron. If ephemeron has been broken, these operations return #f, but they can also return #f if that is the value that was stored in the key or value component.

— procedure: set-ephemeron-key! ephemeron object
— procedure: set-ephemeron-datum! ephemeron object

These set the key or datum component, respectively, of ephemeron to object and return an unspecified result. If ephemeron is broken, neither of these operations has any effect.

Like weak-pair/car?, ephemeron-broken? must be used with care. If (ephemeron-broken? ephemeron) yields false, it guarantees only that prior evaluations of (ephemeron-key ephemeron) or (ephemeron-datum ephemeron) yielded the key or datum that was stored in the ephemeron, but it makes no guarantees about subsequent calls to ephemeron-key or ephemeron-datum: the garbage collector may run and break the ephemeron immediately after ephemeron-broken? returns. Thus, the correct idiom to fetch an ephemeron's key and datum and use them if the ephemeron is not broken is

     (let ((key (ephemeron-key ephemeron))
           (datum (ephemeron-datum ephemeron)))
       (if (ephemeron-broken? ephemeron)
           ... broken case ...
           ... code using key and datum ...))