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

Classes of Waste Disposal

Michael, I hope you'll be pleased (at least amused) to know that you
just slept through a very interesting design session between Chris,
Roger, and myself; which was stimulated by your message.  Here are the

Abstract: Michael's proposal as is doesn't seem implementable.  We've
identified two interesting variations: 1) A simple scheme which we
plan to implement today which works, but doesn't give us some of the
power of Michael's scheme.  2) A simple transform of Michael's scheme
which has all its advantages and more, and which we can easily do
later.  In the interests of unblocking the critical path (Michael &
Dean), we are going to do #1.  After Michael & Dean are unblocked, we
may do #2 before First Developer Release, or may wait till Performance
Engineering Phase.  Below we document the problem with Michael's
scheme followed by both of our variations.  Michael's STACKABLE
suggestion isn't considered, I need to give it alot more thought.  By
the way Michael, it's all really neat stuff!

The problem with Michael's proposal is that the CHECKED_CLASS(Foo)
macro of a client would have to expand differently depending on Foo's
garbage collection attributes.  However, the whole point of the
CHECKED_CLASS macro is to enable clients to point at a Foo
opaquely--without having access to Foo's declaration (The analogue of
"class Foo;").  If this property of Foo changes by changing the .hxx
Foo appears in, then this change cannot affect clients which refer to
Foo opaquely.

Variation #1 (What Chris & I are implementing while you sleep):

If a class is NOT_A_TYPE, then it gets no WPTR, SPTR, or CKPTR.
Otherwise (given that it is CONCRETE or DEFERRED) it gets all three,
*independent* of it collectability status!  CHECKED_CLASS(Foo)
declares all three, and stubble provides the definitions for SPTR &
CKPTR (WPTRs don't need any definitions).

The problem of client independence doesn't appear with this scheme.
If a client declares an opaque pointer to Foo and Foo is NOT_A_TYPE,
then the client is making an error even though they can't see the
declaration of Foo.  (The error will be caught at link time because
the definition supporting SPTR(Foo) & CKPTR(Foo) will be missing.)

The cost is that the garbage collector will be led to mark objects
(like Categorys (how do you pluralize a proper noun?)) that it needn't
have bothered with.  This had better be only an efficiency issue--if
it is a correctness issue then we're screwed anyway because we can't
stop the garbage collector from getting there through a SPTR(Heaper).

A related issue which you may not be aware of: We have simplified the
class attributes for GC as follows:

AUTO_GC(Foo) -- declare markInstances & cause its definition to be
automatically generated (by stubble)

MANUAL_GC(Foo) -- do neither.  This covers both the case where I want
to write my own markInstances (in which case I also declare it
myself), and the case where I desire no markInstances.  Developers
(including us) bewarned: The procedural interface to gc will probably
change.  When this happens all MANUAL_GC classes will have to be
manually reexamined & perhaps changed!

Variation #2 (Michael's proposal transformed):

What we really have are 4 garbage collection cases which can be
arranged on a two by two matrix.  (Read on a fixed width font):


PTR in GC	Default case, all GC		Manual marking
						Example: PtrArray

PTR not GC	Michael's DONT_COLLECT		All manual
		Unsolved problem: how		Example: Category
		to tell gc it's a root

The above matrix convinced us that AUTO_GC vs MANUAL_GC really is an
orthogonal distinction from messing around with the pointer types.
Conceptually, the rows differ wrt whether the garbage collector needs
to get there by following PTRs.  The columns differ wrt what the
garbage collector should do given that it has gotten there.

The columns can be coded (as in #1) with a class attribute.  The
question is: how to code the rows so that they work with opaqueness?
(In Smalltalk, the rows would also be a class attribute (the first row
obviously being the default), which the translator will translate into
the answer to the above question.)  

The opaqueness problem results from the CHECKED_CLASS macro being
called promiscuously by all sorts of clients we have little control
over.  This way of doing CHECKED_CLASS has other problems as well.
Chris & I (a long time ago) suggested another way of arranging opaque
declarations which would solve both the old and new problems:

Given that file "foox.hxx" declares both classes Foo and Bar, the file
"foox.oxx" would read:

#ifndef FOOX_OXX
#define FOOX_OXX


#endif /* FOOX_OXX */

"foox.hxx" would now include "foox.oxx" near its top (before any of
its own declarations).  If some client module wants to refer to either
Foo or Bar opaquely, he simply includes "foox.oxx" and not "foox.hxx".
This is as opposed to the current situation where the client's header
begins with a long unreadable sequence of

#ifndef CHECKED_Foo
#define CHECKED_Foo
#endif /* CHECKED_Foo */

#ifndef CHECKED_Bar
#define CHECKED_Bar
#endif /* CHECKED_Bar */

So now each CHECKED_CLASS declaration appears only once, without all
the macro overhead, and without cluttering up the .hxx files which is
what most people will be spending their time reading (most people
won't be in Smalltalk).  Yes, I know there were some interesting
counter-arguments to this scheme, which is why we didn't do it before.
But now we have a killer reason!  It enables us to code the rows in
the matrix.  If Bar's pointers are to be the low overhead kind that
don't bother leading the garbage collector to the object they point
to, then the "foox.oxx" file can simply read:

#ifndef FOOX_OXX
#define FOOX_OXX


#endif /* FOOX_OXX */

Once we have control over the declarations that our clients-who-
view-us-opaquely see, the rest of the scheme would be as Michael

That's all folks!