Thread overview
GC finalisation
Sep 20, 2005
John C
Sep 21, 2005
Russ Lewis
Sep 21, 2005
Chris Sauls
Sep 21, 2005
John C
Sep 22, 2005
James Dunne
September 20, 2005
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.


September 21, 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. 
> 
> 
September 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.
> 
>> 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?

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:

# class XYZ : IDisposable!(XYZ) {
#   public static void dispose (in XYZ obj) {
#     obj.dispose();
#     delete obj;
#   }
#
#   public this () {
#     std.gc.addRoot(...);
#   }
#
#   public void dispose () {
#     std.gc.removeRoot(...);
#   }
# }

But then the pattern is breaking down.

-- Chris Sauls
September 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.


September 22, 2005
John C wrote:
> "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. 
> 
> 
Please see my response to "Ares 0.1" in DigitalMars.Announce newsgroup.