1 | // Copyright (C) 2011 Thiago Macieira <thiago@kde.org> |
2 | // Copyright (C) 2018 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QBASICATOMIC_H |
6 | #define QBASICATOMIC_H |
7 | |
8 | #include <QtCore/qatomic_cxx11.h> |
9 | |
10 | QT_WARNING_PUSH |
11 | QT_WARNING_DISABLE_MSVC(4522) |
12 | |
13 | QT_BEGIN_NAMESPACE |
14 | |
15 | #if 0 |
16 | // silence syncqt warnings |
17 | QT_END_NAMESPACE |
18 | #pragma qt_no_master_include |
19 | #pragma qt_sync_stop_processing |
20 | #endif |
21 | |
22 | // New atomics |
23 | |
24 | template <typename T> |
25 | class QBasicAtomicInteger |
26 | { |
27 | public: |
28 | typedef T Type; |
29 | typedef QAtomicOps<T> Ops; |
30 | // static check that this is a valid integer |
31 | static_assert(std::is_integral_v<T>, "template parameter is not an integral type" ); |
32 | static_assert(QAtomicOpsSupport<sizeof(T)>::IsSupported, "template parameter is an integral of a size not supported on this platform" ); |
33 | |
34 | typename Ops::Type _q_value; |
35 | |
36 | // Everything below is either implemented in ../arch/qatomic_XXX.h or (as |
37 | // fallback) in qgenericatomic.h |
38 | T loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); } |
39 | void storeRelaxed(T newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); } |
40 | |
41 | T loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); } |
42 | void storeRelease(T newValue) noexcept { Ops::storeRelease(_q_value, newValue); } |
43 | operator T() const noexcept { return loadAcquire(); } |
44 | T operator=(T newValue) noexcept { storeRelease(newValue); return newValue; } |
45 | |
46 | static constexpr bool isReferenceCountingNative() noexcept { return Ops::isReferenceCountingNative(); } |
47 | static constexpr bool isReferenceCountingWaitFree() noexcept { return Ops::isReferenceCountingWaitFree(); } |
48 | |
49 | bool ref() noexcept { return Ops::ref(_q_value); } |
50 | bool deref() noexcept { return Ops::deref(_q_value); } |
51 | |
52 | static constexpr bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); } |
53 | static constexpr bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); } |
54 | |
55 | bool testAndSetRelaxed(T expectedValue, T newValue) noexcept |
56 | { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); } |
57 | bool testAndSetAcquire(T expectedValue, T newValue) noexcept |
58 | { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); } |
59 | bool testAndSetRelease(T expectedValue, T newValue) noexcept |
60 | { return Ops::testAndSetRelease(_q_value, expectedValue, newValue); } |
61 | bool testAndSetOrdered(T expectedValue, T newValue) noexcept |
62 | { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); } |
63 | |
64 | bool testAndSetRelaxed(T expectedValue, T newValue, T ¤tValue) noexcept |
65 | { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, ¤tValue); } |
66 | bool testAndSetAcquire(T expectedValue, T newValue, T ¤tValue) noexcept |
67 | { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, ¤tValue); } |
68 | bool testAndSetRelease(T expectedValue, T newValue, T ¤tValue) noexcept |
69 | { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, ¤tValue); } |
70 | bool testAndSetOrdered(T expectedValue, T newValue, T ¤tValue) noexcept |
71 | { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, ¤tValue); } |
72 | |
73 | static constexpr bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); } |
74 | static constexpr bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); } |
75 | |
76 | T fetchAndStoreRelaxed(T newValue) noexcept |
77 | { return Ops::fetchAndStoreRelaxed(_q_value, newValue); } |
78 | T fetchAndStoreAcquire(T newValue) noexcept |
79 | { return Ops::fetchAndStoreAcquire(_q_value, newValue); } |
80 | T fetchAndStoreRelease(T newValue) noexcept |
81 | { return Ops::fetchAndStoreRelease(_q_value, newValue); } |
82 | T fetchAndStoreOrdered(T newValue) noexcept |
83 | { return Ops::fetchAndStoreOrdered(_q_value, newValue); } |
84 | |
85 | static constexpr bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); } |
86 | static constexpr bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); } |
87 | |
88 | T fetchAndAddRelaxed(T valueToAdd) noexcept |
89 | { return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); } |
90 | T fetchAndAddAcquire(T valueToAdd) noexcept |
91 | { return Ops::fetchAndAddAcquire(_q_value, valueToAdd); } |
92 | T fetchAndAddRelease(T valueToAdd) noexcept |
93 | { return Ops::fetchAndAddRelease(_q_value, valueToAdd); } |
94 | T fetchAndAddOrdered(T valueToAdd) noexcept |
95 | { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); } |
96 | |
97 | T fetchAndSubRelaxed(T valueToAdd) noexcept |
98 | { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); } |
99 | T fetchAndSubAcquire(T valueToAdd) noexcept |
100 | { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); } |
101 | T fetchAndSubRelease(T valueToAdd) noexcept |
102 | { return Ops::fetchAndSubRelease(_q_value, valueToAdd); } |
103 | T fetchAndSubOrdered(T valueToAdd) noexcept |
104 | { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); } |
105 | |
106 | T fetchAndAndRelaxed(T valueToAdd) noexcept |
107 | { return Ops::fetchAndAndRelaxed(_q_value, valueToAdd); } |
108 | T fetchAndAndAcquire(T valueToAdd) noexcept |
109 | { return Ops::fetchAndAndAcquire(_q_value, valueToAdd); } |
110 | T fetchAndAndRelease(T valueToAdd) noexcept |
111 | { return Ops::fetchAndAndRelease(_q_value, valueToAdd); } |
112 | T fetchAndAndOrdered(T valueToAdd) noexcept |
113 | { return Ops::fetchAndAndOrdered(_q_value, valueToAdd); } |
114 | |
115 | T fetchAndOrRelaxed(T valueToAdd) noexcept |
116 | { return Ops::fetchAndOrRelaxed(_q_value, valueToAdd); } |
117 | T fetchAndOrAcquire(T valueToAdd) noexcept |
118 | { return Ops::fetchAndOrAcquire(_q_value, valueToAdd); } |
119 | T fetchAndOrRelease(T valueToAdd) noexcept |
120 | { return Ops::fetchAndOrRelease(_q_value, valueToAdd); } |
121 | T fetchAndOrOrdered(T valueToAdd) noexcept |
122 | { return Ops::fetchAndOrOrdered(_q_value, valueToAdd); } |
123 | |
124 | T fetchAndXorRelaxed(T valueToAdd) noexcept |
125 | { return Ops::fetchAndXorRelaxed(_q_value, valueToAdd); } |
126 | T fetchAndXorAcquire(T valueToAdd) noexcept |
127 | { return Ops::fetchAndXorAcquire(_q_value, valueToAdd); } |
128 | T fetchAndXorRelease(T valueToAdd) noexcept |
129 | { return Ops::fetchAndXorRelease(_q_value, valueToAdd); } |
130 | T fetchAndXorOrdered(T valueToAdd) noexcept |
131 | { return Ops::fetchAndXorOrdered(_q_value, valueToAdd); } |
132 | |
133 | T operator++() noexcept |
134 | { return fetchAndAddOrdered(valueToAdd: 1) + 1; } |
135 | T operator++(int) noexcept |
136 | { return fetchAndAddOrdered(valueToAdd: 1); } |
137 | T operator--() noexcept |
138 | { return fetchAndSubOrdered(valueToAdd: 1) - 1; } |
139 | T operator--(int) noexcept |
140 | { return fetchAndSubOrdered(valueToAdd: 1); } |
141 | |
142 | T operator+=(T v) noexcept |
143 | { return fetchAndAddOrdered(valueToAdd: v) + v; } |
144 | T operator-=(T v) noexcept |
145 | { return fetchAndSubOrdered(valueToAdd: v) - v; } |
146 | T operator&=(T v) noexcept |
147 | { return fetchAndAndOrdered(valueToAdd: v) & v; } |
148 | T operator|=(T v) noexcept |
149 | { return fetchAndOrOrdered(valueToAdd: v) | v; } |
150 | T operator^=(T v) noexcept |
151 | { return fetchAndXorOrdered(valueToAdd: v) ^ v; } |
152 | |
153 | |
154 | QBasicAtomicInteger() = default; |
155 | constexpr QBasicAtomicInteger(T value) noexcept : _q_value(value) {} |
156 | QBasicAtomicInteger(const QBasicAtomicInteger &) = delete; |
157 | QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) = delete; |
158 | QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) volatile = delete; |
159 | }; |
160 | typedef QBasicAtomicInteger<int> QBasicAtomicInt; |
161 | |
162 | template <typename X> |
163 | class QBasicAtomicPointer |
164 | { |
165 | public: |
166 | typedef X *Type; |
167 | typedef QAtomicOps<Type> Ops; |
168 | typedef typename Ops::Type AtomicType; |
169 | |
170 | AtomicType _q_value; |
171 | |
172 | Type loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); } |
173 | void storeRelaxed(Type newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); } |
174 | |
175 | operator Type() const noexcept { return loadAcquire(); } |
176 | Type operator=(Type newValue) noexcept { storeRelease(newValue); return newValue; } |
177 | |
178 | // Atomic API, implemented in qatomic_XXX.h |
179 | Type loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); } |
180 | void storeRelease(Type newValue) noexcept { Ops::storeRelease(_q_value, newValue); } |
181 | |
182 | static constexpr bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); } |
183 | static constexpr bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); } |
184 | |
185 | bool testAndSetRelaxed(Type expectedValue, Type newValue) noexcept |
186 | { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); } |
187 | bool testAndSetAcquire(Type expectedValue, Type newValue) noexcept |
188 | { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); } |
189 | bool testAndSetRelease(Type expectedValue, Type newValue) noexcept |
190 | { return Ops::testAndSetRelease(_q_value, expectedValue, newValue); } |
191 | bool testAndSetOrdered(Type expectedValue, Type newValue) noexcept |
192 | { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); } |
193 | |
194 | bool testAndSetRelaxed(Type expectedValue, Type newValue, Type ¤tValue) noexcept |
195 | { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, ¤tValue); } |
196 | bool testAndSetAcquire(Type expectedValue, Type newValue, Type ¤tValue) noexcept |
197 | { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, ¤tValue); } |
198 | bool testAndSetRelease(Type expectedValue, Type newValue, Type ¤tValue) noexcept |
199 | { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, ¤tValue); } |
200 | bool testAndSetOrdered(Type expectedValue, Type newValue, Type ¤tValue) noexcept |
201 | { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, ¤tValue); } |
202 | |
203 | static constexpr bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); } |
204 | static constexpr bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); } |
205 | |
206 | Type fetchAndStoreRelaxed(Type newValue) noexcept |
207 | { return Ops::fetchAndStoreRelaxed(_q_value, newValue); } |
208 | Type fetchAndStoreAcquire(Type newValue) noexcept |
209 | { return Ops::fetchAndStoreAcquire(_q_value, newValue); } |
210 | Type fetchAndStoreRelease(Type newValue) noexcept |
211 | { return Ops::fetchAndStoreRelease(_q_value, newValue); } |
212 | Type fetchAndStoreOrdered(Type newValue) noexcept |
213 | { return Ops::fetchAndStoreOrdered(_q_value, newValue); } |
214 | |
215 | static constexpr bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); } |
216 | static constexpr bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); } |
217 | |
218 | Type fetchAndAddRelaxed(qptrdiff valueToAdd) noexcept |
219 | { return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); } |
220 | Type fetchAndAddAcquire(qptrdiff valueToAdd) noexcept |
221 | { return Ops::fetchAndAddAcquire(_q_value, valueToAdd); } |
222 | Type fetchAndAddRelease(qptrdiff valueToAdd) noexcept |
223 | { return Ops::fetchAndAddRelease(_q_value, valueToAdd); } |
224 | Type fetchAndAddOrdered(qptrdiff valueToAdd) noexcept |
225 | { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); } |
226 | |
227 | Type fetchAndSubRelaxed(qptrdiff valueToAdd) noexcept |
228 | { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); } |
229 | Type fetchAndSubAcquire(qptrdiff valueToAdd) noexcept |
230 | { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); } |
231 | Type fetchAndSubRelease(qptrdiff valueToAdd) noexcept |
232 | { return Ops::fetchAndSubRelease(_q_value, valueToAdd); } |
233 | Type fetchAndSubOrdered(qptrdiff valueToAdd) noexcept |
234 | { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); } |
235 | |
236 | Type operator++() noexcept |
237 | { return fetchAndAddOrdered(valueToAdd: 1) + 1; } |
238 | Type operator++(int) noexcept |
239 | { return fetchAndAddOrdered(valueToAdd: 1); } |
240 | Type operator--() noexcept |
241 | { return fetchAndSubOrdered(valueToAdd: 1) - 1; } |
242 | Type operator--(int) noexcept |
243 | { return fetchAndSubOrdered(valueToAdd: 1); } |
244 | Type operator+=(qptrdiff valueToAdd) noexcept |
245 | { return fetchAndAddOrdered(valueToAdd) + valueToAdd; } |
246 | Type operator-=(qptrdiff valueToSub) noexcept |
247 | { return fetchAndSubOrdered(valueToAdd: valueToSub) - valueToSub; } |
248 | |
249 | QBasicAtomicPointer() = default; |
250 | constexpr QBasicAtomicPointer(Type value) noexcept : _q_value(value) {} |
251 | QBasicAtomicPointer(const QBasicAtomicPointer &) = delete; |
252 | QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) = delete; |
253 | QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) volatile = delete; |
254 | }; |
255 | |
256 | #ifndef Q_BASIC_ATOMIC_INITIALIZER |
257 | # define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) } |
258 | #endif |
259 | |
260 | QT_END_NAMESPACE |
261 | |
262 | QT_WARNING_POP |
263 | |
264 | #endif // QBASICATOMIC_H |
265 | |