
Alexander Terekhov wrote:
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.
Yeah. http://boost.org/libs/smart_ptr/weak_ptr.htm#use_count is a bit out of date, "the" specification is at http://open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html and in the TR. I'll fix the boost documentation when I rewrite the pointers to use atomics. "Returns: 0 if *this is empty; otherwise, the number of shared_ptr instances that share ownership with *this."
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? ;-)
An implementation can do that if it wants to, but I don't want to impose it as a requirement. It's better to allow use_count() to lag behind in MT code for performance reasons, because idiomatic weak_ptr use does not rely on the latest value anyway.
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.
No, it's not; C++ behavior _is defined in terms of_ volatile (and I/O calls), not the other way around.