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
10QT_WARNING_PUSH
11QT_WARNING_DISABLE_MSVC(4522)
12
13QT_BEGIN_NAMESPACE
14
15#if 0
16// silence syncqt warnings
17QT_END_NAMESPACE
18#pragma qt_no_master_include
19#pragma qt_sync_stop_processing
20#endif
21
22// New atomics
23
24template <typename T>
25class QBasicAtomicInteger
26{
27public:
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 &currentValue) noexcept
65 { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
66 bool testAndSetAcquire(T expectedValue, T newValue, T &currentValue) noexcept
67 { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
68 bool testAndSetRelease(T expectedValue, T newValue, T &currentValue) noexcept
69 { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
70 bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue) noexcept
71 { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
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};
160typedef QBasicAtomicInteger<int> QBasicAtomicInt;
161
162template <typename X>
163class QBasicAtomicPointer
164{
165public:
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 &currentValue) noexcept
195 { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
196 bool testAndSetAcquire(Type expectedValue, Type newValue, Type &currentValue) noexcept
197 { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
198 bool testAndSetRelease(Type expectedValue, Type newValue, Type &currentValue) noexcept
199 { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
200 bool testAndSetOrdered(Type expectedValue, Type newValue, Type &currentValue) noexcept
201 { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
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
260QT_END_NAMESPACE
261
262QT_WARNING_POP
263
264#endif // QBASICATOMIC_H
265

source code of qtbase/src/corelib/thread/qbasicatomic.h