I want to initialize a field in a constructor and never change it afterwards. I want the guarantee that after the constructor finished, every read of the field reads the initialized value, no matter in which thread the read happens.
Basically, I want the same guarantees as a final
field gives in Java.
This is what I tried:
#include <atomic>
#include <iostream>
#include <thread>
struct Foo
{
Foo(int x) : x(x)
{
// ensure all writes are visible to other threads
std::atomic_thread_fence(std::memory_order_release);
}
int x;
};
void print_x(Foo const& foo)
{
// I don't think I need an aquire fence here, because the object is
// newly constructed, so there cannot be any stale reads.
std::cout << foo.x << std::endl;
}
int main()
{
Foo foo(1);
std::thread t(print_x, foo);
t.join();
}
- Is this guaranteed to always print
1
or can threadt
observefoo.x
in an uninitialized state? - What if instead of using the member initializer
x(x)
an explicit assignmentthis->x = x;
is used? - What if
x
is not anint
but some class type? - Does making
x
aconst int
change anything with regards to thread safety?