[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: cyclic

The 'cyclic' keyword does not tell the garbage collector anything.
Literally, it just disables an error in the compiler.  Without the
'cyclic' keyword, you can define cyclic data *types* but you cannot
create cyclic *structures*.  Consider this excerpt from our current
version of draw.m:

	Image: adt
		r:      Rect;		# rectangle in data area, local coords
		clipr:  Rect;		# clipping region
		ldepth: int;		# log base 2 of number of bits per pixel
		repl:   int;		# whether data area replicates to tile the plane
		display:ref Display; # where Image resides
		screen: ref Screen;	 # nil if not window


	Display: adt
		image:	ref Image;	# holds the contents of the display
		ones:	ref Image;	# predefined mask
		zeros:	ref Image;	# predefined mask

Notice that Image contains a ref Display and Display contains a ref Image,
but no 'cyclic' is necessary.  It might seem that this would mean we could
construct a cyclic data structure, but we cannot.   If we attempt to assign
to, say, Display.image, the Limbo compiler will complain that we are
attempting to modify a field that could potentially produce a cyclic
structure.   We consider it helpful that the compiler prevents this,
because it gives the programmer guarantees that his data structures
will be freed as soon as the reference count goes to zero.

If we did want to build an explicitly circular structure, we would have
to say so, for example:

	Display: adt
		image:	cyclic ref Image;

would suppress the compiler error and permit us to build a cycle.

So the cyclic keyword does not inform the collector anything; the
collector discovers circular, unreferenced structures with no help
from the language.  Instead, the notion of 'cyclic' in the language is
a way of making intentions clear and honoring guarantees about
storage allocation and, particularly, freeing properties.