Refcounting smart pointer?

Jb jb at nowhere.com
Fri Sep 5 18:44:50 PDT 2008


"Sönke Ludwig" <ludwig_no at spam_informatik.uni-luebeck.de> wrote in message 
news:g9rt39$4qn$1 at digitalmars.com...
> 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.

Ah yeah I see the problem now.






More information about the Digitalmars-d mailing list