
Alexander Terekhov wrote:
Peter Dimov wrote:
Now that I think of it, compiler value propagation isn't a problem either because of the "memory" clobber on the decrement. So the cast to volatile can be removed.
void release() // nothrow { if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) { dispose();
if( weak_count_ == 1 ) // no weak ptrs
(this doesn't convey the notion of (potentially) competing accesses; who says that implementation can't read it bit-after-bit-and-sum-it, bytes aside for a moment... just for the sake of breaking your logic?)
Hm. You are right in theory, but in practice, I know that this is g++ on x86, and I know that it doesn't do such things. (Aside: why invent naked_competing instead of just using nsync as per PL2?)
{ destroy(); } else { weak_release(); } } }
... you also have and manage client-provided "deleter" objects and I see no reason why weak_ptr clients may NOT have access to them (resulting in similar problem with respect to access and destruction as with Whitehead's mutex).
Hmmmm. IIUC, you are saying that a thread can obtain access to the deleter using get_deleter, then hold on to the returned pointer after the shared_ptr is destroyed while holding only a weak_ptr to the object to keep the deleter alive? I'm having trouble picturing a situation where disallowing this will be a problem. Via the pointer you can only _read_ the deleter safely, and only if its operator() is const (because operator() can be called at any time.) Hence, you could have performed the reads beforehand, while still holding a shared_ptr. This aside, is this a problem on x86? I don't think it is since the load has acquire semantics either way.