scc@cl.cam.ac.uk (Stephen Crawley) (06/16/89)
Have you ever had one of the following problems? 1) You have designed an abstract type XXX that needs to perform some finalisation before the associated space is reclaimed. For example, your cluster internally has an open file stream that needs flushing and closing. Sadly, standard Clu does not provide any way for a cluster to perform finalisation when it is garbage collected. 2) You are trying to manage a pool of instances of some type so that you can recycle them instead of dropping them on the floor for the GC to tidy up. However, if the GC does run, you would like the GC to reclaim your pool so that the space can be used for something more important. Sadly the GC will not be able to do this because the OWN variable which is used to "hold" your pool will constitute a reference to the object. In my work, I have both of these problems and I cannot afford to brush them under the carpet. So I've come up with two new Clu types soft_ref and share_ref that can be used to solve the problem. A soft pointer to an object of type T is represented by an instance of soft_ref[T]. Conceptually the type soft_ref[T] is similar to the type oneof[value: T, broken: null]. When the GC finds a soft pointer, it looks at the object it points to. If that object has no other ordinary references to it, the GC breaks the soft_ref and collects the object it used to point to. A sharing pointer to an object of type T is represented by an instance of share_ref[T]. It is similar to the type struct[value: T, shared: bool]. The GC never breaks a share_ref type and it always treats the value as being accessible (assuming of course that the share_ref itself is accessible!). However, when the GC runs, it updates the share_ref's 'shared' flag according to whether or not there is some other ordinary reference to the value object. The application of soft_ref to problem 2) above should be obvious. In the case of problem 1), the cluster for the abstract type could keep an array of share_ref[XXX] pointers for each of the 'live' instances the type. Periodically (i.e. after each GC run) the XXX cluster would run through the array looking for share_ref's whose 'shared' flags had been set FALSE. These share_ref's would be removed from the array and the XXX cluster would perform the necessary finalisation. Below I've attached the interface spec's for soft_ref and share_ref. Implementation is messy and requires some large scale hacks to the garbage collector. If anyone is interested in some hints on how to do it, please send me email. ================================================================ soft_ref = cluster [t: type] is create, smash, is_broken, get_value, set_value rep = null create = proc (val: t) returns (cvt) end create is_broken = proc (ref: cvt) returns (bool) end is_broken smash = proc (ref: cvt) end smash get_value = proc (ref: cvt) returns (t) signals (broken) end get_value set_value = proc (ref: cvt, new_value: t) end set_value end soft_ref ================================================================ share_ref = cluster [t: type] is create, get_shared, get_value, set_value, touch rep = null create = proc (val: t) returns (cvt) end create get_shared = proc (ref: cvt) returns (bool) end get_shared get_value = proc (ref: cvt) returns (t) end get_value set_value = proc (ref: cvt, new_value: t) end set_value touch = proc (ref: cvt) end touch end share_ref
moj@cs.utu.fi (Matti Jokinen) (06/21/89)
References to related work: %A Atkins, Martin C. %A Nackman, Lee R. %T The Active Deallocation of Objects in Object-Oriented Systems %J Software - Practice & Experience %V 18 %N 11 %P 1073-1089 %D Nov 1988 %X In object-oriented systems, it is often useful for objects to be allowed to carry out some action before they are deallocated. This can be done by defining a destroy method in the object's class, and arranging for the memory system to send a message invoking this method immediately before deallocating the object. This allows resources associated with the object to be returned to the system, limited cross-language garbage collection, and other, more complex, behaviour. During the execution of the destroy method it is possible for new references to objects to be created. Care must be taken that the garbage collector does not erroneously free such objects. Algorithms are presented to implement destroy methods in systems using reference counting and mark-scan garbage collection techniques. Preperties that are desirable in such systems are also discussed. %A Jokinen, Matti O. %T Customizable Garbage Collectors %J Information Processing Letters %V 30 %N 3 %D 13 Feb 1989 %P 115-118 %X Conventional garbage collectors retain components of data structures as long as the structure itself is accessible. In some applications, however, the components of a data structure are useful only if they are referred by external pointers. Recognition and deletion of useless components requires co-operation between the garbage collector and the user program: the analysis of accessibility is carried out by the garbage collector but user-defined routines are necessary to remove obsolete components from the structure. Two different co-operation mechanisms are discussed; the first can be used with garbage collectors based on reference counters, the other with mark-and-sweep collectors.