Should destructors be able to tell who called them?

Steven Schveighoffer schveiguy at yahoo.com
Tue Aug 10 11:25:48 PDT 2010


One of the common problems of destructors is that they cannot assume any  
of their GC-allocated resources are valid when inside the destrutor.

The spec says:

The garbage collector is not guaranteed to run the destructor for all  
unreferenced objects. Furthermore, the order in which the garbage  
collector calls destructors for unreference objects is not specified. This  
means that when the garbage collector calls a destructor for an object of  
a class that has members that are references to garbage collected objects,  
those references may no longer be valid. This means that destructors  
cannot reference sub objects. This rule does not apply to auto objects or  
objects deleted with the DeleteExpression, as the destructor is not being  
run by the garbage collector, meaning all references are valid.

Let's analyze that last sentence (BTW, I think where it says auto, it  
should say scope).  "This does not apply to objects deleted with the  
DeleteExpression..."  Well, how the hell do you know while in the  
destructor whether you were called via delete/clear or from the GC?  You  
don't.  So the destructor *must* be written as if you are called from the  
GC, because the GC may be calling it, it is up to the user to determine  
whether your class will be destroyed via delete/clear or the GC.  So you  
must assume worst case.  Unless you declare your class as scope, which I  
don't even know if anyone does that anymore (I think it's scheduled for  
deprecation anyways).

But, what if the destructor was given an idea of whether its resources are  
valid or not?  Then you could do something different based on that input.

For example, an object that wants to open a file can do so, and in the  
destructor, use the determination of validity to decide whether to close  
the file or not.

This can be implemented by an optional parameter to the destructor that's  
always passed, but it's not necessary to use it.  i.e. you could declare  
your destructor like this:

~this(bool deterministic)
{
    if(deterministic) file.close();
}

or like this:

~this()
{
}

Scope classes (if allowed to exist) or calls to clear will set  
deterministic to true.  The GC will set it to false.

This would make destructors a lot more useful.  Thoughts?

-Steve


More information about the Digitalmars-d mailing list