On Fri, 27 Apr 2012 17:55:02 +0200, Rene Zwanenburg <[email protected]> wrote:

I _could_ modify the system to use ref counting everywhere, but I'm
reluctant to do that.

You wouldn't really need to. Only the texture struct would need that.
Look to std.typecons's RefCounted[1] for inspiration. One could easily
imagine and RAII version of that, which would take as a template parameter
a function that would run in the destructor. Simple implementation (I'm
lazy):

import std.typecons : Tuple;
import std.traits : hasIndirections;
import std.algorithm : swap, move;
import core.stdc.stdlib : malloc, free;
import std.conv : emplace;

struct RefCountedDestructor(T, alias destructor = {}) if (!is(T == class)) {
    Tuple!(T, "_payload", size_t, "_count")* _store;

    this(A...)(A args) {
        auto sz = (*_store).sizeof;
        auto p = malloc(sz)[0..sz];
        static if (hasIndirections!T)
        {
            GC.addRange(p.ptr, sz);
        }
        emplace(cast(T*)p.ptr, args);
        _store = cast(typeof(_store))p.ptr;
        _store._count = 1;
    }

    this(this) {
        _store._count++;
    }

    ~this() {
        assert(_store._count > 0);
        if (--_store._count) {
            return;
        }

        destructor();

        clear(_store._payload);
        static if (hasIndirections!T) {
            GC.removeRange(_store);
        }
        _store = null;
    }

    void opAssign(typeof(this) rhs)
    {
        swap(_store, rhs._store);
    }

    void opAssign(T rhs)
    {
        _store._payload = move(rhs);
    }

    @property
    ref T payload( ) {
        return _store._payload;
    }

    @property const
    ref const(T) payload( ) {
        return _store._payload;
    }

    alias payload this;
}

Usage:

void main() {
auto a = RefCountedDestructor!(int, {writeln("Goodbye, cruel world")})(4);
}

Reply via email to