Thread overview | ||||||
---|---|---|---|---|---|---|
|
August 18, 2004 issue with calling destructors from GC | ||||
---|---|---|---|---|
| ||||
I have a question about calling destructors from the GC - in particular at the program exit. I'm fixing some bugs in std.stream and one of the things I'm doing is adding a destructor for BufferedStream that closes the source stream. The problem is that when the GC runs the source stream can be destroyed before the buffered stream's destructor runs. So I end up trying to reference an object that has been destroyed. Is there some way I can tell if an object is still valid - or somehow control the order in which the GC runs the destructors? -Ben |
August 18, 2004 Re: issue with calling destructors from GC | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | I should probably add that a fallback position is to have the buffered stream's destructor print a warning to stderr if the stream is still open and the buffer is non-empty. This isn't so bad IMO since managing non-memory resources though garbage collection is problematic in any case - the least of which is that the destructor may never run. Failing to close the buffered stream could mean the final buffered content is never written to the source stream, but at least a warning to stderr would alert users to the problem. -Ben "Ben Hinkle" <bhinkle4@juno.com> wrote in message news:cg02ss$4fp$1@digitaldaemon.com... > I have a question about calling destructors from the GC - in particular at the program exit. I'm fixing some bugs in std.stream and one of the things I'm doing is adding a destructor for BufferedStream that closes the source stream. The problem is that when the GC runs the source stream can be destroyed before the buffered stream's destructor runs. So I end up trying to reference an object that has been destroyed. Is there some way I can tell if an object is still valid - or somehow control the order in which the GC runs the destructors? > > -Ben |
August 18, 2004 Re: issue with calling destructors from GC | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | Ben Hinkle wrote: > I have a question about calling destructors from the GC - in particular at > the program exit. I'm fixing some bugs in std.stream and one of the things > I'm doing is adding a destructor for BufferedStream that closes the source > stream. The problem is that when the GC runs the source stream can be > destroyed before the buffered stream's destructor runs. So I end up trying > to reference an object that has been destroyed. Is there some way I can > tell if an object is still valid - or somehow control the order in which > the GC runs the destructors? AFAIK, the GC doesn't let you control in what order things are destructed. However, if you care about order, here's a way to make sure things appen in order. Basically, the concept is that you have to keep a global list of references to the objects that you want to clean up last. This global list prevents those objects from being garbage. When the other object is cleaned up, you remove this reference in your destructor. Thus, the former object only becomes garbage after you've cleaned up. class Used {} class User { static Object destructionOrderingArray_syncObj; static int[Used] destructionOrderingArray; static this() { destructionOrderingArray_syncObj = new Object; } void removeFromOrderingArray(Used u) { assert(u in destructionOrderingArray); destructionOrderingArray[u]--; if(destructionOrderingArray[u] == 0) delete /*from array*/ destructionOrderingArray[u]; } void addToOrderingArray(Used u) { if(u in destructionOrderingArray) destructionOrderingArray[u]++; else destructionOrderingArray[u] = 1; } Used _myUsed; void used(Used u) { // settor property if(u === _myUsed) return; synchronized(destructionOrderingArray_syncObj) { if(_myUsed !== null) removeFromOrderingArray(_myUsed); addToOrderingArray(_myUsed); } _myUsed = used; } Used used() { // gettor property return _myUsed; } ~this() { if(_myUsed !== null) removeFromOrderingArray(_myUsed); } } |
August 18, 2004 Re: issue with calling destructors from GC | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russ Lewis | Russ Lewis wrote:
> Ben Hinkle wrote:
>
>> I have a question about calling destructors from the GC - in particular at
>> the program exit. I'm fixing some bugs in std.stream and one of the things
>> I'm doing is adding a destructor for BufferedStream that closes the source
>> stream. The problem is that when the GC runs the source stream can be
>> destroyed before the buffered stream's destructor runs. So I end up trying
>> to reference an object that has been destroyed. Is there some way I can
>> tell if an object is still valid - or somehow control the order in which
>> the GC runs the destructors?
>
>
> AFAIK, the GC doesn't let you control in what order things are destructed. However, if you care about order, here's a way to make sure things appen in order. Basically, the concept is that you have to keep a global list of references to the objects that you want to clean up last. This global list prevents those objects from being garbage. When the other object is cleaned up, you remove this reference in your destructor. Thus, the former object only becomes garbage after you've cleaned up.
>
The thing is that GC is essentially nondeterministic, and efforts to
make it deterministic only cause the language implementation to become
very complex--and worse, it invites people to try to out-think the
GC. If you accept that the GC is nondeterministic then there are ways
to deal with it.
So, if you call delete on a deleted object would an exception be thrown,
or would the system ignore the extraneous call to delete? This would
allow the BufferedStream to delete the underlying stream (and if written
correctly consequently release the resources held by it), and do nothing
if the underlying stream has been collected.
|
Copyright © 1999-2021 by the D Language Foundation