Since an OpenGL context is owned by one thread, any OpenGL calls made from other threads will fail. I've wrapped OpenGL 'objects' in D classes to automate destruction of the underlying object:

this() {
    // Init texture
}

~this() {
    glDeleteTextures(1, &_handle);
}

This will blow up if the GC runs in it's own thread. As a solution, I was planning for each wrapper instance to have a reference to an OpenGL command queue unique to the context which owns the object. This queue will be emptied once per frame. The texture wrapper will change to

this(CommandQueue comQueue) {
    this.comQueue = comQueue;
    comQueue ~= { /* Init texture */ }
}

~this() {
    this.comQueue ~= { /* Delete texture */ }
}

Putting the initialization in a command allows for asynchronous loading of resources, which is a nice bonus. However, access to this queue should be synchronized. I haven't used synchronized in D yet so I'd like to know what happens in the following situation:

One thread is processing the command queue. Due to some allocation by code in a command or on another thread, the GC runs. The processing thread still holds the lock on the queue mutex when the GC blocks all threads. The GC runs the destructor of a resource, so it waits for the lock on the queue to be released and we have a deadlock.

Does the GC somehow avoid this? If not, what's the best solution to this problem?

Reply via email to