What's the use case of clear?

Steven Schveighoffer schveiguy at yahoo.com
Tue Aug 10 08:09:13 PDT 2010


On Tue, 10 Aug 2010 10:49:16 -0400, django  
<django at thisinotmyrealemail.com> wrote:

> I read the recent discussion on the subject (TDPL: Manual invocation of
> destructor) but I still don't understand what is the use case clear()  
> wants to
> cover?
>
> Assume for a moment that we have this class:
>
> class Connection {
> 	this() { connect(); }
> 	~this() { if (connected) disconnect(); }
> 	void disconnect() { ... }
> 	...
> }
>
> Now I see the following use cases:
>
> // The connection is closed at some later point if at all.
> var c1 = new Connection;
>
>
> // I want the connection closed at the end of the function.
> // Should be safe everytime.
> void foo() {
> 	var c2 = new Connection;
> 	scope(exit) c2.disconnect();
> 	...
> }
>
>
> // I want the connection closed and memory released.
> // (I know what I'm doing)
> void bar() {
> 	var c2 = new Connection;
> 	scope(exit) {
> 		c2.disconnect();	// Even better, call the constructor.
> 		GC.free(c2);
> 	}
> 	...
> }
>
> What's left for clear()? In which scenario would I like the default
> constructor called again?

None.  Why would you call the constructor again?  I think that's the point  
of the discussion.

But we should clarify a couple things.  First, destructors are *only*  
valid for releasing resources not allocated by the GC.  For example, in  
your Connection object, if you used a phobos object to make the  
connection, and allocated that connection via new, then you are *not*  
guaranteed that the GC hasn't collected that object already.  So it is not  
valid in the destructor.

But if your connection is implemented via something like OS calls/handles,  
then you must release in the destructor.

So the idea is, in order for this object to be properly reclaimed during  
the GC collection cycle, it must release the resource in the destructor.   
If the validity of the object is directly dependent on the resource, then  
what clear allows you to do is to have a standard way of reclaiming these  
resources without having to define a separate function.  It also takes the  
place of delete, which is a very unsafe way of doing the same thing.

The case which clear doesn't handle very well is releasing of GC resources.

For example, this class would be invalid:

class X
{
}

class C
{
    X x;
    this() { x = new X;}
    ~this() { clear(x);}
}

because the GC may have already deallocated x before deallocating the  
parent class.

One way to fix this is to have the storage for x be in the same memory  
block as C.  But this concept has not been implemented (I think it's a  
planned feature).  Then you can be sure that the memory for x is stored  
inside the C instance.  You can also be sure that the GC won't destroy the  
C if there are still references to its X, but not any references to the C  
itself.

-Steve


More information about the Digitalmars-d mailing list