fennec
Loading...
Searching...
No Matches
atomic.h
Go to the documentation of this file.
1// =====================================================================================================================
2// fennec, a free and open source game engine
3// Copyright © 2025 Medusa Slockbower
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17// =====================================================================================================================
18
30
31
32#ifndef FENNEC_THREADING_ATOMIC_H
33#define FENNEC_THREADING_ATOMIC_H
34
35#include <fennec/threading/detail/_atomic.h>
36
38
39namespace fennec
40{
41
42using ::memory_order;
43using ::memory_order_relaxed;
44using ::memory_order_consume;
45using ::memory_order_acquire;
46using ::memory_order_release;
47using ::memory_order_acq_rel;
48using ::memory_order_seq_cst;
49
53template<typename T>
54struct atomic {
55
56// Assertions ==========================================================================================================
57public:
58 static_assert(is_integral_v<T>, "fennec::atomic not defined for the provided type. Default implementation"
59 "only supports integral types.");
60
61
62
63// Definitions =========================================================================================================
64public:
65 using value_t = T;
66
67
68
69// Constructors ========================================================================================================
70
75 constexpr atomic() noexcept
76 : _value(static_cast<T>(0)) {
77 }
78
84 constexpr atomic(const T value) noexcept
85 : _value(value) {
86 }
87
88 atomic(const atomic&) = delete;
89
90
91
92// Assignment ==========================================================================================================
93
94 atomic& operator=(const atomic&) = delete;
95 atomic& operator=(const atomic&) volatile = delete;
96
101 T operator=(const T x) noexcept {
102 this->store(x);
103 return x;
104 }
105
112 T operator=(const T x) volatile noexcept {
113 this->store(x);
114 return x;
115 }
116
117
118
119// Modifiers ===========================================================================================================
120
125 void store(const T x, memory_order order = memory_order_seq_cst) noexcept {
126 ::atomic_store_explicit(&_value, x, order);
127 }
128
135 void store(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
136 ::atomic_store_explicit(&_value, x, order);
137 }
138
139
145 T load(memory_order order = memory_order_seq_cst) const noexcept {
146 return ::atomic_load_explicit(&_value, order);
147 }
148
156 T load(memory_order order = memory_order_seq_cst) const volatile noexcept {
157 return ::atomic_load_explicit(&_value, order);
158 }
159
160
163 operator T() const noexcept {
164 return load();
165 }
166
171 operator T() const volatile noexcept {
172 return load();
173 }
174
175
182 T exchange(const T x, memory_order order = memory_order_seq_cst) noexcept {
183 return ::atomic_exchange_explicit(&_value, x, order);
184 }
185
194 T exchange(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
195 return ::atomic_exchange_explicit(&_value, x, order);
196 }
197
198
209 bool compare_exchange_weak(T& exp, T x, memory_order succ, memory_order fail) noexcept {
210 return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, succ, fail);
211 }
212
223 bool compare_exchange_weak(T& exp, T x, memory_order succ, memory_order fail) volatile noexcept {
224 return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, succ, fail);
225 }
226
237 bool compare_exchange_weak(T& exp, T x, memory_order order = memory_order_seq_cst) noexcept {
238 return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, order, order);
239 }
240
253 bool compare_exchange_weak(T& exp, T x, memory_order order = memory_order_seq_cst) volatile noexcept {
254 return ::atomic_compare_exchange_weak_explicit(&_value, &exp, x, order, order);
255 }
256
257
268 bool compare_exchange_strong(T& exp, T x, memory_order succ, memory_order fail) noexcept {
269 return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, succ, fail);
270 }
271
282 bool compare_exchange_strong(T& exp, T x, memory_order succ, memory_order fail) volatile noexcept {
283 return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, succ, fail);
284 }
285
296 bool compare_exchange_strong(T& exp, T x, memory_order order = memory_order_seq_cst) noexcept {
297 return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, order, order);
298 }
299
312 bool compare_exchange_strong(T& exp, T x, memory_order order = memory_order_seq_cst) volatile noexcept {
313 return ::atomic_compare_exchange_strong_explicit(&_value, &exp, x, order, order);
314 }
315
316
317
318// Operations ==========================================================================================================
319
320 T fetch_add(const T x, memory_order order = memory_order_seq_cst) noexcept {
321 return ::atomic_fetch_add_explicit(&_value, x, order);
322 }
323
324 T fetch_add(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
325 return ::atomic_fetch_add_explicit(&_value, x, order);
326 }
327
328 T operator+=(const T x) noexcept {
329 return this->fetch_add(x) + x;
330 }
331
332 T operator+=(const T x) volatile noexcept {
333 return this->fetch_add(x) + x;
334 }
335
336
337
338 T operator++() noexcept {
339 return this->fetch_add(1) + 1;
340 }
341
342 T operator++() volatile noexcept {
343 return this->fetch_add(1) + 1;
344 }
345
346 T operator++(int) noexcept {
347 return this->fetch_add(1);
348 }
349
350 T operator++(int) volatile noexcept {
351 return this->fetch_add(1);
352 }
353
354
355
356 T fetch_sub(const T x, memory_order order = memory_order_seq_cst) noexcept {
357 return ::atomic_fetch_sub_explicit(&_value, x, order);
358 }
359
360 T fetch_sub(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
361 return ::atomic_fetch_sub_explicit(&_value, x, order);
362 }
363
364 T operator-=(const T x) noexcept {
365 return this->fetch_sub(x) - x;
366 }
367
368 T operator-=(const T x) volatile noexcept {
369 return this->fetch_sub(x) - x;
370 }
371
372
373
374 T operator--() noexcept {
375 return this->fetch_sub(1) - 1;
376 }
377
378 T operator--() volatile noexcept {
379 return this->fetch_sub(1) - 1;
380 }
381
382 T operator--(int) noexcept {
383 return this->fetch_sub(1);
384 }
385
386 T operator--(int) volatile noexcept {
387 return this->fetch_sub(1);
388 }
389
390
391
392// Bit Operations ======================================================================================================
393
394 T fetch_and(const T x, memory_order order = memory_order_seq_cst) noexcept {
395 return ::atomic_fetch_and_explicit(&_value, x, order);
396 }
397
398 T fetch_and(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
399 return ::atomic_fetch_and_explicit(&_value, x, order);
400 }
401
402 T operator&=(const T x) noexcept {
403 return this->fetch_and(x) & x;
404 }
405
406 T operator&=(const T x) volatile noexcept {
407 return this->fetch_and(x) & x;
408 }
409
410
411
412 T fetch_or(const T x, memory_order order = memory_order_seq_cst) noexcept {
413 return ::atomic_fetch_or_explicit(&_value, x, order);
414 }
415
416 T fetch_or(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
417 return ::atomic_fetch_or_explicit(&_value, x, order);
418 }
419
420 T operator|=(const T x) noexcept {
421 return this->fetch_or(x) & x;
422 }
423
424 T operator|=(const T x) volatile noexcept {
425 return this->fetch_or(x) & x;
426 }
427
428
429
430 T fetch_xor(const T x, memory_order order = memory_order_seq_cst) noexcept {
431 return ::atomic_fetch_xor_explicit(&_value, x, order);
432 }
433
434 T fetch_xor(const T x, memory_order order = memory_order_seq_cst) volatile noexcept {
435 return ::atomic_fetch_xor_explicit(&_value, x, order);
436 }
437
438 T operator^=(const T x) noexcept {
439 return this->fetch_xor(x) & x;
440 }
441
442 T operator^=(const T x) volatile noexcept {
443 return this->fetch_xor(x) & x;
444 }
445
446
447
448private:
449 _Atomic T _value;
450};
451
452}
453
454#endif // FENNEC_THREADING_ATOMIC_H
constexpr genType exp(genType x)
Returns the natural exponentiation of , i.e., .
Definition exponential.h:122
Wrapper for atomic variables.
Definition atomic.h:54
void store(const T x, memory_order order=memory_order_seq_cst) noexcept
Definition atomic.h:125
bool compare_exchange_strong(T &exp, T x, memory_order order=memory_order_seq_cst) noexcept
Definition atomic.h:296
bool compare_exchange_strong(T &exp, T x, memory_order order=memory_order_seq_cst) volatile noexcept
Atomically compares the value of the atomic object with non-atomic argument and performs atomic excha...
Definition atomic.h:312
bool compare_exchange_strong(T &exp, T x, memory_order succ, memory_order fail) noexcept
Definition atomic.h:268
bool compare_exchange_strong(T &exp, T x, memory_order succ, memory_order fail) volatile noexcept
Definition atomic.h:282
T load(memory_order order=memory_order_seq_cst) const volatile noexcept
Atomically obtains the value of the atomic object.
Definition atomic.h:156
constexpr atomic(const T value) noexcept
Value Constructor.
Definition atomic.h:84
void store(const T x, memory_order order=memory_order_seq_cst) volatile noexcept
Atomically replaces the value of the atomic object with a non-atomic argument.
Definition atomic.h:135
bool compare_exchange_weak(T &exp, T x, memory_order order=memory_order_seq_cst) volatile noexcept
Atomically compares the value of the atomic object with non-atomic argument and performs atomic excha...
Definition atomic.h:253
bool compare_exchange_weak(T &exp, T x, memory_order succ, memory_order fail) noexcept
Definition atomic.h:209
T exchange(const T x, memory_order order=memory_order_seq_cst) volatile noexcept
Atomically replaces the value of the atomic object and obtains the value held previously.
Definition atomic.h:194
T load(memory_order order=memory_order_seq_cst) const noexcept
Definition atomic.h:145
bool compare_exchange_weak(T &exp, T x, memory_order succ, memory_order fail) volatile noexcept
Definition atomic.h:223
T operator=(const T x) noexcept
Definition atomic.h:101
bool compare_exchange_weak(T &exp, T x, memory_order order=memory_order_seq_cst) noexcept
Definition atomic.h:237
T exchange(const T x, memory_order order=memory_order_seq_cst) noexcept
Definition atomic.h:182
constexpr atomic() noexcept
Default Constructor.
Definition atomic.h:75
T operator=(const T x) volatile noexcept
Stores a value into an atomic object.
Definition atomic.h:112
Type Traits