I wonder if this code is fine or not:
#include <iostream>
#include <future>
struct Foo
{
Foo()
:m_a(0)
{
}
int m_a;
};
int main()
{
Foo f;
auto handle =
std::async( std::launch::async,
[](Foo* f) { std::cout << f->m_a << '\n'; } ,
&f
);
handle.get();
}
I believe m_a
should be protected by a synchronization mechanism but my colleague says it is not necessary.
EDIT: To clarify my question: I am worried that the STORE operation from the constructor of Foo()
happens after the LOAD operation from the other thread. I can't see what mechanism prevents the compiler from executing those instruction in this order.
EDIT: I believe an enthusiastic compiler could decide to inline the constructor, and delay the STORE operation for after the CALL operation to std::async
. In which case the second thread could access m_a
before it has been committed to memory.
Yes, this is correctly synchronised.
From the specification for async
, C++11 30.6.8/5:
the invocation of
async
synchronizes with the invocation off
.
where f
is the function argument to async
(the lambda in your example).
Initialisation of f.m_a
is sequenced before the call to async
, and therefore before any access by the asynchronous function.
Furthermore,
the completion of the function f is sequenced before the shared state is made ready.
so the access must happen before the call to get()
returns, and therefore before the object is destroyed.