Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I read an atomic variable without atomic_load?

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.

like image 213
Cornstalks Avatar asked Feb 02 '17 13:02

Cornstalks


1 Answers

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.

like image 120
Jens Gustedt Avatar answered Sep 30 '22 08:09

Jens Gustedt