Resource Management... Howto?

Jarrett Billingsley kb3ctd2 at yahoo.com
Fri Jul 6 13:54:20 PDT 2007


"Samuel Winchenbach" <swinchen at eece.maine.edu> wrote in message 
news:f6m75n$22hh$1 at digitalmars.com...
>
> I could have something like:
> auto h = texture.loadTexture(...);
> ... use the texture ...
> texture.releaseTexture(h);
>
> and texture keeps a reference count and when it drops to zero it is 
> removed from the data structure and appropriate actions are taken to 
> release any system resources.
>
> What I would like is to not have a texture.releaseTexture().  I would like 
> that to be automatic.  Perhaps "h" could be an object with a destructor 
> that automatically calls "releaseTexture()"?   Not sure of the structure 
> of this....

You have the basic idea right.  Say one of your resource classes (for 
textures) looks like this:

class Texture
{
    private static Texture[char[]] Textures;

    public static Texture opIndex(char[] name)
    {
        if(auto tex = name in Textures)
        {
            (*tex).mRefCount++;
            return *tex;
        }

        Texture t = new Texture(name);
        Textures[name] = t;
        return t;
    }

    public static void release(Texture t)
    {
        t.mRefCount--;

        if(t.mRefCount == 0)
        {
            t.releaseResources();
            Textures.remove(t);
            delete t; // optional
        }
    }

    private int mRefCount = 1;

    private this(char[] name)
    {
        // find and load the texture
    }

    private void releaseResources()
    {
        // you know what to do here
    }
}

This way, all you have to do is write "Texture["clouds"]" and it'll look it 
up in the AA, and if it's not there, automatically load it.  Then when 
you're done, you call "Texture.release(t)" so that it can remove the texture 
from the Textures AA.  Note that every time you access the texture list with 
the static opIndex, it increments the ref count if the texture is already in 
the list, so you'll have to call .release on any ref that you get out of it.

Now comes the auto-destruction.  What you can do is make a little scope 
class which controls the destruction:

scope class TextureRef
{
    private Texture mTexture;

    public this(Texture t)
    {
        mTexture = t;
    }

    ~this()
    {
        Texture.release(t);
    }

    public Texture tex()
    {
        return mTexture;
    }
}

Then you'd use it like this:

void foo()
{
    scope t = new TextureRef(Texture["clouds"]);

    // do crap with t.tex
}

When the function leaves, t will have its destructor called, and so the 
reference count will be decremented.

Note that using scope classes can be very efficient, since when you have the 
pattern "scope x = new X", it will be allocated on the stack, and no heap 
allocation is made.  This means the TextureRef class is very lightweight.

Of course, with this layout, there's nothing binding you to using the 
TextureRef class; you can do it manually too, if you have i.e. a texture 
that needs to outlive a single function call.

auto t = Texture["clouds"];

...

Texture.release(t); 




More information about the Digitalmars-d-learn mailing list