Reputation: 986
I'm not sure what's the scope of std::memory_order_release
or std::memory_order_acquire
memory barriers. Below is an example taken from cppreference. I tweaked the code to make my point:
#include <atomic>
#include <cassert>
#include <string>
#include <thread>
#include <iostream>
std::atomic<std::string*> ptr;
void producer()
{
std::string* p = new std::string("Hello");
ptr.store(p, std::memory_order_release);
}
bool acquire(std::string* p2)
{
while (!(p2 = ptr.load(std::memory_order_acquire)));
return p2 != nullptr;
}
void consumer()
{
std::string* p2 {nullptr};
// while (!(p2 = ptr.load(std::memory_order_acquire))); // prints "makes sense"
assert(acquire(p2)); // prints "what's going on?"
if (p2 == nullptr)
{
std::cout << "what's going on?" << std::endl;
}
else
{
std::cout << "makes sense" << std::endl;
}
}
int main()
{
std::thread t1(producer);
std::thread t2(consumer);
t1.join(); t2.join();
}
The output of the above code is what's going on?
I'm familiar (not expert) with memory barriers. From the test above I have the following questions:
The std::memory_order_acquire
used in acquire()
function only is used for the scope of acquire()
, based on the output of the program since uncommenting while(...)
prints the expected output "makes sense". Does this make sense? am I missing anything?
How is it possible to print "what's going on?", the assert(acquire(p2))
makes it clear p2 is not nullptr
, but somehow it reads the nullptr
value in the if
conditional. I'm not an expert in out of order execution rules, but I'd expect that p2 = nullptr
is honored before calling acquire()
, since acquire()
depends on it.
Upvotes: 1
Views: 421
Reputation: 63735
- The
std::memory_order_acquire
used inacquire()
function only is used for the scope of acquire()
No. It applies to the thread and is not bound by any function boundaries.
- How is it possible to print "what's going on?"
Because you are modifying a copy of the pointer. Change:
bool acquire(std::string* p2)
to:
bool acquire(std::string*& p2)
to make the function reference the same pointer that's being passed to it.
Upvotes: 4