diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-05-18 14:49:44 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-05-18 15:02:55 +0300 |
commit | 386f168ab340791631e4d8979c4370ecef7e6b05 (patch) | |
tree | 6dd67b95b02ef42b7d76b138f31554a7cc433a9e /include/my_atomic.h | |
parent | fde94b4cd6c916f118ccb2785c09dafef391298c (diff) | |
download | mariadb-git-386f168ab340791631e4d8979c4370ecef7e6b05.tar.gz |
MDEV-22456 after-merge fix: introduce Atomic_relaxed
In the merge 9e6e43551fc61bc34152f8d60f5d72f0d3814787
we made Atomic_counter a more generic wrapper of std::atomic
so that dict_index_t would support the implicit assignment operator.
It is better to revert the changes to Atomic_counter and
instead introduce Atomic_relaxed as a generic wrapper to std::atomic.
Unlike Atomic_counter, we will not define operator++, operator+=
or similar, because we want to make the operations more explicit
in the users of Atomic_wrapper, because unlike loads and stores,
atomic read-modify-write operations always incur some overhead.
Diffstat (limited to 'include/my_atomic.h')
-rw-r--r-- | include/my_atomic.h | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/include/my_atomic.h b/include/my_atomic.h index 1c54c24d455..88f6746ba3d 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -2,6 +2,7 @@ #define MY_ATOMIC_INCLUDED /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2018, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -169,4 +170,48 @@ my_atomic_casptr((P), (E), (D)) #endif +#ifdef __cplusplus +#include <atomic> +/** + A wrapper for std::atomic, defaulting to std::memory_order_relaxed. + + When it comes to atomic loads or stores at std::memory_order_relaxed + on IA-32 or AMD64, this wrapper is only introducing some constraints + to the C++ compiler, to prevent some optimizations of loads or + stores. + + On POWER and ARM, atomic loads and stores involve different instructions + from normal loads and stores and will thus incur some overhead. + + Because atomic read-modify-write operations will always incur + overhead, we intentionally do not define + operator++(), operator--(), operator+=(), operator-=(), or similar, + to make the overhead stand out in the users of this code. +*/ +template <typename Type> class Atomic_relaxed +{ + std::atomic<Type> m; +public: + Atomic_relaxed(const Atomic_relaxed<Type> &rhs) + { m.store(rhs, std::memory_order_relaxed); } + Atomic_relaxed(Type val) : m(val) {} + Atomic_relaxed() {} + + operator Type() const { return m.load(std::memory_order_relaxed); } + Type operator=(const Type val) + { m.store(val, std::memory_order_relaxed); return val; } + Type operator=(const Atomic_relaxed<Type> &rhs) { return *this= Type{rhs}; } + Type fetch_add(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_add(i, o); } + Type fetch_sub(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.fetch_sub(i, o); } + bool compare_exchange_strong(Type& i1, const Type i2, + std::memory_order o1= std::memory_order_relaxed, + std::memory_order o2= std::memory_order_relaxed) + { return m.compare_exchange_strong(i1, i2, o1, o2); } + Type exchange(const Type i, std::memory_order o= std::memory_order_relaxed) + { return m.exchange(i, o); } +}; +#endif /* __cplusplus */ + #endif /* MY_ATOMIC_INCLUDED */ |