Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 Bib Ind
[Top of Book] [Contents] [Previous Chapter] [Next Chapter]

[MathJax off]

86 Weak Pointers
86.1 Weak Pointer Objects
86.1-1 WeakPointerObj
86.2 Low Level Access Functions for Weak Pointer Objects
86.2-1 SetElmWPObj
86.3 Accessing Weak Pointer Objects as Lists
86.4 Copying Weak Pointer Objects
86.5 The GASMAN Interface for Weak Pointer Objects

### 86 Weak Pointers

This chapter describes the use of the kernel feature of weak pointers. This feature is primarily intended for use only in GAP internals, and should be used extremely carefully otherwise.

The GASMAN garbage collector is the part of the kernel that manages memory in the users workspace. It will normally only reclaim the storage used by an object when the object cannot be reached as a subobject of any GAP variable, or from any reference in the kernel. We say that any link to object \(a\) from object \(b\) "keeps object \(a\) alive", as long as \(b\) is alive. It is occasionally convenient, however, to have a link to an object which does not keep it alive, and this is a weak pointer. The most common use is in caches, and similar structures, where it is only necessary to remember how to solve problem \(x\) as long as some other link to \(x\) exists.

The following section 86.1 describes the semantics of the objects that contain weak pointers. Following sections describe the functions available to manipulate them.

#### 86.1 Weak Pointer Objects

A weak pointer object is similar to a mutable plain list, except that it does not keep its subobjects alive during a garbage collection. From the GAP viewpoint this means that its entries may become unbound, apparently spontaneously, at any time. Considerable care is therefore needed in programming with such an object.

##### 86.1-1 WeakPointerObj

`‣ WeakPointerObj`( list ) | ( function )

`WeakPointerObj` returns a weak pointer object which contains the same subobjects as the list list, that is it returns a shallow weak copy of list.

    gap> w := WeakPointerObj( [ 1, , [2,3], fail, rec( a := 1) ] );
    WeakPointerObj( [ 1, , [ 2, 3 ], fail, rec( a := 1 ) ] )

After some computations involving garbage collections (but not necessarily in the first garbage collection after the above assignment), GAP will notice that the list and the record stored in `w` are not referenced by other objects than `w`, and that therefore these entries may disappear.

    gap> GASMAN("collect");

    ... (perhaps more computations and garbage collections) ...

    gap> GASMAN("collect");
    gap> w;
    WeakPointerObj( [ 1, , , fail ] )

Note that `w` has failed to keep its list and record subobjects alive during the garbage collections. Certain subobjects, such as small integers and elements of small finite fields, are not stored in the workspace, and so are not subject to garbage collection, while certain other objects, such as the Boolean values, are always reachable from global variables or the kernel and so are never garbage collected.

Subobjects reachable without going through a weak pointer object do not evaporate, as in:

    gap> w := WeakPointerObj( [ 1, , , fail ] );
    WeakPointerObj( [ 1, , , fail ] )
    gap> l := [1,2,3];;
    gap> w[1] := l;;
    gap> w;
    WeakPointerObj( [ [ 1, 2, 3 ], , , fail ] )
    gap> GASMAN("collect");
    gap> w;
    WeakPointerObj( [ [ 1, 2, 3 ], , , fail ] )

Note also that the global variables `last`, `last2` and `last3` will keep things alive –this can be confusing when debugging.

#### 86.2 Low Level Access Functions for Weak Pointer Objects

##### 86.2-1 SetElmWPObj

`‣ SetElmWPObj`( wp, pos, val ) | ( function )

`‣ UnbindElmWPObj`( wp, pos ) | ( function )

`‣ ElmWPObj`( wp, pos ) | ( function )

`‣ IsBoundElmWPObj`( wp, pos ) | ( function )

`‣ LengthWPObj`( wp ) | ( function )

The functions `SetElmWPObj` and `UnbindElmWPObj` set and unbind entries in a weak pointer object.

