C ++ 11 how to identify atomic type at compile time (via mtl or defines)?

I wonder if it is possible to determine whether a given type is atomic (which means that you can perform operations on it without a mutex without endangering yourself).

I wonder if there is any definition of atomic(type) that determines whether a type is atomic. To create something like DEFINE( (int)(do) ); that would create pseudo code like:

  int _do; #if !atomic(int) mutex do_mutex; #endif void set_do(int do) { #if atomic(int) _do = do; #else lock(do_mutex); _do = do; #endif } 

So, is there a way to check the define / mtl level if the type is atomic (use boost if necessary).

+4
source share
2 answers

You cannot do anything like this during preprocessing, because this definition requires semantic information about types and their names that are not available during preprocessing.

A template trait of type is_atomic<T> must be provided by the implementation, but is not available even in C ++ 11. The utility will be very limited, because on platforms that support threads in general, it is rather unusual to have types that are atoms in themselves.

In addition, it may even be impossible to determine this only by type, since some types have different atomicity properties depending on their alignment from memory (without the alignment requirement for atomicity, which is mandatory for the type).

Instead, you should use the provided implementation of std::atomic<T> , which should provide the most efficient implementation for atomic operations (with given memory restrictions) available on this platform.

Using platform-specific memory restrictions or atomic access instructions, such implementations can be locked without atomic types, even if the underlying memory model provides atomicity for a non- bare type.

You can use std::atomic<T>::is_lockfree() to determine if such an implementation should use locks under the hood.

+10
source

The <atomic> ATOMIC_INT_LOCK_FREE provides ATOMIC_INT_LOCK_FREE and friends for all types of built-in types. These are preprocessor macros and are defined as 0 if the atomic variant of the type is never blocked, 1 if it is sometimes blocked (for example, if the target system supports it) and 2 if it is always free from blocking. for example, if std::atomic<int> always locked, but std::atomic<long long> only sometimes, then ATOMIC_INT_LOCK_FREE will be 2, and ATOMIC_LLONG_LOCK_FREE will be 1. Pointer types are covered by ATOMIC_POINTER_LOCK_FREE .

You can use these macros to decide whether to use just int and semaphore when std::atomic<int> not non-blocking, but in most cases you better just write std::atomic<int> and give the compiler handle this.

+8
source

All Articles