Fw: [patch] Make std::tr1::shared_ptr thread-safe.
Alexander Terekhov
alexander.terekhov@gmail.com
Thu Mar 31 20:32:00 GMT 2005
On Thu, 31 Mar 2005 22:09:21 +0300, Peter Dimov <pdimov@mmltd.net> wrote:
> Alexander Terekhov wrote:
> > "Peter Dimov" <pdimov@mmltd.net> on 03/30/2005 11:33:56 PM:
> > [...]
> >> 3. Making __exchange_and_add offer the following memory
> >> synchronization guarantees:
> >>
> >> - acquire memory semantics when the result is not zero;
> >> - release memory semantics when the result is zero
> >
> > release memory semantics when the result is not zero;
> > acquire memory semantics when the result is zero
>
> Umm, of course.
>
> > And "result" means new value of count stored by __exchange_and_add(),
> > not return value (its old value). BTW, I had a typo in my previous
> > message when I wrote "result > 1".
>
> [...]
>
> > 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().
>
> > destruct();
> > }
> >
> > void release() throw() {
> > if (!use_count_.decrement()) { // "full" release-acquire protocol
>
> As above:
>
> - release memory semantics when the result is not zero;
> - acquire memory semantics when the result is zero
>
> > dispose();
> > if (!self_count_.decrement(msync::rel, count::may_not_store_min))
>
> - release memory semantics when result is not zero (old value > 1)
> - no-op when the old value is 1 (no memory synchronization, may skip the
> final store of 0)
>
> > destruct();
> > }
> > }
>
> Right?
Right. But lock() must be MT-ordered with respect to destruction of
control block and I missed that.
regards,
alexander.
More information about the Libstdc++
mailing list