2776. shared_ptr unique() and use_count()

Section: 23.11.3.5 [util.smartptr.shared.obs] Status: New Submitter: Hans Boehm Opened: 2016-09-22 Last modified: 2016-10-12

Priority: 2

View all other issues in [util.smartptr.shared.obs].

View all issues with New status.

Discussion:

The removal of the "debug only" restriction for use_count() and unique() in shared_ptr by LWG 2434 introduced a bug. In order for unique() to produce a useful and reliable value, it needs a synchronize clause to ensure that prior accesses through another reference are visible to the successful caller of unique(). Many current implementations use a relaxed load, and do not provide this guarantee, since it's not stated in the standard. For debug/hint usage that was OK. Without it the specification is unclear and probably misleading.

I would vote for making unique() use memory_order_acquire, and specifying that reference count decrement operations synchronize with unique(). That still doesn't give us sequential consistency by default, like we're supposed to have. But the violations seem sufficiently obscure that I think it's OK. All uses that anybody should care about will work correctly, and the bad uses are clearly bad. I agree with Peter that this version of unique() may be quite useful.

I would prefer to specify use_count() as only providing an unreliable hint of the actual count (another way of saying debug only). Or deprecate it, as JF suggested. We can't make use_count() reliable without adding substantially more fencing. We really don't want someone waiting for use_count() == 2 to determine that another thread got that far. And unfortunately, I don't think we currently say anything to make it clear that's a mistake.

This would imply that use_count() normally uses memory_order_relaxed, and unique is neither specified nor implemented in terms of use_count().

Proposed resolution: