Reputation: 2491
I'm currently having troubles correctly understanding the usage of the new std::atomic
types. For my case I have the following assumptions:
uint64_t
values stored in memoryOriginally I implemented the methods like this
uint64_t inc(const size_t pos) { return _data[pos]++; }
uint64_t atomic_inc(const size_t pos) { return __sync_fetch_and_add(&_data[pos], 1); }
Now I wanted to port this correctly to C++11 and was wondering how should I handle this correctly. From my understanding of std::atomic_fetch_add one basically needs an atomic integral value to do this. However, how do I need to implement this correctly, so that I can point using an atomic variable to a location and increment the value?
Thanks!
Upvotes: 4
Views: 9766
Reputation: 68631
You cannot use C++11 facilities to get atomic access to a variable that is not declared as an atomic type. You would need to replace your array of uint64_t
with an array of std::atomic<uint64_t>
. On many platforms, this will have the same size and alignment as plain uint64_t
, but all operations will be atomic.
You can then use data[pos].fetch_add(1,memory_order)
to do the atomic increment with the specified memory_order
. If you need a memory order of std::memory_order_seq_cst
(which is probably the closest to the GCC __sync_fetch_and_add
), then the memory order can be omitted, or you could use an increment operator, e.g. data[pos]++
.
Upvotes: 9
Reputation: 4463
You can't.
A C++11 atomic object encapsulates its base type. It does not provide access to its value as lvalue nor can you set it up to provide atomic operations on a preexisting object of the underlying type (at a given memory location).
Depending on the platform any given atomic type might have special requirements (e.g. stronger alignment constraints) or need auxiliary data (most atomic types are not guaranteed to be lock-free)
Doing what you want to do still requires platform-specific functionality.
If you want to do non-atomic increments,the closest you can get is:
atomic<uint64_t> data(initial_value);
data.store(data.load(memory_order_relaxed) + 1, memory_order_relaxed);
This will still do atomic loads and stores, but no memory fencing or atomic read-modify-write operations.
Upvotes: 3