0

I have a std::shared_ptr which changes asynchronously from a callback.

In main thread, I want to read the "latest" value and do complex calculations on it, and I do not care if the pointer's value changes while those calculations are running.

For this, I am simply making a copy of the contained value on the main thread:

// async thread
void callback(P new_data) {
  smart_pointer_ = new_data;
}

// main thread loop!
Value copy_of_pointer_value = *smart_pointer_; // smart_pointer_ could be changing in callback right now
// do calcs with copy_of_pointer_value

Is this safe or should I be explicitly making a copy of the smart pointer before trying to read its value, like this:

// main thread loop!
auto smart_copy = smart_pointer_;
// I know I could work with *smart_copy directly, but I need to copy anyway for other reasons
Value copy_of_pointer_value = *smart_copy;
// do calcs with copy_of_pointer_value
Bill Kotsias
  • 3,258
  • 6
  • 33
  • 60
  • 1
    Neither the first nor the second approach is safe - both contain a data race. The second approach could be salvaged with `auto smart_copy = std::atomic_load(&smart_pointer_);` , as well as `callback` doing `std::atomic_store(&smart_pointer_, std::shared_ptr

    (new_data));`

    – Igor Tandetnik May 19 '20 at 15:19
  • @IgorTandetnik Then, what IS thread safe about smart pointers, according to the standard? I'm confused – Bill Kotsias May 19 '20 at 21:01
  • Nothing is thread-safe about `std::shared_ptr`, according to the standard. Why do you expect something to be? Generally, standard library classes are not thread-safe, except those specifically intended for thread synchronization, e.g. `std::mutex` – Igor Tandetnik May 20 '20 at 01:33
  • @IgorTandetnik But making copies of the control block is safe. Please Check this out: https://stackoverflow.com/a/14485302/113718 – Bill Kotsias May 20 '20 at 05:28
  • 1
    The C++ standard never mentions the words "control block". That's an internal implementation detail. The basic guarantee the standard provides for all library classes is that a) different instances can be manipulated concurrently (if those instances internally share state, it's their responsibility to protect it), and b) `const` methods of a single instance can be called concurrently. In your example, `callback` calls a non-`const` method on `smart_pointer_` - namely, `operator=` - and that needs to be synchronized with any other access to `smart_pointer_`, whether `const` or non-`const`. – Igor Tandetnik May 20 '20 at 10:53
  • 1
    The exact relevant wording can be found [here](http://eel.is/c++draft/res.on.data.races), especially paragraphs 2, 3 and 7. – Igor Tandetnik May 20 '20 at 11:08

0 Answers0