digitalmars.D.learn - GC finalisation
- John C (30/30) Sep 20 2005 I'm using a disposable pattern on objects that free system resources. On...
- Russ Lewis (8/47) Sep 21 2005 As I understand it, addRoot() means that the object will never be seen
- Chris Sauls (20/35) Sep 21 2005 It is an issue, but could his XYZ.dispose() method call std.gc.removeRoo...
- John C (4/11) Sep 21 2005 Best to abandon the idea, then. I'l try my original idea of keeping trac...
- James Dunne (2/19) Sep 22 2005 Please see my response to "Ares 0.1" in DigitalMars.Announce newsgroup.
I'm using a disposable pattern on objects that free system resources. One reason for this is that you may want to free a class's resources yet keep the object itself alive. The interface is as follows: interface IDisposable { void dispose(); } A class typically implements the interface like this: class SomeObjectHoldingResources : IDisposable { void dispose() { // free all resources } ~this() { // dispose should run on finalisation because it may not have been called explicitly dispose(); } } As you can see with this design, the dispose method could get called twice: once by an explicit call, and by the destructor when the GC collects. To prevent this, I could maintain a state tracking whether dispose() has been called and only run it from the destructor if the state is 0. However, I was wondering if we might be able to tell the GC not to run the destructor in certain cases. I'm looking for something similar to .NET's GC.SuppressFinalizer() and std.gc.addRoot() seems to be what I'm after, and indeed calling this after the first dispose() appears to work - that is, it prevents the GC from running ~this(). My question is this: is this a safe thing to do? I've not encountered any issues as yet but are there any side-effects such as leaks? Is there another way to accomplish this? Thanks.
Sep 20 2005
As I understand it, addRoot() means that the object will never be seen as garbage; it will always be considered live. Thus, you are not only preventing the destructor from running, you are also preventing that memory from ever being reclaimed. Unless you plan for that object to live forever anyway, then yes, you will have a memory leak. And of course, if this object points to anything else, then the memory leak gets even worse. John C wrote:I'm using a disposable pattern on objects that free system resources. One reason for this is that you may want to free a class's resources yet keep the object itself alive. The interface is as follows: interface IDisposable { void dispose(); } A class typically implements the interface like this: class SomeObjectHoldingResources : IDisposable { void dispose() { // free all resources } ~this() { // dispose should run on finalisation because it may not have been called explicitly dispose(); } } As you can see with this design, the dispose method could get called twice: once by an explicit call, and by the destructor when the GC collects. To prevent this, I could maintain a state tracking whether dispose() has been called and only run it from the destructor if the state is 0. However, I was wondering if we might be able to tell the GC not to run the destructor in certain cases. I'm looking for something similar to .NET's GC.SuppressFinalizer() and std.gc.addRoot() seems to be what I'm after, and indeed calling this after the first dispose() appears to work - that is, it prevents the GC from running ~this(). My question is this: is this a safe thing to do? I've not encountered any issues as yet but are there any side-effects such as leaks? Is there another way to accomplish this? Thanks.
Sep 21 2005
Russ Lewis wrote:As I understand it, addRoot() means that the object will never be seen as garbage; it will always be considered live. Thus, you are not only preventing the destructor from running, you are also preventing that memory from ever being reclaimed. Unless you plan for that object to live forever anyway, then yes, you will have a memory leak.It is an issue, but could his XYZ.dispose() method call std.gc.removeRoot()? And maybe it would be best to indirectly call the dispose method from a static overload. Aka, something like this: But then the pattern is breaking down. -- Chris SaulsHowever, I was wondering if we might be able to tell the GC not to run the destructor in certain cases. I'm looking for something similar to .NET's GC.SuppressFinalizer() and std.gc.addRoot() seems to be what I'm after, and indeed calling this after the first dispose() appears to work - that is, it prevents the GC from running ~this(). My question is this: is this a safe thing to do? I've not encountered any issues as yet but are there any side-effects such as leaks? Is there another way to accomplish this?
Sep 21 2005
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:dgs3ub$18rk$1 digitaldaemon.com...As I understand it, addRoot() means that the object will never be seen as garbage; it will always be considered live. Thus, you are not only preventing the destructor from running, you are also preventing that memory from ever being reclaimed. Unless you plan for that object to live forever anyway, then yes, you will have a memory leak. And of course, if this object points to anything else, then the memory leak gets even worse.Best to abandon the idea, then. I'l try my original idea of keeping track of the object's disposed state.
Sep 21 2005
John C wrote:"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:dgs3ub$18rk$1 digitaldaemon.com...Please see my response to "Ares 0.1" in DigitalMars.Announce newsgroup.As I understand it, addRoot() means that the object will never be seen as garbage; it will always be considered live. Thus, you are not only preventing the destructor from running, you are also preventing that memory from ever being reclaimed. Unless you plan for that object to live forever anyway, then yes, you will have a memory leak. And of course, if this object points to anything else, then the memory leak gets even worse.Best to abandon the idea, then. I'l try my original idea of keeping track of the object's disposed state.
Sep 22 2005