0

I need to perform some writes in the main thread and call another thread strictly after that to work with that written data. This is just a simple example:

std::atomic<int> x(0);
int z = 0;
int y = 0;
// ...
// ...
// ...
z = 12;
y = 15;
x.store(80, std::memory_order_release);
std::thread thr = std::thread( // Should be called strictly after x.store()
    [&]
    {
        if (x.load(std::memory_order_acquire) < 100)
        {
            // do stuff
        }
    });

The above code guarantees that thr, if called after x.store(), will always observe any writes performed in the main thread before x.store(), including non-atomic writes, that's fine. But is it guaranteed that thr creation will not be moved before x.store(), or should I use something like condition variable to notify thr about x being ready to be read and checked against the condition?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Alexey104
  • 969
  • 1
  • 5
  • 17
  • 2
    Creating a thread is a release operation synchronizing with an acquire operation at the start of the thread. – EOF Dec 17 '21 at 16:00
  • 3
    Formally, the completion of the invocation of the `std::thread` constructor **synchronizes with** the beginning of execution of the function passed to the constructor. Informally, any writes that occur before the constructor will be seen by the thread function. There's no need for atomics if that's all that's going on. – Pete Becker Dec 17 '21 at 16:06
  • 2
    A large part of [Does this multithreaded list processing code have enough synchronization?](https://stackoverflow.com/q/66975444)/ is about writing a variable before starting a thread that reads it, so I think it's a valid duplicate. It quotes cppreference for the point that EOF and Pete both made. Consider how broken it would be if it was data-race UB to do this with non-atomic `int x`; this design for ISO C++11 was I think required for sanity. – Peter Cordes Dec 17 '21 at 16:12
  • This [imaginary] piece of code is running in a loop, and `x` may be changed during the check in `thr`, this is why it is atomic. Thank you for the response! – Alexey104 Dec 17 '21 at 16:15
  • 2
    If there's a loop then I think you should post example code that represents that. Ideally a [mcve]. – Nate Eldredge Dec 18 '21 at 00:52
  • 1
    Right sure, in your case it may need to be `atomic` for other reasons; my point was that thinking about a non-atomic variable may help see why C++ had to forbid the reordering you're worried about, because that would be horrible. Nobody wants to require newly created threads to start by spin-waiting for some kind of synchronization. Despite how tricky C++ can be sometimes, it's not *that* bad. :P – Peter Cordes Dec 18 '21 at 00:52

0 Answers0