[patch] Make std::tr1::shared_ptr thread-safe.
Peter Dimov
pdimov@mmltd.net
Wed Mar 30 14:37:00 GMT 2005
Alexander Terekhov wrote:
> [... __release/acquire_memory_barrier() ...]
>
>> The only reliable implementation of these barriers that I see
>> is an empty pthread_mutex_lock/pthread_mutex_unlock pair.
>
> Nope. That won't work. [...]
Update:
I think that we've reached the conclusion that the following implementation:
void release() // nothrow
{
if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == 1)
{
pthread_mutex_lock( &_M_mutex );
dispose();
pthread_mutex_unlock( &_M_mutex );
weak_release();
}
}
void weak_release() // nothrow
{
if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1)
{
pthread_mutex_lock( &_M_mutex );
pthread_mutex_unlock( &_M_mutex );
destroy();
}
}
will work *provided that __exchange_and_add imposes at least the ordering
that is required for reference-counted immutable objects to work*.
The last point is important, because it affects the other uses of
__exchange_and_add in libstdc++.
Alexander has identified the following problematic case:
// thread A
read *p1
p1.drop_reference()
// thread B
p2.drop_reference(); // destroys *p1
If the __exchange_and_adds hidden in drop_reference do not establish
ordering, it is possible for *p1 to be destroyed (and the storage
invalidated, zeroed or reused) by thread B before the read in thread A.
More information about the Libstdc++
mailing list