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