summaryrefslogtreecommitdiffstats
path: root/src/common/ceph_atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/ceph_atomic.h')
-rw-r--r--src/common/ceph_atomic.h93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/common/ceph_atomic.h b/src/common/ceph_atomic.h
new file mode 100644
index 000000000..4a96ed97e
--- /dev/null
+++ b/src/common/ceph_atomic.h
@@ -0,0 +1,93 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include <atomic>
+
+// What and why
+// ============
+//
+// ceph::atomic – thin wrapper to differentiate behavior of atomics.
+//
+// Not all users of the common truly need costly atomic operations to
+// synchronize data between CPUs and threads. Some, like crimson-osd,
+// stick to shared-nothing approach. Enforcing issue of atomics in
+// such cases is wasteful – on x86 any locked instruction works actually
+// like a full memory barrier stalling execution till CPU's store and
+// load buffers are drained.
+
+#if defined(WITH_SEASTAR) && !defined(WITH_BLUESTORE)
+
+#include <type_traits>
+
+namespace ceph {
+ template <class T>
+ class dummy_atomic {
+ T value;
+
+ public:
+ dummy_atomic() = default;
+ dummy_atomic(const dummy_atomic&) = delete;
+ dummy_atomic(T value) : value(std::move(value)) {
+ }
+ bool is_lock_free() const noexcept {
+ return true;
+ }
+ void store(T desired, std::memory_order) noexcept {
+ value = std::move(desired);
+ }
+ T load(std::memory_order = std::memory_order_seq_cst) const noexcept {
+ return value;
+ }
+ T operator=(T desired) noexcept {
+ value = std::move(desired);
+ return *this;
+ }
+ operator T() const noexcept {
+ return value;
+ }
+
+ // We need to differentiate with SFINAE as std::atomic offers beefier
+ // interface for integral types.
+
+ template<class TT=T>
+ std::enable_if_t<!std::is_enum_v<TT> && std::is_integral_v<TT>, TT> operator++() {
+ return ++value;
+ }
+ template<class TT=T>
+ std::enable_if_t<!std::is_enum_v<TT> && std::is_integral_v<TT>, TT> operator++(int) {
+ return value++;
+ }
+ template<class TT=T>
+ std::enable_if_t<!std::is_enum_v<TT> && std::is_integral_v<TT>, TT> operator--() {
+ return --value;
+ }
+ template<class TT=T>
+ std::enable_if_t<!std::is_enum_v<TT> && std::is_integral_v<TT>, TT> operator--(int) {
+ return value--;
+ }
+ template<class TT=T>
+ std::enable_if_t<!std::is_enum_v<TT> && std::is_integral_v<TT>, TT> operator+=(const dummy_atomic& b) {
+ value += b;
+ return value;
+ }
+ template<class TT=T>
+ std::enable_if_t<!std::is_enum_v<TT> && std::is_integral_v<TT>, TT> operator-=(const dummy_atomic& b) {
+ value -= b;
+ return value;
+ }
+
+ static constexpr bool is_always_lock_free = true;
+ };
+
+ template <class T> using atomic = dummy_atomic<T>;
+} // namespace ceph
+
+#else // WITH_SEASTAR
+
+namespace ceph {
+ template <class T> using atomic = ::std::atomic<T>;
+} // namespace ceph
+
+#endif // WITH_SEASTAR