This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [patch] Make std::tr1::shared_ptr thread-safe.
- From: "Peter Dimov" <pdimov at mmltd dot net>
- To: <libstdc++ at gcc dot gnu dot org>
- Cc: "Alexander Terekhov" <TEREKHOV at de dot ibm dot com>
- Date: Wed, 30 Mar 2005 17:36:54 +0300
- Subject: Re: [patch] Make std::tr1::shared_ptr thread-safe.
- References: <OF51216141.374EAC91-ONC1256FD3.00537529-C1256FD3.005361E0@de.ibm.com> <e52efbe105032907371ce02f72@mail.gmail.com>
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.