Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the meaning of this piece of Standardese about shared_ptr's use_count()?

While trying to wrap my head around the problem shown in this question I found myself stuck on the following sentence from [util.smartptr.shared]/4:

[...] Changes in use_count() do not reflect modifications that can introduce data races.

I don't understand how I should read that, and what conclusions shall I draw. Here are a few interpretations:

  • Invoking use_count() does not introduce data races (but this should be guaranteed by the const-ness of that function alone, together with the corresponding library-wide guarantees)
  • The value returned by use_count() is not influenced by ("does not reflect"?) the outcome of operations that require atomicity or synchronization (but what are these relevant operations?)
  • use_count() is executed atomically, but without preventing reordering by the CPU or the compiler (i.e. without sequential consistency, but then why not mentioning the particular model?)

To me, none of the above seems to follow from that sentence, and I am at loss trying to interpret it.

like image 382
Andy Prowl Avatar asked Jan 23 '15 15:01

Andy Prowl


3 Answers

The current wording derives from library issue 896, which also addressed the question of whether shared_ptr should be thread safe in the sense that distinct shared_ptrs owning the same object can be accessed (in particular, copied and destructed) from distinct threads simultaneously. The conclusion of that discussion was that shared_ptr should be thread-safe; the mechanism to guarantee this was to pretend that shared_ptr member functions only access the shared_ptr object itself and not its on-heap control block:

For purposes of determining the presence of a data race, member functions access and modify only the shared_ptr and weak_ptr objects themselves and not objects they refer to.

Here "objects they refer to" means the control block.

However this raises an issue; if we pretend that distinct shared_ptrs owning the same object don't access the control block, then surely use_count() cannot change? This is patched by making use_count() a magic function that produces a result out of thin air:

Changes in use_count() do not reflect modifications that can introduce data races.

That is, use_count() can change from one call to the next, but that does not mean that a data race (or potential data race) has occurred. This is perhaps clearer from the previous wording of that sentence:

[Note: This is true in spite of that fact that such functions often modify use_count() --end note]

like image 186
ecatmur Avatar answered Nov 14 '22 23:11

ecatmur


It means that the code in use_count() is either lock-free or uses mutexs to lock critical sections. In other words you can call it from threads without worring about race conditions.

like image 34
Paul Evans Avatar answered Nov 14 '22 21:11

Paul Evans


I think when we add the previous sentence the intent becomes a little clearer:

For purposes of determining the presence of a data race, member functions shall access and modify only the shared_ptr and weak_ptr objects themselves and not objects they refer to. Changes in use_count() do not reflect modifications that can introduce data races.

So, the last sentence is just emphasizing the same point as the first sentence. For example, if I copy a shared_ptr, its use-count will be incremented to reflect the fact that the shared_ptr has been copied--therefore the result from use_count() will be changed--but this is not allowed to access (and, especially, not allowed to modify) the pointee object, so it can never introduce a data race in use of that pointee object.

like image 21
Jerry Coffin Avatar answered Nov 14 '22 23:11

Jerry Coffin