How to make sure GC allocated resources stay around when used in C functions?

Gary Willoughby via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon May 12 10:42:40 PDT 2014


Based on this conversation in another thread: 
http://forum.dlang.org/thread/wdddgiowaidcojbrklsg@forum.dlang.org?page=5#post-yjmrqgesjtadecutvkye:40forum.dlang.org 
I've realised i may have a nasty bug lurking in the code. Now i 
want to completely understand what is happening.

Take the following code:

struct Args
{
	Element element;
	string uniqueData;
	Callback callback;
}

class Element
{
	void foo(Callback callback, string uniqueData = null)
	{
		auto handler = function(ClientData data)
		{
			// Use data.
		};

		auto cleanup = function(ClientData data)
		{
			free(data);
		};

		Args* args = cast(Args*)malloc(Args.sizeof);

		(*args)            = Args.init;
		(*args).element    = this;
		(*args).uniqueData = uniqueData;
		(*args).callback   = callback;

		c_function(handler, args, cleanup);
	}
}

I want to make sure that `callback` and `uniqueData` are never 
cleaned up by the GC until i wish to allow them to be freed. A 
comment was made that in the above scenario `callback` and 
`uniqueData` allow the potential of being cleaned up and that a 
call to `GC.addRoot` might fix this problem.

Would it be as simple to just add:

GC.addRoot(cast(void*)args);
GC.setAttr(cast(void*)args, GC.BlkAttr.NO_MOVE);

to the above example? Would this not allow collection until a 
call to GC.removeRoot(). Or do i have to handle `callback` and 
`uniqueData` individually? If so how do you stop a delegate and 
string from being cleaned up by the GC?

Any help or explanations are very much appreciated.

This is the actual production code: 
https://github.com/nomad-software/tkd/blob/master/source/tkd/element/element.d#L172


More information about the Digitalmars-d-learn mailing list