Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!cs.utexas.edu!uunet!mcvax!kth!draken!tut!tucos!moj From: scc@cl.cam.ac.uk (Stephen Crawley) Newsgroups: comp.lang.clu Subject: Garbage collection and types. Message-ID: <788@scaup.cl.cam.ac.uk> Date: 15 Jun 89 23:46:19 GMT Sender: moj@tucos.UUCP Distribution: inet Organization: U of Cambridge Comp Lab, UK Lines: 95 Approved: moj@cs.utu.fi Source-Info: From (or Sender) name not authenticated. X-Posting-Number: 46 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