Iros
 
Loading...
Searching...
No Matches
atomic_ref.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/meta/core.h"
4#include "di/meta/language.h"
6#include "di/types/prelude.h"
7#include "di/util/addressof.h"
8#include "di/util/exchange.h"
10
11namespace di::sync {
12template<typename T>
13requires((concepts::Enum<T> || concepts::Arithmetic<T> || concepts::Pointer<T>) && sizeof(T) <= sizeof(void*))
14class AtomicRef {
15private:
17
18 // NOTE: the builtin atomic operations treat pointer addition bytewise, so we
19 // must multiply by the sizeof(*T) if T is a pointer.
20 constexpr auto adjust_delta(DeltaType value) -> DeltaType {
21 if constexpr (concepts::Pointer<T>) {
22 return value * sizeof(**m_pointer);
23 } else {
24 return value;
25 }
26 }
27
28public:
29 AtomicRef(AtomicRef const&) = default;
30
31 constexpr explicit AtomicRef(T& value) : m_pointer(util::addressof(value)) {}
32
33 auto operator=(AtomicRef const&) -> AtomicRef& = delete;
34
35 constexpr void store(T value, MemoryOrder order = MemoryOrder::SequentialConsistency) {
36 if consteval {
37 *m_pointer = value;
38 } else {
39 __atomic_store_n(m_pointer, value, util::to_underlying(order));
40 }
41 }
42
43 constexpr auto load(MemoryOrder order = MemoryOrder::SequentialConsistency) const -> T {
44 if consteval {
45 return *m_pointer;
46 }
47 return __atomic_load_n(m_pointer, util::to_underlying(order));
48 }
49
50 constexpr auto exchange(T value, MemoryOrder order = MemoryOrder::SequentialConsistency) -> T {
51 if consteval {
52 return di::exchange(*m_pointer, value);
53 }
54 return __atomic_exchange_n(m_pointer, value, util::to_underlying(order));
55 }
56
57 constexpr auto compare_exchange_weak(T& expected, T desired, MemoryOrder success, MemoryOrder failure) -> bool {
58 if consteval {
59 if (*m_pointer == expected) {
60 *m_pointer = desired;
61 return true;
62 }
63 expected = *m_pointer;
64 return false;
65 }
66 return __atomic_compare_exchange_n(m_pointer, util::addressof(expected), desired, true,
67 util::to_underlying(success), util::to_underlying(failure));
68 }
69
70 constexpr auto compare_exchange_weak(T& expected, T desired, MemoryOrder order = MemoryOrder::SequentialConsistency)
71 -> bool {
72 if (order == MemoryOrder::AcquireRelease || order == MemoryOrder::Release) {
74 }
75 return compare_exchange_weak(expected, desired, order, order);
76 }
77
78 constexpr auto compare_exchange_strong(T& expected, T desired, MemoryOrder success, MemoryOrder failure) -> bool {
79 if consteval {
80 if (*m_pointer == expected) {
81 *m_pointer = desired;
82 return true;
83 }
84 expected = *m_pointer;
85 return false;
86 }
87 return __atomic_compare_exchange_n(m_pointer, util::addressof(expected), desired, false,
88 util::to_underlying(success), util::to_underlying(failure));
89 }
90
91 constexpr auto compare_exchange_strong(T& expected, T desired,
93 if (order == MemoryOrder::AcquireRelease || order == MemoryOrder::Release) {
95 }
96 return compare_exchange_strong(expected, desired, order, order);
97 }
98
99 constexpr auto fetch_add(DeltaType delta, MemoryOrder order = MemoryOrder::SequentialConsistency) -> T
101 {
102 if consteval {
103 auto result = *m_pointer;
104 *m_pointer += adjust_delta(delta);
105 return result;
106 }
107 return __atomic_fetch_add(m_pointer, adjust_delta(delta), util::to_underlying(order));
108 }
109
110 constexpr auto fetch_sub(DeltaType delta, MemoryOrder order = MemoryOrder::SequentialConsistency) -> T
112 {
113 if consteval {
114 auto result = *m_pointer;
115 *m_pointer -= adjust_delta(delta);
116 return result;
117 }
118 return __atomic_fetch_sub(m_pointer, adjust_delta(delta), util::to_underlying(order));
119 }
120
121 constexpr auto fetch_and(T value, MemoryOrder order = MemoryOrder::SequentialConsistency) -> T
122 requires(concepts::Integral<T>)
123 {
124 if consteval {
125 auto result = *m_pointer;
126 *m_pointer &= value;
127 return result;
128 }
129 return __atomic_fetch_and(m_pointer, value, util::to_underlying(order));
130 }
131
132 constexpr auto fetch_or(T value, MemoryOrder order = MemoryOrder::SequentialConsistency) -> T
133 requires(concepts::Integral<T>)
134 {
135 if consteval {
136 auto result = *m_pointer;
137 *m_pointer |= value;
138 return result;
139 }
140 return __atomic_fetch_or(m_pointer, value, util::to_underlying(order));
141 }
142
143 constexpr auto fetch_xor(T value, MemoryOrder order = MemoryOrder::SequentialConsistency) -> T
144 requires(concepts::Integral<T>)
145 {
146 if consteval {
147 auto result = *m_pointer;
148 *m_pointer ^= value;
149 return result;
150 }
151 return __atomic_fetch_xor(m_pointer, value, util::to_underlying(order));
152 }
153
154private:
155 T* m_pointer { nullptr };
156};
157}
158
159namespace di {
160using sync::AtomicRef;
161}
Definition atomic_ref.h:14
constexpr auto compare_exchange_weak(T &expected, T desired, MemoryOrder order=MemoryOrder::SequentialConsistency) -> bool
Definition atomic_ref.h:70
constexpr auto compare_exchange_strong(T &expected, T desired, MemoryOrder success, MemoryOrder failure) -> bool
Definition atomic_ref.h:78
constexpr AtomicRef(T &value)
Definition atomic_ref.h:31
auto operator=(AtomicRef const &) -> AtomicRef &=delete
AtomicRef(AtomicRef const &)=default
constexpr auto load(MemoryOrder order=MemoryOrder::SequentialConsistency) const -> T
Definition atomic_ref.h:43
constexpr auto fetch_add(DeltaType delta, MemoryOrder order=MemoryOrder::SequentialConsistency) -> T requires(concepts::Integral< T >||concepts::Pointer< T >)
Definition atomic_ref.h:99
constexpr auto fetch_or(T value, MemoryOrder order=MemoryOrder::SequentialConsistency) -> T requires(concepts::Integral< T >)
Definition atomic_ref.h:132
constexpr auto fetch_xor(T value, MemoryOrder order=MemoryOrder::SequentialConsistency) -> T requires(concepts::Integral< T >)
Definition atomic_ref.h:143
constexpr auto compare_exchange_strong(T &expected, T desired, MemoryOrder order=MemoryOrder::SequentialConsistency) -> bool
Definition atomic_ref.h:91
constexpr auto compare_exchange_weak(T &expected, T desired, MemoryOrder success, MemoryOrder failure) -> bool
Definition atomic_ref.h:57
constexpr void store(T value, MemoryOrder order=MemoryOrder::SequentialConsistency)
Definition atomic_ref.h:35
constexpr auto exchange(T value, MemoryOrder order=MemoryOrder::SequentialConsistency) -> T
Definition atomic_ref.h:50
constexpr auto fetch_and(T value, MemoryOrder order=MemoryOrder::SequentialConsistency) -> T requires(concepts::Integral< T >)
Definition atomic_ref.h:121
constexpr auto fetch_sub(DeltaType delta, MemoryOrder order=MemoryOrder::SequentialConsistency) -> T requires(concepts::Integral< T >||concepts::Pointer< T >)
Definition atomic_ref.h:110
Definition language.h:224
Definition language.h:61
detail::ConditionalHelper< value, T, U >::Type Conditional
Definition core.h:88
Definition atomic.h:12
MemoryOrder
Definition memory_order.h:6
@ SequentialConsistency
Definition memory_order.h:12
@ AcquireRelease
Definition memory_order.h:11
@ Acquire
Definition memory_order.h:9
@ Release
Definition memory_order.h:10
std::ptrdiff_t ptrdiff_t
Definition ptrdiff_t.h:12
Definition vocab.h:96
constexpr auto to_underlying
Definition to_underlying.h:15
Definition zstring_parser.h:9
constexpr auto exchange(T &object, U &&new_value) -> T
Definition exchange.h:8
@ T
Definition key.h:29