This class multi-threaded safe?

hurd hurd at 163.com
Wed Dec 24 02:57:38 PST 2008



import
	tango.core.Memory,
	tango.core.Atomic;
	
extern (C)  void * memcpy (void *dst, void *src, uint);

class FreeList(MSG){
	
	private{
		struct Node{
			MSG*		msg;
		}
		struct	NodeList{
			Node*	node;
			uint	count;
		}
		Atomic!(NodeList*)	ver;
	}
	
	this(){
		ver.store(&NodeList.init);
	}
	
	uint count(){
		NodeList* now	= ver.load();
		return	now.count;
	}
	
	void unshift(in MSG* p){
		NodeList* ol, nl;
		nl	= new NodeList;
		uint	size;
		Node*	n;
		do{
			ol		= ver.load();
			nl.count	= ol.count + 1;
			n		= cast(Node*) GC.malloc( Node.sizeof *  nl.count );
			if( ol.count > 0 ){
				memcpy(cast(void*)n + Node.sizeof , cast(void*)ol.node, Node.sizeof *  ol.count );
			}
			nl.node	= n;
			n.msg	= p;
		}while( !ver.storeIf(nl, ol) );
	}
		
	void push(in MSG* p){
		NodeList* ol, nl;
		nl	= new NodeList;
		uint	size;
		Node*	n;
		do{
			ol		= ver.load();
			nl.count	= ol.count + 1;
			n		= cast(Node*) GC.malloc( Node.sizeof *  nl.count );
			if( ol.count > 0 ){
				memcpy(cast(void*)n, cast(void*)ol.node, Node.sizeof *  ol.count );
			}
			nl.node			= n;
			(n+ol.count).msg	= p;
		}while( !ver.storeIf(nl, ol) );
	}
	
	bool pop(out MSG* p){
		NodeList* ol, nl;
		nl	= new NodeList;
		uint	size;
		Node*	n;
		do{
			ol	= ver.load();
			if( ol.count is 0 ){
				return false;
			}
			nl.count	= ol.count - 1;
			p		= ( ol.node + nl.count ).msg;
			if( nl.count > 0 ){
				n	= cast(Node*) GC.malloc( Node.sizeof *  nl.count );
				memcpy(cast(void*)n , cast(void*)ol.node  , Node.sizeof *  nl.count );
				nl.node		= n;
			}else{
				nl	= &NodeList.init;
			}
		}while( !ver.storeIf(nl, ol) );
		return true;
	}
	
	bool shift(out MSG* p){
		NodeList* ol, nl;
		nl	= new NodeList;
		uint	size;
		Node*	n;
		do{
			ol	= ver.load();
			if( ol.count is 0 ){
				return false;
			}
			nl.count	= ol.count - 1;
			p		= ol.node.msg;
			if( nl.count > 0 ){
				n	= cast(Node*) GC.malloc( Node.sizeof *  nl.count );
				memcpy(cast(void*)n , cast(void*)ol.node + Node.sizeof , Node.sizeof *  nl.count );
				nl.node		= n;
			}else{
				nl	= &NodeList.init;
			}
		}while( !ver.storeIf(nl, ol) );
		return true;
	}
	
}



// -------------------------

import

	tango.util.log.Trace,
	tango.core.Thread,
	tango.time.Clock,
	tango.core.sync.Semaphore;

void main(){
	struct Msg{
		int 	i;
		Time	now;
		
	};
	auto li	= new FreeList!(Msg);
	
	Msg* p;
	for( int i = 0 ; i < 500 ; i++){
		p	= new Msg;
		p.i	= i;
		p.now	= Clock.now;
		li.unshift(p);
	}
	
	Trace.formatln("msg.count = {} ", li.count).flush;
	
	GC.collect;
	
	while( li.shift(p) ){
		if( p.i % 100 is 0 )
			Trace.format ("{} {}ms \n", p.i, ( Clock.now - p.now).millis );
	}
	
	Trace.formatln("Done").flush;
}






More information about the Digitalmars-d mailing list