RefPtr Class example:
/+
' Source : RefPtr.d - Thread reference counting class
' Author : Regan Heath <regan[at]netwin[dot]co[dot]nz>
' Created : 16.Oct.05 with D v0.135
' :
' Reference : http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=1929
' ----------------------------------------------------------------------------------
' To complie for a unittest:
' dmd refptr.d -debug=refptr -unittest
'
' To compile a D program that uses refptr.d:
' dmd YourSource.d refptr.d
+/
private import std.thread;
debug( refptr ) private import std.random;
debug( refptr ) private import std.stdio;
debug( refptr ) private import std.c.windows.windows;
class RefPtr
{
RefPtr parent;
Object resource = null;
int refs = 0;
this(Object res)
{
resource = res;
debug( refptr )
{
std.stdio.writefln("ThreadID=(", std.thread.Thread.getThis().id,
") Initial RefPtr for resource=(", resource, ")");
}
increment();
}
this(RefPtr rhs)
{
parent = rhs;
parent.increment();
debug( refptr )
{
std.stdio.writefln("ThreadID=(", std.thread.Thread.getThis().id,
") Ref=(", parent.refs,
") for resource=(", parent.resource, ")");
}
}
~this()
{
int r;
if ((r = decrement()) == 0)
{
debug( refptr )
{
std.stdio.writefln("ThreadID=(", std.thread.Thread.getThis().id,
") release last ref Ref=(", r, ")");
}
if (parent)
parent = null;
else
if (resource)
{
debug( refptr )
{
std.stdio.writefln("ThreadID=(", std.thread.Thread.getThis().id,
") delete resource=(", resource, ")");
}
delete resource;
resource = null;
}
}
debug( refptr )
{
std.stdio.writefln("ThreadID=(", std.thread.Thread.getThis().id,
") release Ref=(", r, ")");
}
}
protected:
int increment()
{
int ret;
if (parent)
ret = parent.increment();
else
{
synchronized(this)
{
ret = ++refs;
debug( refptr )
{
std.stdio.writefln("ThreadID=(", std.thread.Thread.getThis().id,
") increment to Ref=(", refs, ")");
}
}
}
return ret;
}
int decrement()
{
int ret;
if (parent)
ret = parent.decrement();
else
{
synchronized(this)
{
ret = --refs;
debug( refptr )
{
std.stdio.writefln("ThreadID=(", std.thread.Thread.getThis().id,
") decrement to Ref=(",refs,")");
}
}
}
return ret;
}
}
class Resource
{
char[] name = "11 was a racehorse";
char[] toString() { return name; }
}
RefPtr pbob;
static this()
{
pbob = new RefPtr(new Resource());
}
static ~this()
{
delete pbob;
}
debug( refptr )
{
void main()
{
Thread[] threads;
int i;
std.stdio.writefln("ThreadID=(", std.thread.Thread.getThis().id, ") is the main thread");
for(i = 0; i < 10; i++)
{
threads ~= new std.thread.Thread(&thread_function, null);
threads[$-1].start();
}
while(true)
{
i = 0;
foreach(Thread t; threads)
{
if (t.getState() == std.thread.Thread.TS.TERMINATED)
i++;
}
if (i == 10)
break;
std.c.windows.windows.Sleep(100);
}
writefln("Main exiting");
}
int thread_function(void* isnull)
{
auto RefPtr p = new RefPtr(pbob);
std.c.windows.windows.Sleep(1000 + std.random.rand() % 1000);
return 0;
}
}
C:\dmd>dmd refptr.d -debug=refptr -unittest
C:\dmd\bin\..\..\dm\bin\link.exe refptr,,,user32+kernel32/noi;
C:\dmd>refptr
ThreadID=(3788) Initial RefPtr for resource=(11 was a racehorse)
ThreadID=(3788) increment to Ref=(1)
ThreadID=(3788) is the main thread
ThreadID=(1840) increment to Ref=(2)
ThreadID=(1840) Ref=(2) for resource=(11 was a racehorse)
ThreadID=(4060) increment to Ref=(3)
ThreadID=(4060) Ref=(3) for resource=(11 was a racehorse)
ThreadID=(3416) increment to Ref=(4)
ThreadID=(3416) Ref=(4) for resource=(11 was a racehorse)
ThreadID=(400) increment to Ref=(5)
ThreadID=(400) Ref=(5) for resource=(11 was a racehorse)
ThreadID=(2620) increment to Ref=(6)
ThreadID=(2620) Ref=(6) for resource=(11 was a racehorse)
ThreadID=(2924) increment to Ref=(7)
ThreadID=(2924) Ref=(7) for resource=(11 was a racehorse)
ThreadID=(1284) increment to Ref=(8)
ThreadID=(1284) Ref=(8) for resource=(11 was a racehorse)
ThreadID=(3376) increment to Ref=(9)
ThreadID=(3376) Ref=(9) for resource=(11 was a racehorse)
ThreadID=(4036) increment to Ref=(10)
ThreadID=(4036) Ref=(10) for resource=(11 was a racehorse)
ThreadID=(4064) increment to Ref=(11)
ThreadID=(4064) Ref=(11) for resource=(11 was a racehorse)
ThreadID=(1840) decrement to Ref=(10)
ThreadID=(1840) release Ref=(10)
ThreadID=(1284) decrement to Ref=(9)
ThreadID=(1284) release Ref=(9)
ThreadID=(4060) decrement to Ref=(8)
ThreadID=(4060) release Ref=(8)
ThreadID=(2620) decrement to Ref=(7)
ThreadID=(2620) release Ref=(7)
ThreadID=(4036) decrement to Ref=(6)
ThreadID=(4036) release Ref=(6)
ThreadID=(3376) decrement to Ref=(5)
ThreadID=(3376) release Ref=(5)
ThreadID=(2924) decrement to Ref=(4)
ThreadID=(2924) release Ref=(4)
ThreadID=(3416) decrement to Ref=(3)
ThreadID=(3416) release Ref=(3)
ThreadID=(400) decrement to Ref=(2)
ThreadID=(400) release Ref=(2)
ThreadID=(4064) decrement to Ref=(1)
ThreadID=(4064) release Ref=(1)
Main exiting
ThreadID=(3788) decrement to Ref=(0)
ThreadID=(3788) release last ref Ref=(0)
ThreadID=(3788) delete resource=(11 was a racehorse)
ThreadID=(3788) release Ref=(0)
C:\dmd>