[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