This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] Make std::tr1::shared_ptr thread-safe.


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]