How can I signal a master object that a resource handle is no longer used, from within the resource class's destructor?

realhet real_het at hotmail.com
Tue Jun 24 08:48:16 UTC 2025


Hi,

I started to make a resident texture class, it just holds a 
TexHandle (an int).
I it's destructor, I try to notify the outer world in a thread 
safe way that that the handle is no longer in use.
I know that in the ~this() I have restricted options.

I tried to do this with a simple queue object:
```d
class SafeQueue(T, bool multiSrc, bool multiDst)
{
	struct Node { T data; Node* next; }
	Node* head, tail;
	
	this()
	{ head = tail = new Node; }
	
	void put(T data)
	{
		auto node = new Node(data);
		void doit()
		{
			tail.next = node;
			tail = node;
		}
		static if(multiSrc) synchronized doit; else doit;
	}
	
	T* fetch()
	{
		T* res;
		void doit()
		{
			if(auto newHead = head.next)
			{
				res = &newHead.data;
				head = newHead;
			}
		}
		static if(multiDst) synchronized doit; else doit;
		return res;
	}
	
	auto fetchAll()
	{
		//Opt: it could be optimized into a single syncronize block.
		T[] res; /+Not the fastest but it's synchronous.+/
		while(1) if(auto a = fetch) res ~= *a; else break;
		return res;
	}
}

alias SSQueue	(T) = SafeQueue!(T, 0, 0),
MSQueue	(T) = SafeQueue!(T, 1, 0),
SMQueue	(T) = SafeQueue!(T, 0, 1),
MMQueue	(T) = SafeQueue!(T, 1, 1);

class Texture
{
	const TexHandle handle;
	
	version(/+$DIDE_REGION Tracking released texHandles+/all)
	{
		protected __gshared MSQueue!TexHandle 
destroyedResidentTexHandles;
		shared static this()
		{ destroyedResidentTexHandles = new 
typeof(destroyedResidentTexHandles); }
	}
	
	this(S)(in TexFlags flags, in TexFormat format, in S size, in 
void[] data=null)
	{
		TexSizeFormat fmt;
		fmt.flags 	= flags,
		fmt.format 	= format,
		fmt.size 	= size;
		fmt.resident = true;
		handle = TB.createHandleAndSetData(fmt, data);
	}
	
	this(S)(in TexFormat format, in S size, in void[] data=null, in 
TexFlags flags=TexFlags.init)
	{ this(flags, format, size, data); }
	
	~this()
	{
		if(handle)
		{ destroyedResidentTexHandles.put(handle); }
	}
}
```

This is working in a normal use case: I create a Texture class 
insance, I store it's pointer and later when I press a key, I 
release the class pointer.

But when I do not store the class pointer: `new Texture(...);` It 
just enters into a dead stall right after the first GC call.

Maybe it is because inside MSQueue.put() there is a 
synchronized{} clause and when the GC runs every thread is 
stopped?

Maybe it because there are additional memory allocation inside 
MSQueue.put()?

What's the best practice to do this automatic resource 
deallocation problem?

Manual deallocation is not a solution for this, because the 
meaning of this is to avoid manual deallocation, and the human 
errors that comes with that, in the first place. ;)


More information about the Digitalmars-d-learn mailing list