MKoD - D Programming Language

D-Sourcery RefPtr Class - Thread reference counting class - code-name RefPtr.d

Very Kool! 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>
Mars: fourth Rock from the Sun.