
Peter Dimov wrote: [...]
bool expired() { return !lock(); }
I don't think that this is an improvement. The user that wants !lock() writes !lock(). The user that wants a (potentially more efficient version of - insert "in theory" here as well) use_count() == 0 writes expired(). ^^^^^^^^^^^
Well, I'm a bit puzzled by its "unspecified nonnegative value" and "number of shared_ptr objects" (if you allow counting of null owners) bits, to tell the truth.
It is deliberately "unspecified" whether expired() msyncs or not.
long use_count() const { shared_ptr<T> const & p = lock(); return p ? p.use_count() - 1 : 0; } Oder? ;-) But ok, just specify "unspecified" behavior a bit more explicit, so to say.
It's PDQ in practice (unless you have a compiler smart enough to ignore volatile hack and use a cached copy in spite of it because you're not supposed to noticed the difference according to the MT memory model rules).
You need to insert lots of "in theory" here.
* "volatile" is specifically intended to prevent "smartness".
Your use of a volatile variable is indistinguishable (no change in behavior whatsoever) from a non-volatile variable if/when run single-thread. I believe that implementations capable to detect it are free to ignore your use of volatile if they operate under POSIX memory model where volatile is totally irrelevant with respect to threading. regards, alexander.