GRPC Core  9.0.0
atomic.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2017 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_LIB_GPRPP_ATOMIC_H
20 #define GRPC_CORE_LIB_GPRPP_ATOMIC_H
21 
23 
24 #include <atomic>
25 
26 #include <grpc/support/atm.h>
27 
28 namespace grpc_core {
29 
30 enum class MemoryOrder {
31  RELAXED = std::memory_order_relaxed,
32  CONSUME = std::memory_order_consume,
33  ACQUIRE = std::memory_order_acquire,
34  RELEASE = std::memory_order_release,
35  ACQ_REL = std::memory_order_acq_rel,
36  SEQ_CST = std::memory_order_seq_cst
37 };
38 
39 template <typename T>
40 class Atomic {
41  public:
42  explicit Atomic(T val = T()) : storage_(val) {}
43 
44  T Load(MemoryOrder order) const {
45  return storage_.load(static_cast<std::memory_order>(order));
46  }
47 
48  void Store(T val, MemoryOrder order) {
49  storage_.store(val, static_cast<std::memory_order>(order));
50  }
51 
52  T Exchange(T desired, MemoryOrder order) {
53  return storage_.exchange(desired, static_cast<std::memory_order>(order));
54  }
55 
56  bool CompareExchangeWeak(T* expected, T desired, MemoryOrder success,
57  MemoryOrder failure) {
58  return GPR_ATM_INC_CAS_THEN(storage_.compare_exchange_weak(
59  *expected, desired, static_cast<std::memory_order>(success),
60  static_cast<std::memory_order>(failure)));
61  }
62 
63  bool CompareExchangeStrong(T* expected, T desired, MemoryOrder success,
64  MemoryOrder failure) {
65  return GPR_ATM_INC_CAS_THEN(storage_.compare_exchange_strong(
66  *expected, desired, static_cast<std::memory_order>(success),
67  static_cast<std::memory_order>(failure)));
68  }
69 
70  template <typename Arg>
72  return GPR_ATM_INC_ADD_THEN(storage_.fetch_add(
73  static_cast<Arg>(arg), static_cast<std::memory_order>(order)));
74  }
75 
76  template <typename Arg>
78  return GPR_ATM_INC_ADD_THEN(storage_.fetch_sub(
79  static_cast<Arg>(arg), static_cast<std::memory_order>(order)));
80  }
81 
82  // Atomically increment a counter only if the counter value is not zero.
83  // Returns true if increment took place; false if counter is zero.
85  T count = storage_.load(static_cast<std::memory_order>(load_order));
86  do {
87  // If zero, we are done (without an increment). If not, we must do a CAS
88  // to maintain the contract: do not increment the counter if it is already
89  // zero
90  if (count == 0) {
91  return false;
92  }
93  } while (!CompareExchangeWeak(&count, count + 1, MemoryOrder::ACQ_REL,
94  load_order));
95  return true;
96  }
97 
98  private:
99  std::atomic<T> storage_;
100 };
101 
102 } // namespace grpc_core
103 
104 #endif /* GRPC_CORE_LIB_GPRPP_ATOMIC_H */
Definition: atomic.h:40
T Exchange(T desired, MemoryOrder order)
Definition: atomic.h:52
bool CompareExchangeStrong(T *expected, T desired, MemoryOrder success, MemoryOrder failure)
Definition: atomic.h:63
Atomic(T val=T())
Definition: atomic.h:42
bool IncrementIfNonzero(MemoryOrder load_order=MemoryOrder::ACQUIRE)
Definition: atomic.h:84
void Store(T val, MemoryOrder order)
Definition: atomic.h:48
T FetchSub(Arg arg, MemoryOrder order=MemoryOrder::SEQ_CST)
Definition: atomic.h:77
bool CompareExchangeWeak(T *expected, T desired, MemoryOrder success, MemoryOrder failure)
Definition: atomic.h:56
T Load(MemoryOrder order) const
Definition: atomic.h:44
T FetchAdd(Arg arg, MemoryOrder order=MemoryOrder::SEQ_CST)
Definition: atomic.h:71
#define GPR_ATM_INC_ADD_THEN(blah)
Definition: atm_gcc_atomic.h:45
#define GPR_ATM_INC_CAS_THEN(blah)
Definition: atm_gcc_atomic.h:44
Round Robin Policy.
Definition: backend_metric.cc:24
MemoryOrder
Definition: atomic.h:30