The function `ElmWPObj` returns the element at position pos of the weak pointer object wp, if there is one, and `fail` otherwise. A return value of `fail` can thus arise either because (a) the value `fail` is stored at position pos, or (b) no value is stored at position pos. Since `fail` cannot vanish in a garbage collection, these two cases can safely be distinguished by a subsequent call to `IsBoundElmWPObj`, which returns `true` if there is currently a value bound at position pos of wp and `false` otherwise.

Note that it is not safe to write:

`if IsBoundElmWPObj(w,i) then x:= ElmWPObj(w,i); fi;`

and treat `x` as reliably containing a value taken from `w`, as a badly timed garbage collection could leave `x` containing `fail`. Instead use

`x := ElmWPObj(w,i); if x <> fail or IsBoundElmWPObj(w,i) then . . .`.

Here is an example.

    gap> w := WeakPointerObj( [ 1, , [2,3], fail, rec() ] );
    WeakPointerObj( [ 1, , [ 2, 3 ], fail, rec(  ) ] )
    gap> SetElmWPObj(w,5,[]);
    gap> w;
    WeakPointerObj( [ 1, , [ 2, 3 ], fail, [  ] ] )
    gap> UnbindElmWPObj(w,1);
    gap> w;
    WeakPointerObj( [ , , [ 2, 3 ], fail, [  ] ] )
    gap> ElmWPObj(w,3);
    [ 2, 3 ]
    gap> ElmWPObj(w,1);
    fail

Now after some computations and garbage collections \(\ldots\)

    gap> 2;;3;;4;;GASMAN("collect"); # clear last, last2, last3

\(\ldots\) we get the following.

    gap> ElmWPObj(w,3);
    fail
    gap> w;
    WeakPointerObj( [ , , , fail ] )
    gap> ElmWPObj(w,4);
    fail
    gap> IsBoundElmWPObj(w,3);
    false
    gap> IsBoundElmWPObj(w,4);
    true

#### 86.3 Accessing Weak Pointer Objects as Lists

Weak pointer objects are members of `ListsFamily` and the categories `IsList` (21.1-1) and `IsMutable` (12.6-2). Methods based on the low-level functions in the previous section, are installed for the list access operations, enabling them to be used as lists. However, it is not recommended that these be used in programming. They are supplied mainly as a convenience for interactive working, and may not be safe, since functions and methods for lists may assume that after `IsBound(w[i])` returns `true`, access to `w[i]` is safe.

#### 86.4 Copying Weak Pointer Objects

A `ShallowCopy` (12.7-1) method is installed, which makes a new weak pointer object containing the same objects as the original.

It is possible to apply `StructuralCopy` (12.7-2) to a weak pointer object, obtaining a new weak pointer object containing copies of the objects in the original. This may not be safe if a badly timed garbage collection occurs during copying.

Applying `Immutable` (12.6-3) to a weak pointer object produces an immutable plain list containing immutable copies of the objects contained in the weak pointer object. An immutable weak pointer object is a contradiction in terms.

#### 86.5 The GASMAN Interface for Weak Pointer Objects

The key support for weak pointers is in the files `src/gasman.c` and `src/gasman.h`. This document assumes familiarity with the rest of the operation of GASMAN. A kernel type (tnum) of bags which are intended to act as weak pointers to their subobjects must meet three conditions. Firstly, the marking function installed for that tnum must use `MarkBagWeakly` for those subbags, rather than `MARK_BAG`. Secondly, before any access to such a subbag, it must be checked with `IS_WEAK_DEAD_BAG`. If that returns `true`, then the subbag has evaporated in a recent garbage collection and must not be accessed. Typically the reference to it should be removed. Thirdly, a sweeping function must be installed for that tnum which copies the bag, removing all references to dead weakly held subbags.

The files `src/weakptr.c` and `src/weakptr.h` use this interface to support weak pointer objects. Other objects with weak behaviour could be implemented in a similar way.

[Top of Book] [Contents] [Previous Chapter] [Next Chapter]
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 Bib Ind

generated by GAPDoc2HTML