auto classes and finalizers

pragma pragma_member at pathlink.com
Thu Apr 13 12:31:55 PDT 2006


In article <e1m6mo$19d$1 at digitaldaemon.com>, Bruno Medeiros says...
>
>*** The extended GC algorithm: ***
>
>delete:
>
>   m = getMemManagerHandle(obj);
>   if(m.isDeleted)
>     return;
>   if(m.isObjectInstance)
>     m.obj.destroy(); // calls ~this()
>   if(!m.isGarbageSet) // If it is not in S
>     freeMemory(m);
>
>GC:
>
>   GC determines a set S of instances to be reclaimed (garbage);
>   foreach(m in S) {
>     m.isGarbage = true;
>   }
>   foreach(m in S) {
>     delete m;
>   }
>   foreach(m in S) {
>     freeMemory(m);
>   }

Something like this will help *part* of the problem.  By delaying the freeing of
referenced memory, dynamically allocated primitives (like arrays) will continue
to function inside of class destructors.  However, this does not help with
references to objects and structs, as they may still be placed in an invalid
state by their own destructors.

/**/ class A{
/**/   public uint resource;
/**/   public this(){ resource = 42; }
/**/   public ~this(){ resource = 0; }
/**/ }
/**/ class B{
/**/   public A a;
/**/   public this(){ a = new A(); }
/**/   public ~this(){ writefln("resource: %d",a.resource); }
/**/ }

Depending on the ording in S, the program will output either "resource: 42" or
"resource: 0".  The problem only gets worse for object cycles.  I'm not saying
it won't work, but it just moves the wrinkle into a different area to be stomped
out.

Now, one way to improve this is if there were a standard method on objects that
can be checked in situations like these.  That way you'd know if another object
is finalized, or in the process of being finalized.

>   foreach(m in S) {
>     m.isFinalized = true;
>     delete m;
>   }

Now this doesn't make life any easier, but it does make things deterministic.

/**/ class A{
/**/   public uint resource;
/**/   public this(){ resource = 42; }
/**/   public ~this(){ resource = 0; }
/**/ }
/**/ class B{
/**/   public A a;
/**/   public this(){ a = new A(); }
/**/   public ~this(){ if(!a.isFinalized) writefln("resource: %d",a.resource); }
/**/ }

(another option would be something like gc.isFinalized(a), should the footprint
of Object be an issue)

Now B outputs nothing if A is finalized.  That seems like a win, but what if B
really needed that value before A went away?  In such a case, you're back to
square-one: you can't depend on the state of another referenced object within a
dtor, valid reference or otherwise.

- EricAnderton at yahoo



More information about the Digitalmars-d mailing list