简体   繁体   中英

C11 mixing atomic and non-atomic access to variable

Sometimes you may want to access a variable both atomically and non-atomically. Which is why I find convinient that on gcc you can write something like :

int var = 0;
var++;
atomic_fetch_add(&var, 1);

However this does not compile with clang 4.0.1 :

error: address argument to atomic operation must be a pointer to _Atomic type ('int *' invalid)
atomic_fetch_add(&var, 1);

The best solution I could find is a cast :

int var = 0;
(*(int*)&var)++;
atomic_fetch_add(&var, 1);

Is there a simpler and portable way to achieve this ?

There are two interfaces in C11 that allow you to act on an atomic object which are less restrictive.

First, you can always overwrite an atomic object, when you know that you are the only one accessing it, usually during an initialization phase, use atomic_init for that.

Second, if you need less guarantees for an access during the execution even with several threads, you can use a less restrictive access mode. Namely you could eg do atomic_fetch_and_add_explicit(&var, 1, memory_order_relaxed) . This still guarantees that your access is indivisible (one of the properties that you want from an atomic) but it doesn't guarantee when another thread sees the updated value.

But generally speaking, if atomic accesses are performance critical, you are doing something wrong. So before you try semantically difficult dealings with atomics, benchmark your code and see if this really is a bottleneck. If so, think first of a way to change your algorithm, eg by doing more computations in local variables that are not subject to races. Only if all of that fails to give you the performance you want, have a look into the different memory semantics that C11 offers.

The abstract machine defined by the C Standard has a rather different view of storage than most real machines. In particular, rather than thinking of memory accesses as actions which can be performed in a variety of different way depending upon required circumstances, it instead views each object has supporting one kind of read and at most one kind of write ( const -qualified objects don't support any kind of write); the kind of read and write required to access an object depend upon its type.

Such an approach may be useful for some kinds of hardware platforms, or for some optimization strategies, but is grossly unsuitable for many kinds of programs running on real-world platforms. Unfortunately, the Standard doesn't recognize any practical way by which programmers can indicate that certain objects should be treated as "ordinary" storage most of the time, but recognize that they require more precise memory semantics at certain specific times during program execution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM