[comp.lang.clu] Garbage collection and types.

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.