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