CodexArcanum
CodexArcanum

Reputation: 4016

The proper and clear way to manage external resources in D with Derelict and SDL

I'm following through an SDL tutorial series (written in C++) using Derelict and D. So far the conversion has been simple, but one element of the tutorial writers style bothers me and I've been trying to figure out the best way around it. But my knowledge of D isn't the best, so I'm not sure hwo to handle this.

Essentially, to use SDL, I must load image files into memory as SDL_Surfaces. Before the program exits, these surfaces need to be manually freed using SDL_FreeSurface(). This seems like an ideal case for scope(exit) and indeed it does work very well... for loading and unloading resources in the span of a single function. But ideally I'd split all that up so that one function handles the loading and then somewhere else another function frees them. And then beyond that maybe each resource just handles itself. I guess that's RAII but I don't really understand how to use it in D.

I thought you just set up a new class to carry the resource, load it in this() and free it in ~this() but it seems I read that the destructor isn't guaranteed to be called unless you instance the class as scope. I could use a struct I guess, but it seems like I'd be missing out on useful benefits of classes if I did.

What I want is to load resources and get guarantees about them being freed, but to do so in a sane manner that doesn't require me putting all loading and unloading into one huge method. How should I approach this?

Upvotes: 2

Views: 262

Answers (2)

eco
eco

Reputation: 2229

If all you want is to automatically free the SDL_Surface you should just wrap SDL_Surface in a struct and take advantage of RAII. It's a good fit for this type of thing. Just be sure to disable postblit to avoid double freeing or implement reference counting.

struct SurfaceRAII
{
    this(SDL_Surface* surf_handle)
    {
        m_handle = surf_handle;
    }

    // disable default constructor and postblit (no copies)
    @disable this();
    @disable this(this);

    ~this()
    {
        SDL_FreeSurface(m_handle);
    }

    public SDL_Surface* m_handle;
}

Untested but that's the general idea.

Edit: You could also use std.typecons.RefCounted on a class if you'd prefer.

Upvotes: 2

Vladimir Panteleev
Vladimir Panteleev

Reputation: 25187

I'm fairly sure that - at least on platforms featuring an operating system with multitasking - you don't need to worry about clean-up when your application exits.

Alternatively, you could simply store said resources in a global set.

Upvotes: 3

Related Questions