I am writing a copy constructor for a data structure which needs to copy two std::atomic<T>
members into a new object. While the process doesn't necessarily have to be atomic in my use-case, I would prefer to have the most correct solution possible.
I am aware that the copy constructor is explicitly deleted with std::atomic<T>
so as to force users to use the atomic interface.
atomic(const atomic&) = delete;
What I am currently I am doing something like this:
SomeObject(const SomeObject& other):
_atomic1(other._atomic1.load()),
_atomic2(other._atomic2.load()) {
...
}
I do not believe this operation is atomic, nor do I know a way to make is so (without locks).
Is there a way to copy these values atomically (without locks)?
The only way is to make a trivially copyable struct S
containing two T
s and use std::atomic<S>
.
Note that this only works if you've been using this S
from the start - there is no way to atomically load two separate atomics without locks.
So instead of:
struct SomeObject {
SomeObject(const SomeObject& other) : i(other.i.load()), j(other.j.load()) { }
std::atomic<int> i, j;
};
Do this:
struct SomeObject {
SomeObject(const SomeObject& other) : data(other.data.load()) { }
struct Data { int i, j; };
std::atomic<Data> data;
};
Note that this might (probably will) still use locks internally. Use is_lock_free
to check if it does.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With