Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
atomic_ops.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Roc Streaming authors
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 //! @file roc_core/target_c11/roc_core/atomic_ops.h
10 //! @brief Atomic operations.
11 
12 #ifndef ROC_CORE_ATOMIC_OPS_H_
13 #define ROC_CORE_ATOMIC_OPS_H_
14 
15 namespace roc {
16 namespace core {
17 
18 //! Atomic operations.
19 //! This wrapper exists because on non-C11 compilers we use another implementation.
20 class AtomicOps {
21 public:
22  //! @name Memory fence
23  //! @{
24 
25  //! Acquire memory barrier.
26  static inline void fence_acquire() {
27  __atomic_thread_fence(__ATOMIC_ACQUIRE);
28  }
29 
30  //! Release memory barrier.
31  static inline void fence_release() {
32  __atomic_thread_fence(__ATOMIC_RELEASE);
33  }
34 
35  //! Full memory barrier.
36  static inline void fence_seq_cst() {
37  __atomic_thread_fence(__ATOMIC_SEQ_CST);
38  }
39 
40  //! @}
41 
42  //! @name Load
43  //! @{
44 
45  //! Atomic load (no barrier).
46  template <class T> static inline T load_relaxed(const T& var) {
47  return __atomic_load_n(&var, __ATOMIC_RELAXED);
48  }
49 
50  //! Atomic load (acquire barrier).
51  template <class T> static inline T load_acquire(const T& var) {
52  return __atomic_load_n(&var, __ATOMIC_ACQUIRE);
53  }
54 
55  //! Atomic load (full barrier).
56  template <class T> static inline T load_seq_cst(const T& var) {
57  return __atomic_load_n(&var, __ATOMIC_SEQ_CST);
58  }
59 
60  //! @}
61 
62  //! @name Store
63  //! @{
64 
65  //! Atomic store (no barrier).
66  template <class T1, class T2> static inline void store_relaxed(T1& var, T2 val) {
67  __atomic_store_n(&var, val, __ATOMIC_RELAXED);
68  }
69 
70  //! Atomic store (release barrier).
71  template <class T1, class T2> static inline void store_release(T1& var, T2 val) {
72  __atomic_store_n(&var, val, __ATOMIC_RELEASE);
73  }
74 
75  //! Atomic store (full barrier).
76  template <class T1, class T2> static inline void store_seq_cst(T1& var, T2 val) {
77  __atomic_store_n(&var, val, __ATOMIC_SEQ_CST);
78  }
79 
80  //! @}
81 
82  //! @name Exchange
83  //! @{
84 
85  //! Atomic exchange (no barrier).
86  template <class T1, class T2> static inline T1 exchange_relaxed(T1& var, T2 val) {
87  return __atomic_exchange_n(&var, val, __ATOMIC_RELAXED);
88  }
89 
90  //! Atomic exchange (acquire barrier).
91  template <class T1, class T2> static inline T1 exchange_acquire(T1& var, T2 val) {
92  return __atomic_exchange_n(&var, val, __ATOMIC_ACQUIRE);
93  }
94 
95  //! Atomic exchange (release barrier).
96  template <class T1, class T2> static inline T1 exchange_release(T1& var, T2 val) {
97  return __atomic_exchange_n(&var, val, __ATOMIC_RELEASE);
98  }
99 
100  //! Atomic exchange (acquire-release barrier).
101  template <class T1, class T2> static inline T1 exchange_acq_rel(T1& var, T2 val) {
102  return __atomic_exchange_n(&var, val, __ATOMIC_ACQ_REL);
103  }
104 
105  //! Atomic exchange (full barrier).
106  template <class T1, class T2> static inline T1 exchange_seq_cst(T1& var, T2 val) {
107  return __atomic_exchange_n(&var, val, __ATOMIC_SEQ_CST);
108  }
109 
110  //! @}
111 
112  //! @name CAS
113  //! @{
114 
115  //! Atomic compare-and-swap (no barrier).
116  template <class T1, class T2>
117  static inline bool compare_exchange_relaxed(T1& var, T1& exp, T2 des) {
118  return __atomic_compare_exchange_n(&var, &exp, des, 0, __ATOMIC_RELAXED,
119  __ATOMIC_RELAXED);
120  }
121 
122  //! Atomic compare-and-swap (acquire barrier).
123  template <class T1, class T2>
124  static inline bool compare_exchange_acquire(T1& var, T1& exp, T2 des) {
125  return __atomic_compare_exchange_n(&var, &exp, des, 0, __ATOMIC_ACQUIRE,
126  __ATOMIC_ACQUIRE);
127  }
128 
129  //! Atomic compare-and-swap (release barrier).
130  template <class T1, class T2>
131  static inline bool compare_exchange_release(T1& var, T1& exp, T2 des) {
132  return __atomic_compare_exchange_n(&var, &exp, des, 0, __ATOMIC_RELEASE,
133  __ATOMIC_RELAXED);
134  }
135 
136  //! Atomic compare-and-swap (acquire-release barrier).
137  template <class T1, class T2>
138  static inline bool compare_exchange_acq_rel(T1& var, T1& exp, T2 des) {
139  return __atomic_compare_exchange_n(&var, &exp, des, 0, __ATOMIC_ACQ_REL,
140  __ATOMIC_ACQUIRE);
141  }
142 
143  //! Atomic compare-and-swap (full barrier).
144  template <class T1, class T2>
145  static inline bool compare_exchange_seq_cst(T1& var, T1& exp, T2 des) {
146  return __atomic_compare_exchange_n(&var, &exp, des, 0, __ATOMIC_SEQ_CST,
147  __ATOMIC_SEQ_CST);
148  }
149 
150  //! @}
151 
152  //! @name Addition
153  //! @{
154 
155  //! Atomic fetch-add (no barrier).
156  template <class T1, class T2> static inline T1 fetch_add_relaxed(T1& var, T2 val) {
157  return __atomic_fetch_add(&var, val, __ATOMIC_RELAXED);
158  }
159 
160  //! Atomic add-and-fetch (acquire barrier).
161  template <class T1, class T2> static inline T1 fetch_add_acquire(T1& var, T2 val) {
162  return __atomic_fetch_add(&var, val, __ATOMIC_ACQUIRE);
163  }
164 
165  //! Atomic add-and-fetch (release barrier).
166  template <class T1, class T2> static inline T1 fetch_add_release(T1& var, T2 val) {
167  return __atomic_fetch_add(&var, val, __ATOMIC_RELEASE);
168  }
169 
170  //! Atomic add-and-fetch (full barrier).
171  template <class T1, class T2> static inline T1 fetch_add_seq_cst(T1& var, T2 val) {
172  return __atomic_fetch_add(&var, val, __ATOMIC_SEQ_CST);
173  }
174 
175  //! @}
176 
177  //! @name Subtraction
178  //! @{
179 
180  //! Atomic fetch-sub (no barrier).
181  template <class T1, class T2> static inline T1 fetch_sub_relaxed(T1& var, T2 val) {
182  return __atomic_fetch_sub(&var, val, __ATOMIC_RELAXED);
183  }
184 
185  //! Atomic sub-and-fetch (acquire barrier).
186  template <class T1, class T2> static inline T1 fetch_sub_acquire(T1& var, T2 val) {
187  return __atomic_fetch_sub(&var, val, __ATOMIC_ACQUIRE);
188  }
189 
190  //! Atomic sub-and-fetch (release barrier).
191  template <class T1, class T2> static inline T1 fetch_sub_release(T1& var, T2 val) {
192  return __atomic_fetch_sub(&var, val, __ATOMIC_RELEASE);
193  }
194 
195  //! Atomic sub-and-fetch (full barrier).
196  template <class T1, class T2> static inline T1 fetch_sub_seq_cst(T1& var, T2 val) {
197  return __atomic_fetch_sub(&var, val, __ATOMIC_SEQ_CST);
198  }
199 
200  //! @}
201 
202  //! @name Bitwise AND
203  //! @{
204 
205  //! Atomic fetch-and (no barrier).
206  template <class T1, class T2> static inline T1 fetch_and_relaxed(T1& var, T2 val) {
207  return __atomic_fetch_and(&var, val, __ATOMIC_RELAXED);
208  }
209 
210  //! Atomic fetch-and (acquire barrier).
211  template <class T1, class T2> static inline T1 fetch_and_acquire(T1& var, T2 val) {
212  return __atomic_fetch_and(&var, val, __ATOMIC_ACQUIRE);
213  }
214 
215  //! Atomic fetch-and (release barrier).
216  template <class T1, class T2> static inline T1 fetch_and_release(T1& var, T2 val) {
217  return __atomic_fetch_and(&var, val, __ATOMIC_RELEASE);
218  }
219 
220  //! Atomic fetch-and (full barrier).
221  template <class T1, class T2> static inline T1 fetch_and_seq_cst(T1& var, T2 val) {
222  return __atomic_fetch_and(&var, val, __ATOMIC_SEQ_CST);
223  }
224 
225  //! @}
226 
227  //! @name Bitwise OR
228  //! @{
229 
230  //! Atomic fetch-or (no barrier).
231  template <class T1, class T2> static inline T1 fetch_or_relaxed(T1& var, T2 val) {
232  return __atomic_fetch_or(&var, val, __ATOMIC_RELAXED);
233  }
234 
235  //! Atomic fetch-or (acquire barrier).
236  template <class T1, class T2> static inline T1 fetch_or_acquire(T1& var, T2 val) {
237  return __atomic_fetch_or(&var, val, __ATOMIC_ACQUIRE);
238  }
239 
240  //! Atomic fetch-or (release barrier).
241  template <class T1, class T2> static inline T1 fetch_or_release(T1& var, T2 val) {
242  return __atomic_fetch_or(&var, val, __ATOMIC_RELEASE);
243  }
244 
245  //! Atomic fetch-or (full barrier).
246  template <class T1, class T2> static inline T1 fetch_or_seq_cst(T1& var, T2 val) {
247  return __atomic_fetch_or(&var, val, __ATOMIC_SEQ_CST);
248  }
249 
250  //! @}
251 
252  //! @name Bitwise XOR
253  //! @{
254 
255  //! Atomic fetch-xor (no barrier).
256  template <class T1, class T2> static inline T1 fetch_xor_relaxed(T1& var, T2 val) {
257  return __atomic_fetch_xor(&var, val, __ATOMIC_RELAXED);
258  }
259 
260  //! Atomic fetch-xor (acquire barrier).
261  template <class T1, class T2> static inline T1 fetch_xor_acquire(T1& var, T2 val) {
262  return __atomic_fetch_xor(&var, val, __ATOMIC_ACQUIRE);
263  }
264 
265  //! Atomic fetch-xor (release barrier).
266  template <class T1, class T2> static inline T1 fetch_xor_release(T1& var, T2 val) {
267  return __atomic_fetch_xor(&var, val, __ATOMIC_RELEASE);
268  }
269 
270  //! Atomic fetch-xor (full barrier).
271  template <class T1, class T2> static inline T1 fetch_xor_seq_cst(T1& var, T2 val) {
272  return __atomic_fetch_xor(&var, val, __ATOMIC_SEQ_CST);
273  }
274 
275  //! @}
276 };
277 
278 } // namespace core
279 } // namespace roc
280 
281 #endif // ROC_CORE_ATOMIC_OPS_H_
Atomic operations. This wrapper exists because on non-C11 compilers we use another implementation.
Definition: atomic_ops.h:20
static T1 fetch_and_release(T1 &var, T2 val)
Atomic fetch-and (release barrier).
Definition: atomic_ops.h:216
static T1 fetch_or_acquire(T1 &var, T2 val)
Atomic fetch-or (acquire barrier).
Definition: atomic_ops.h:236
static T1 exchange_release(T1 &var, T2 val)
Atomic exchange (release barrier).
Definition: atomic_ops.h:96
static void store_relaxed(T1 &var, T2 val)
Atomic store (no barrier).
Definition: atomic_ops.h:66
static T1 fetch_add_release(T1 &var, T2 val)
Atomic add-and-fetch (release barrier).
Definition: atomic_ops.h:166
static void fence_seq_cst()
Full memory barrier.
Definition: atomic_ops.h:36
static T1 fetch_or_release(T1 &var, T2 val)
Atomic fetch-or (release barrier).
Definition: atomic_ops.h:241
static void fence_acquire()
Acquire memory barrier.
Definition: atomic_ops.h:26
static T1 exchange_seq_cst(T1 &var, T2 val)
Atomic exchange (full barrier).
Definition: atomic_ops.h:106
static T1 fetch_or_relaxed(T1 &var, T2 val)
Atomic fetch-or (no barrier).
Definition: atomic_ops.h:231
static T1 exchange_relaxed(T1 &var, T2 val)
Atomic exchange (no barrier).
Definition: atomic_ops.h:86
static T1 exchange_acquire(T1 &var, T2 val)
Atomic exchange (acquire barrier).
Definition: atomic_ops.h:91
static T1 fetch_sub_seq_cst(T1 &var, T2 val)
Atomic sub-and-fetch (full barrier).
Definition: atomic_ops.h:196
static bool compare_exchange_acq_rel(T1 &var, T1 &exp, T2 des)
Atomic compare-and-swap (acquire-release barrier).
Definition: atomic_ops.h:138
static void store_seq_cst(T1 &var, T2 val)
Atomic store (full barrier).
Definition: atomic_ops.h:76
static T load_relaxed(const T &var)
Atomic load (no barrier).
Definition: atomic_ops.h:46
static T1 fetch_or_seq_cst(T1 &var, T2 val)
Atomic fetch-or (full barrier).
Definition: atomic_ops.h:246
static bool compare_exchange_seq_cst(T1 &var, T1 &exp, T2 des)
Atomic compare-and-swap (full barrier).
Definition: atomic_ops.h:145
static T load_acquire(const T &var)
Atomic load (acquire barrier).
Definition: atomic_ops.h:51
static bool compare_exchange_acquire(T1 &var, T1 &exp, T2 des)
Atomic compare-and-swap (acquire barrier).
Definition: atomic_ops.h:124
static void store_release(T1 &var, T2 val)
Atomic store (release barrier).
Definition: atomic_ops.h:71
static void fence_release()
Release memory barrier.
Definition: atomic_ops.h:31
static T1 fetch_xor_relaxed(T1 &var, T2 val)
Atomic fetch-xor (no barrier).
Definition: atomic_ops.h:256
static T1 fetch_and_seq_cst(T1 &var, T2 val)
Atomic fetch-and (full barrier).
Definition: atomic_ops.h:221
static T1 fetch_add_seq_cst(T1 &var, T2 val)
Atomic add-and-fetch (full barrier).
Definition: atomic_ops.h:171
static T1 exchange_acq_rel(T1 &var, T2 val)
Atomic exchange (acquire-release barrier).
Definition: atomic_ops.h:101
static T1 fetch_and_acquire(T1 &var, T2 val)
Atomic fetch-and (acquire barrier).
Definition: atomic_ops.h:211
static T1 fetch_xor_acquire(T1 &var, T2 val)
Atomic fetch-xor (acquire barrier).
Definition: atomic_ops.h:261
static T1 fetch_add_acquire(T1 &var, T2 val)
Atomic add-and-fetch (acquire barrier).
Definition: atomic_ops.h:161
static bool compare_exchange_relaxed(T1 &var, T1 &exp, T2 des)
Atomic compare-and-swap (no barrier).
Definition: atomic_ops.h:117
static T1 fetch_sub_release(T1 &var, T2 val)
Atomic sub-and-fetch (release barrier).
Definition: atomic_ops.h:191
static T1 fetch_sub_relaxed(T1 &var, T2 val)
Atomic fetch-sub (no barrier).
Definition: atomic_ops.h:181
static T1 fetch_and_relaxed(T1 &var, T2 val)
Atomic fetch-and (no barrier).
Definition: atomic_ops.h:206
static T1 fetch_sub_acquire(T1 &var, T2 val)
Atomic sub-and-fetch (acquire barrier).
Definition: atomic_ops.h:186
static T1 fetch_xor_release(T1 &var, T2 val)
Atomic fetch-xor (release barrier).
Definition: atomic_ops.h:266
static T1 fetch_xor_seq_cst(T1 &var, T2 val)
Atomic fetch-xor (full barrier).
Definition: atomic_ops.h:271
static bool compare_exchange_release(T1 &var, T1 &exp, T2 des)
Atomic compare-and-swap (release barrier).
Definition: atomic_ops.h:131
static T load_seq_cst(const T &var)
Atomic load (full barrier).
Definition: atomic_ops.h:56
static T1 fetch_add_relaxed(T1 &var, T2 val)
Atomic fetch-add (no barrier).
Definition: atomic_ops.h:156
Root namespace.