< Forward Inline http://gcc.gnu.org/ml/libstdc++/2005-03/msg00371.html>
-------- Original Message --------
Message-ID: <e52efbe10503300728333c87d9@[EMAIL PROTECTED]
>
Subject: Re: [patch] Make std::tr1::shared_ptr thread-safe.
"Peter Dimov" <pdimov@[EMAIL PROTECTED]
> on 03/30/2005 04:36:54 PM:
>
> 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 release() // nothrow
{
if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == 1)
{
dispose();
pthread_mutex_lock( &_M_mutex );
pthread_mutex_unlock( &_M_mutex );
weak_release();
}
}
would also work. The key here is...
>
> 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();
> }
> }
to have the same lock on both sides. Some "thread-specific" locks to
"emulate" bidirectional fences with minimum contention won't work.
>
> will work *provided that __exchange_and_add imposes at least the
ordering
> that is required for reference-counted immutable objects to work*.
That's msync::slb (relaxed msync::rel not affecting sinking of preceding
stores) when result > 1 and msync::cchsb (relaxed msync::acq [cc stands
control condition hint] not affecting hoisting of subsequent loads) when
result == 0.
No _M_mutex above is needed with more constrained version of
__exchange_and_add() providing msync::rel when result > 1 and msync::ccacq
when result == 0. Such semantics will also sup****t basic thread-safety of
shared_ptr<> for mutable managed objects without unpleasant requirement
for client provided synchronizing deleters.
>
> The last point is im****tant, 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.
Yep.
regards,
alexander.


|