Refcounting smart pointer?

Sönke Ludwig ludwig_no at spam_informatik.uni-luebeck.de
Fri Sep 5 11:17:13 PDT 2008


Jb schrieb:
> "Sönke Ludwig" <ludwig_no at spam_informatik.uni-luebeck.de> wrote in message 
> news:g9nvrs$284k$1 at digitalmars.com...
>> On the other side, making a completely thread-safe variant is not possible 
>> as far as I see, since the copy operation is not safe - so only the 
>> reference counting part can really be made safe.
> 
> Thread safe ref counting can be done with
> 
> lock inc [this.refcount]
> lock dec [this.refcount]
> 
> You need the lock prefix or else they are not atomic.
> 
> 
> 
> 

The problem that remains is that the copy operation (blit) of the 
counted reference struct is not synchronized or executed atomically 
together with the subsequent increment. Consider the following setup:

struct RefCounter {
	int* count;
	this(){ count = new int; *count = 1; }
	this(this){ atomic_inc(count); }
	~this(){ if( !atomic_dec(count) ) delete count; }
}

// init
RefCounter a;

// thread a
{
	// write to a
	RefCounter dummy1;
	a = dummy1;
	// 1. read tmp = a.count
	// 2. atomically decrement *tmp
	// 3.   delete a.count if <= 0
	// 4. copy dummy1 to a
	// 5. read a.count
	// 6. atomically increment *a.count
}

// thread b
{
	// read from a
	RefCounter dummy2 = a;
	// - copy
	// 1. copy a to dummy
	// 2. read dummy2.count
	// 3. atomically increment *dummy2.count
}

A possible order of execution would be:

B 1. dummy2.count is the original a.count
A 1. tmp is a.count
A 2. *tmp/*a.count is decremented -> *a.count == 0
A 3. a.count is deleted
B 2. tmp is dummy2.count, which is the original a.count
B 3. *tmp/*dummy2.count/*a.count is incremented (CRASH)
...

And if there are two pointers inside of the struct, the number
of possible failures increases considerably. So thread-safety can only 
be guaranteed if there are no concurrent read/write or write/write 
accesses to the same reference.



More information about the Digitalmars-d mailing list