The WEAK signature

A weak pointer is one that is not sufficient to keep an object live. If some object x is pointed to by ordinary pointers and by weak pointers, it will stay live (not be garbage collected); but if it is pointed to only by weak pointers, then it may be garbage collected.

As an example, suppose we want to make a "finalization" function for some data structure t. We can create a w=weak(t) and put w onto a list (of things we want to finalize). Then we can watch this list from time to time, and when strong(w)=NONE we can perform the finalization procedure. A good time to examine the list is upon receipt of the GC signal; see Signals.

The semantics of weak pointers to immutable data structures in ML is ambiguous. For example, consider the following:

let val (b',w') = 
    let val a = (1,2)
        val b = (1,2)
        val w = weak(a)
     in (b,w)
    end
 in (b, strong w)
end
After this expression is evaluated, a is both statically and dynamically dead; so one would think that the result is ((1,2),NONE). But first of all, weak pointers do not generally go dead until a garbage collection occurs, so the answer will likely be ((1,2),SOME(1,2)). Secondly, the compiler or runtime system may have done common subexpression elimination, so that a and b point to the same (1,2), and therefore w's contents may stay alive as long as b does.

Finally, in this example:

let val a = (1,2)
    val w = weak(a)
 in (a,w)
end
even though a is still alive, the compiler may have unpacked a into registers; in creating w it may box a new copy of (1,2) onto the heap, but there are no other pointers to this copy, so w's contents are immediately dead and may be reclaimed by the collector.

One way of avoiding these problems, this year, is to apply weak only to ref objects, which have a stronger notion of object identity than do ordinary records, tuples, and data constructors. This works as long as the compiler does not optimize refs too much, which at present is a safe assumption.


Synopsis

signature WEAK
structure SMLofNJ.Weak : WEAK

Interface

type 'a weak
val weak : 'a -> 'a weak
val strong : 'a weak -> 'a option
type weak'
val weak' : 'a -> weak'
val strong' : weak' -> bool

Description

type 'a weak
The type of weak pointers to objects of type 'a.

weak a
Make a weak pointer to object a.

strong w
The result is NONE if the object to which w points has already been garbage-collected; or SOME(a) if w points to some still-live object a.

type weak'
The type of opaque weak pointers to objects of type 'a; weak pointers of this type can be examined to see if the underlying objects are still alive, but the underlying objects cannot be extracted from them. This is useful to make finalizers (of heterogenous collections) statically type-check.

weak' a
Make an opaque weak pointer to a.

strong' w
Tell if the underlying object is still alive.