I have a C++ library, which supposed to do some computations on multiple threads. I made independent threads code (i.e. there are no shared variables between them), except f
Here is a cleaned up version of your AtomicUInt64
type:
template<typename T>
struct MobileAtomic
{
std::atomic<T> atomic;
MobileAtomic() : atomic(T()) {}
explicit MobileAtomic ( T const& v ) : atomic ( v ) {}
explicit MobileAtomic ( std::atomic<T> const& a ) : atomic ( a.load() ) {}
MobileAtomic ( MobileAtomic const&other ) : atomic( other.atomic.load() ) {}
MobileAtomic& operator=( MobileAtomic const &other )
{
atomic.store( other.atomic.load() );
return *this;
}
};
typedef MobileAtomic<uint64_t> AtomicUInt64;
and use:
AtomicUInt64 value;
myVector->push_back ( value );
or:
AtomicUInt64 value(x);
myVector->push_back ( value );
your problem was you took a std::atomic
by value, which causes a copy, which is blocked. Oh, and you failed to return from operator=
. I also made some constructors explicit, probably needlessly. And I added const
to your copy constructor.
I would also be tempted to add store
and load
methods to MobileAtomic
that forwards to atomic.store
and atomic.load
.
This line
AtomicUInt64 ( std::atomic<uint64_t> a ) : atomic ( atomic.load() ) {}
You're completely ignoring the argument you pass in, You probably want it to be a.load() and you probably want to take elements by const reference so they aren't copied.
AtomicUInt64 (const std::atomic<uint64_t>& a) : atomic (a.load()) {}
As for what you're doing, I'm not sure if it is correct. The modification of the variables inside the array will be atomic, but if the vector is modified or reallocated (which is possible with push_back
), then there's nothing to guarantee your array modifications will work between threads and be atomic.
You're trying to copy a non-copyable type: the AtomicUInt64
constructor takes an atomic
by value.
If you need it to be initialisable from atomic
, then it should take the argument by (const) reference. However, in your case, it doesn't look like you need to initialise from atomic
at all; why not initialise from uint64_t
instead?
Also a couple of minor points:
The copy constructor and assignment operator should take their values by const
reference, to allow temporaries to be copied.
Allocating the vector with new
is a rather odd thing to do; you're just adding an extra level of indirection with no benefit.
Make sure you never resize the array while other threads might be accessing it.