auto classes and finalizers
Bruno Medeiros
brunodomedeirosATgmail at SPAM.com
Fri Apr 14 08:44:28 PDT 2006
pragma wrote:
> 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.
>
True, I forgot to mention that. The order of destruction is undefined,
so it will only work with objects where that order doesn't matter. (that
should be the case with most)
> 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
Exactly, you can't really solve the order/state problem with this. I
think the only way to do it is to manually memory manage the member
objects (with a construct such as mmnew or otherwise).
--
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
More information about the Digitalmars-d
mailing list