Правильный и понятный способ управления внешними ресурсами в D с помощью Derelict и SDL - PullRequest
2 голосов
/ 22 декабря 2011

Я просматриваю серию учебных пособий по SDL (написанных на C ++), используя Derelict и D. До сих пор преобразование было простым, но один элемент стиля авторов учебных пособий беспокоит меня, и я пытался выяснить, лучший способ обойти это. Но мои знания D не самые лучшие, поэтому я не уверен, что справлюсь с этим.

По сути, чтобы использовать SDL, я должен загружать файлы изображений в память как SDL_Surfaces. Перед выходом из программы эти поверхности необходимо вручную освободить с помощью SDL_FreeSurface (). Это кажется идеальным случаем для scope(exit) и действительно работает очень хорошо ... для загрузки и выгрузки ресурсов в пределах одной функции. Но в идеале я бы разделил все это так, чтобы одна функция обрабатывала загрузку, а затем где-то другая функция освобождала их. И, кроме того, возможно, каждый ресурс обрабатывает сам себя. Я думаю, что это RAII, но я не совсем понимаю, как использовать его в D.

Я думал, что вы просто создали новый класс для переноса ресурса, загрузили его в this() и освободили его в ~this(), но, кажется, я прочитал, что деструктор не гарантированно будет вызван, если вы не создадите экземпляр класса как scope. Я мог бы использовать структуру, я думаю, но, похоже, я бы упустил полезные преимущества классов, если бы я это сделал.

Что я хочу, так это загружать ресурсы и получать гарантии об их освобождении, но делать это разумным образом, не требуя от меня загрузки и выгрузки в один огромный метод. Как мне подойти к этому?

Ответы [ 2 ]

3 голосов
/ 22 декабря 2011

Я вполне уверен, что - по крайней мере на платформах с операционной системой с многозадачностью - вам не нужно беспокоиться об очистке при выходе из приложения.

В качестве альтернативы, вы можете просто хранить указанные ресурсы в глобальном наборе.

2 голосов
/ 22 декабря 2011

Если все, что вам нужно - это автоматически освободить SDL_Surface, вам просто нужно обернуть SDL_Surface в структуру и воспользоваться преимуществами RAII. Это хорошо подходит для такого рода вещей. Обязательно отключите постблит, чтобы избежать двойного освобождения или подсчета ссылок.

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;
}

Не проверено, но это общая идея.

Редактировать: Вы также можете использовать std.typecons.RefCounting для класса, если хотите.

...