I have a single-writer, multiple-reader situation. There's a counter that one thread is writing to, and any thread may read this counter. Since the single writing thread doesn't have to worry about contending with other threads for data access, is the following code safe?
#include <stdatomic.h>
#include <stdint.h>
_Atomic uint32_t counter;
// Only 1 thread calls this function. No other thread is allowed to.
uint32_t increment_counter() {
atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
return counter; // This is the line in question.
}
// Any thread may call this function.
uint32_t load_counter() {
return atomic_load_explicit(&counter, memory_order_relaxed);
}
The writer thread just reads the counter
directly without calling any atomic_load*
function. This should be safe (since it's safe for multiple threads to read a value), but I don't know if declaring a variable _Atomic
restricts you from using that variable directly, or if you're required to always read it using one of the atomic_load*
functions.
Yes, all operations that you do on _Atomic
objects are guaranteed to be effected as if you would issue the corresponding call with sequential consistency. And in your particular case an evaluation is equivalent to atomic_load
.
But the algorithm as used there is wrong, because by doing an atomic_fetch_add
and an evaluation the value that is returned may already be change by another thread. Correct would be
uint32_t ret = atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);
return ret+1;
This looks a bit suboptimal because the addition is done twice, but a good optimizer will sort this out.
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