I wonder if it is possible to determine if a given type is atomic (meaning you can perform operations on it without mutex, not putting yourself in danger).
I wonder if there is some atomic(type)
define that would determine if type is atomic. In order to create something like DEFINE( (int)(do) );
that would create pseudocode 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 any way to check on define/mtl level if type is atomic (using boost if needed).
You can't do anything like this at preprocessing time, because that determination requires semantic information about types and their names, which are not available during preprocessing.
A templated is_atomic<T>
type trait would have to be provided by the implementation, but isn't available even in C++11. It utility would be very limited, because on platforms that support threads at all, it is rather unusual to have types that are atomic by themselves.
Additionally it may not even be possible to determine this from type alone, as some types have different atomicity properties depending on their memory alignment (without making the alignment requirements for atomicity mandatory for the type).
Instead you should use the implementation provided std::atomic<T>
, which ought to provide the most efficient implementation for atomic operations (with given memory constraints) available on a given platform.
By using platform-specific memory fence or atomic access instructions such implementations may be able to provide lock-free atomic types even if the underlying memory model provides atomicity for no 'naked' native type.
You can use std::atomic<T>::is_lockfree()
to determine whether such an implementation needs to use locks under the hood.
The <atomic>
header provides ATOMIC_INT_LOCK_FREE
and friends, for all the various sizes of built-in type. These are preprocessor macros, and are defined to 0 if the atomic variant of the type is never lock free, 1 if it is sometimes lock free (e.g. if the target system supports it), and 2 if it is always lock free. e.g. if std::atomic<int>
is always lock free, but std::atomic<long long>
is 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 could use these macros to decide to use a plain int
and a mutex when std::atomic<int>
was not lock-free, but in most circumstances you are better off just writing std::atomic<int>
and letting the compiler handle it.
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