This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Fw: [patch] Make std::tr1::shared_ptr thread-safe.
- From: Alexander Terekhov <alexander dot terekhov at gmail dot com>
- To: Peter Dimov <pdimov at mmltd dot net>
- Cc: libstdc++ at gcc dot gnu dot org, Jonathan Wakely <cow at compsoc dot man dot ac dot uk>
- Date: Fri, 1 Apr 2005 02:05:29 +0200
- Subject: Re: Fw: [patch] Make std::tr1::shared_ptr thread-safe.
- References: <OF24DE43AB.98214558-ONC1256FD5.0044D61E-C1256FD5.0044BD18@de.ibm.com> <e52efbe105033105212ee0988a@mail.gmail.com> <013201c53625$27348390$6501a8c0@pdimov2> <e52efbe1050331123229a6c57d@mail.gmail.com>
- Reply-to: Alexander Terekhov <alexander dot terekhov at gmail dot com>
On Thu, 31 Mar 2005 22:32:42 +0200, Alexander Terekhov
<alexander.terekhov@gmail.com> wrote:
[...]
> > > void weak_release() throw() {
> > > if (!self_count_.decrement(msync::acq, count::may_not_store_min))
> >
> > In an expanded form:
> >
> > - no memory synchronization when the result is not zero (old value > 1)
> > - acquire memory semantics when the old value is 1 (may skip the final store
> > of 0)
>
> Yes. Assumption here is that on weak_ptr<> side we only increment and
> decrement self_count and don't make any other acceses to "control block"
> object apart from destruction and lock(). This allows to relax msync
> protocol.
>
> Gosh. We need (relaxed) acquire in lock() for conditional increment
> (better than release constraint when the result is not zero for
> decrement in weak_release()).
>
> Hmm. Now comes Whitehead (mutex inside lock())..
>
> Without "real" fence in lock(), I don't see how to make it safe with
> relaxed msync protocol for self_count_.decrement() in weak_release().
Mutex dtor is another issue. So given that Peter says that it seems to
him that in general lock() calls outnumber weak_release() calls, and
that it's better to just use acq/rel in weak_release instead of
modifying lock(), lets simply get rid of relaxation of acq/rel protocol
on self_count() entirely. <pseudo-code>
class sp_counted_base {
/* ... */
typedef refcount<std::size_t, basic> count;
count use_count_, self_count_;
/* ... */
public:
/* ... */
sp_counted_base() : use_count_(1), self_count_(1) { }
void add_ref() throw() {
use_count_.increment(); // naked
}
void release() throw() {
// "full" release-acquire protocol for decrements
if (!use_count_.decrement()) {
dispose();
if (!self_count_.decrement(count::may_not_store_min))
destruct();
}
}
bool lock() throw() {
// Whitehead or
return use_count_.increment_if_not_min(); // naked
}
void weak_add_ref() throw() {
self_count_.increment(); // naked
}
void weak_release() throw() {
// "full" release-acquire protocol
if (!self_count_.decrement(count::may_not_store_min))
destruct();
}
/* ... */
};
regards,
alexander.