Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / src / core / lib / gprpp / atomic.h
diff --git a/legacy-libs/grpc-cloned/deps/grpc/src/core/lib/gprpp/atomic.h b/legacy-libs/grpc-cloned/deps/grpc/src/core/lib/gprpp/atomic.h
new file mode 100644 (file)
index 0000000..095ebf1
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_GPRPP_ATOMIC_H
+#define GRPC_CORE_LIB_GPRPP_ATOMIC_H
+
+#include <grpc/support/port_platform.h>
+
+#include <atomic>
+
+#include <grpc/support/atm.h>
+
+namespace grpc_core {
+
+enum class MemoryOrder {
+  RELAXED = std::memory_order_relaxed,
+  CONSUME = std::memory_order_consume,
+  ACQUIRE = std::memory_order_acquire,
+  RELEASE = std::memory_order_release,
+  ACQ_REL = std::memory_order_acq_rel,
+  SEQ_CST = std::memory_order_seq_cst
+};
+
+template <typename T>
+class Atomic {
+ public:
+  explicit Atomic(T val = T()) : storage_(val) {}
+
+  T Load(MemoryOrder order) const {
+    return storage_.load(static_cast<std::memory_order>(order));
+  }
+
+  void Store(T val, MemoryOrder order) {
+    storage_.store(val, static_cast<std::memory_order>(order));
+  }
+
+  T Exchange(T desired, MemoryOrder order) {
+    return storage_.exchange(desired, static_cast<std::memory_order>(order));
+  }
+
+  bool CompareExchangeWeak(T* expected, T desired, MemoryOrder success,
+                           MemoryOrder failure) {
+    return GPR_ATM_INC_CAS_THEN(storage_.compare_exchange_weak(
+        *expected, desired, static_cast<std::memory_order>(success),
+        static_cast<std::memory_order>(failure)));
+  }
+
+  bool CompareExchangeStrong(T* expected, T desired, MemoryOrder success,
+                             MemoryOrder failure) {
+    return GPR_ATM_INC_CAS_THEN(storage_.compare_exchange_strong(
+        *expected, desired, static_cast<std::memory_order>(success),
+        static_cast<std::memory_order>(failure)));
+  }
+
+  template <typename Arg>
+  T FetchAdd(Arg arg, MemoryOrder order = MemoryOrder::SEQ_CST) {
+    return GPR_ATM_INC_ADD_THEN(storage_.fetch_add(
+        static_cast<Arg>(arg), static_cast<std::memory_order>(order)));
+  }
+
+  template <typename Arg>
+  T FetchSub(Arg arg, MemoryOrder order = MemoryOrder::SEQ_CST) {
+    return GPR_ATM_INC_ADD_THEN(storage_.fetch_sub(
+        static_cast<Arg>(arg), static_cast<std::memory_order>(order)));
+  }
+
+  // Atomically increment a counter only if the counter value is not zero.
+  // Returns true if increment took place; false if counter is zero.
+  bool IncrementIfNonzero(MemoryOrder load_order = MemoryOrder::ACQUIRE) {
+    T count = storage_.load(static_cast<std::memory_order>(load_order));
+    do {
+      // If zero, we are done (without an increment). If not, we must do a CAS
+      // to maintain the contract: do not increment the counter if it is already
+      // zero
+      if (count == 0) {
+        return false;
+      }
+    } while (!CompareExchangeWeak(&count, count + 1, MemoryOrder::ACQ_REL,
+                                  load_order));
+    return true;
+  }
+
+ private:
+  std::atomic<T> storage_;
+};
+
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_GPRPP_ATOMIC_H */