GC for noobs

Remo remo4d at gmail.com
Thu Feb 27 05:18:50 PST 2014


On Thursday, 27 February 2014 at 13:07:37 UTC, Mike Parker wrote:
> On 2/27/2014 9:25 PM, Szymon Gatner wrote:
>
>>
>> This is just an example but I would think that it is something 
>> rather
>> important to have... What about child objects un-registering 
>> themselves
>> in d-tors from a list that parent object holds and parent is 
>> destroyed
>> first? What about asynchronous completion handler object that 
>> should
>> notify some other object that it finished/not finished a job 
>> but a
>> notifee is already destroyed because application is being 
>> shut-down? I
>> honestly can't imagine how to reason about object graph 
>> lifetimes in GC
>> world and I am sure I am missing something very basic. 
>> Probably a very
>> different mindset.
>>
>
> Two simple rules I follow.
>
> #1 Never rely on class destructors for determinstic clean up
> #2 Never rely on class destructors for releasing system 
> resources
>
> I tend to add two methods to classes that need to do any sort 
> of set up and clean up: initialize and terminate. Then, at app 
> exit, I make sure that the terminate methods are called either 
> with scope(exit) or, if I want to log any exceptions that 
> percolate up to main, try-catch-finally. Something like this:
>
> class TextureManager {
>    private TexContainer _loadedTextures;
>    public void initialize() {...}
>    public void terminate() {
>       foreach( tex; _loadedTextures[])
>           tex.terminate();
>    }
> }
>
> struct Game {
>     @disable this();
>     @disable this( this );
>
>     private static TextureManager _texMan;
>
>     public static void initialize() {
>        _texMan = new TextureManager();
>        _texMan.initialize();
>     }
>     public static void terminate() {
>         _texMan.terminate();
>     }
> }
>
> void main() {
>    scope( exit ) Game.terminate();
>    Game.initialize();
> }
>
> In some parts of a system, for objects that tend to be short 
> lived, I'll use structs with destructors for RAII. A good 
> example of this is for vertex and fragment shaders. The shader 
> programs are long-lived, so those are classes, but I always 
> destroy the shader objects as soon as any programs that need 
> them are built. So those are perfect candidates for the 
> struct-based RAII approach.
>
> RAII is a convenient tool, but it's just that, a tool. One of 
> the tradeoffs you have to make with D's GC is that you can't 
> use RAII the same way you do in C++. You *can* use it with 
> structs, but for classes you're going to have to put C++ out of 
> your head.


Then the question is why not use structs all the time?
After using D for a bit more as a week I come to the solution 
that looks like this.

strict WasAClassInCpp
{
    @disable this(); //sadly we can not use ctor in D like in C++ 
:(
    @disable this(this); //this is not a copy constructor, this is 
something called after all the data in the struct was copied...

   ~this(){ ... }  //dtor, just like in C++
}

So all my classes in C++ are ported to D structs.
I was using class only to port abstract class from C++.
Replacing it by inerface.


More information about the Digitalmars-d-learn mailing list