Line data Source code
1 : /****************************************************************************
2 : **
3 : ** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
4 : ** Contact: http://www.qt-project.org/legal
5 : **
6 : ** This file is part of the QtCore module of the Qt Toolkit.
7 : **
8 : ** $QT_BEGIN_LICENSE:LGPL$
9 : ** Commercial License Usage
10 : ** Licensees holding valid commercial Qt licenses may use this file in
11 : ** accordance with the commercial license agreement provided with the
12 : ** Software or, alternatively, in accordance with the terms contained in
13 : ** a written agreement between you and Digia. For licensing terms and
14 : ** conditions see http://qt.digia.com/licensing. For further information
15 : ** use the contact form at http://qt.digia.com/contact-us.
16 : **
17 : ** GNU Lesser General Public License Usage
18 : ** Alternatively, this file may be used under the terms of the GNU Lesser
19 : ** General Public License version 2.1 as published by the Free Software
20 : ** Foundation and appearing in the file LICENSE.LGPL included in the
21 : ** packaging of this file. Please review the following information to
22 : ** ensure the GNU Lesser General Public License version 2.1 requirements
23 : ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 : **
25 : ** In addition, as a special exception, Digia gives you certain additional
26 : ** rights. These rights are described in the Digia Qt LGPL Exception
27 : ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 : **
29 : ** GNU General Public License Usage
30 : ** Alternatively, this file may be used under the terms of the GNU
31 : ** General Public License version 3.0 as published by the Free Software
32 : ** Foundation and appearing in the file LICENSE.GPL included in the
33 : ** packaging of this file. Please review the following information to
34 : ** ensure the GNU General Public License version 3.0 requirements will be
35 : ** met: http://www.gnu.org/copyleft/gpl.html.
36 : **
37 : **
38 : ** $QT_END_LICENSE$
39 : **
40 : ****************************************************************************/
41 :
42 : #include <QtCore/qatomic.h>
43 :
44 : #ifndef QBASICATOMIC_H
45 : #define QBASICATOMIC_H
46 :
47 : #if defined(QT_BOOTSTRAPPED)
48 : # include <QtCore/qatomic_bootstrap.h>
49 :
50 : // Compiler dependent implementation
51 : #elif defined(Q_CC_MSVC)
52 : # include <QtCore/qatomic_msvc.h>
53 :
54 : // Processor dependent implementation
55 : #elif defined(Q_PROCESSOR_ARM_V7) && defined(Q_PROCESSOR_ARM_32)
56 : # include "QtCore/qatomic_armv7.h"
57 : #elif defined(Q_PROCESSOR_ARM_V6) && defined(Q_PROCESSOR_ARM_32)
58 : # include "QtCore/qatomic_armv6.h"
59 : #elif defined(Q_PROCESSOR_ARM_V5) && defined(Q_PROCESSOR_ARM_32)
60 : # include "QtCore/qatomic_armv5.h"
61 : #elif defined(Q_PROCESSOR_IA64)
62 : # include "QtCore/qatomic_ia64.h"
63 : #elif defined(Q_PROCESSOR_MIPS)
64 : # include "QtCore/qatomic_mips.h"
65 : #elif defined(Q_PROCESSOR_X86)
66 : # include <QtCore/qatomic_x86.h>
67 :
68 : // Fallback compiler dependent implementation
69 : #elif defined(Q_COMPILER_ATOMICS) && defined(Q_COMPILER_CONSTEXPR)
70 : # include <QtCore/qatomic_cxx11.h>
71 : #elif defined(Q_CC_GNU)
72 : # include <QtCore/qatomic_gcc.h>
73 :
74 : // Fallback operating system dependent implementation
75 : #elif defined(Q_OS_UNIX)
76 : # include <QtCore/qatomic_unix.h>
77 :
78 : // No fallback
79 : #else
80 : # error "Qt has not been ported to this platform"
81 : #endif
82 :
83 : QT_BEGIN_NAMESPACE
84 :
85 : #if 0
86 : // silence syncqt warnings
87 : QT_END_NAMESPACE
88 : #pragma qt_no_master_include
89 : #pragma qt_sync_stop_processing
90 : #endif
91 :
92 : // New atomics
93 :
94 : #if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
95 : # if defined(Q_CC_CLANG) && ((((__clang_major__ * 100) + __clang_minor__) < 303) \
96 : || defined(__apple_build_version__) \
97 : )
98 : /* Do not define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS for "stock" clang before version 3.3.
99 : Apple's version has different (higher!) version numbers, so disable it for all of them for now.
100 : (The only way to distinguish between them seems to be a check for __apple_build_version__ .)
101 :
102 : For details about the bug: see http://llvm.org/bugs/show_bug.cgi?id=12670
103 : */
104 : # else
105 : # define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
106 : # endif
107 : #endif
108 :
109 : template <typename T>
110 : class QBasicAtomicInteger
111 : {
112 : public:
113 : typedef QAtomicOps<T> Ops;
114 : // static check that this is a valid integer
115 : Q_STATIC_ASSERT_X(QTypeInfo<T>::isIntegral, "template parameter is not an integral type");
116 : Q_STATIC_ASSERT_X(QAtomicOpsSupport<sizeof(T)>::IsSupported, "template parameter is an integral of a size not supported on this platform");
117 :
118 : typename Ops::Type _q_value;
119 :
120 : // Everything below is either implemented in ../arch/qatomic_XXX.h or (as fallback) in qgenericatomic.h
121 :
122 2340 : T load() const Q_DECL_NOTHROW { return Ops::load(_q_value); }
123 : void store(T newValue) Q_DECL_NOTHROW { Ops::store(_q_value, newValue); }
124 :
125 : T loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); }
126 : void storeRelease(T newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); }
127 : operator T() const Q_DECL_NOTHROW { return loadAcquire(); }
128 : T operator=(T newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; }
129 :
130 : static Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return Ops::isReferenceCountingNative(); }
131 : static Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return Ops::isReferenceCountingWaitFree(); }
132 :
133 132 : bool ref() Q_DECL_NOTHROW { return Ops::ref(_q_value); }
134 349 : bool deref() Q_DECL_NOTHROW { return Ops::deref(_q_value); }
135 :
136 : static Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return Ops::isTestAndSetNative(); }
137 : static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return Ops::isTestAndSetWaitFree(); }
138 :
139 : bool testAndSetRelaxed(T expectedValue, T newValue) Q_DECL_NOTHROW
140 : { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
141 : bool testAndSetAcquire(T expectedValue, T newValue) Q_DECL_NOTHROW
142 : { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); }
143 : bool testAndSetRelease(T expectedValue, T newValue) Q_DECL_NOTHROW
144 : { return Ops::testAndSetRelease(_q_value, expectedValue, newValue); }
145 : bool testAndSetOrdered(T expectedValue, T newValue) Q_DECL_NOTHROW
146 : { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
147 :
148 : bool testAndSetRelaxed(T expectedValue, T newValue, T ¤tValue) Q_DECL_NOTHROW
149 : { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, ¤tValue); }
150 : bool testAndSetAcquire(T expectedValue, T newValue, T ¤tValue) Q_DECL_NOTHROW
151 : { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, ¤tValue); }
152 : bool testAndSetRelease(T expectedValue, T newValue, T ¤tValue) Q_DECL_NOTHROW
153 : { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, ¤tValue); }
154 : bool testAndSetOrdered(T expectedValue, T newValue, T ¤tValue) Q_DECL_NOTHROW
155 : { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, ¤tValue); }
156 :
157 : static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return Ops::isFetchAndStoreNative(); }
158 : static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndStoreWaitFree(); }
159 :
160 : T fetchAndStoreRelaxed(T newValue) Q_DECL_NOTHROW
161 : { return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
162 : T fetchAndStoreAcquire(T newValue) Q_DECL_NOTHROW
163 : { return Ops::fetchAndStoreAcquire(_q_value, newValue); }
164 : T fetchAndStoreRelease(T newValue) Q_DECL_NOTHROW
165 : { return Ops::fetchAndStoreRelease(_q_value, newValue); }
166 : T fetchAndStoreOrdered(T newValue) Q_DECL_NOTHROW
167 : { return Ops::fetchAndStoreOrdered(_q_value, newValue); }
168 :
169 : static Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return Ops::isFetchAndAddNative(); }
170 : static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndAddWaitFree(); }
171 :
172 : T fetchAndAddRelaxed(T valueToAdd) Q_DECL_NOTHROW
173 : { return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
174 : T fetchAndAddAcquire(T valueToAdd) Q_DECL_NOTHROW
175 : { return Ops::fetchAndAddAcquire(_q_value, valueToAdd); }
176 : T fetchAndAddRelease(T valueToAdd) Q_DECL_NOTHROW
177 : { return Ops::fetchAndAddRelease(_q_value, valueToAdd); }
178 : T fetchAndAddOrdered(T valueToAdd) Q_DECL_NOTHROW
179 : { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
180 :
181 : T fetchAndSubRelaxed(T valueToAdd) Q_DECL_NOTHROW
182 : { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
183 : T fetchAndSubAcquire(T valueToAdd) Q_DECL_NOTHROW
184 : { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
185 : T fetchAndSubRelease(T valueToAdd) Q_DECL_NOTHROW
186 : { return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
187 : T fetchAndSubOrdered(T valueToAdd) Q_DECL_NOTHROW
188 : { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
189 :
190 : T fetchAndAndRelaxed(T valueToAdd) Q_DECL_NOTHROW
191 : { return Ops::fetchAndAndRelaxed(_q_value, valueToAdd); }
192 : T fetchAndAndAcquire(T valueToAdd) Q_DECL_NOTHROW
193 : { return Ops::fetchAndAndAcquire(_q_value, valueToAdd); }
194 : T fetchAndAndRelease(T valueToAdd) Q_DECL_NOTHROW
195 : { return Ops::fetchAndAndRelease(_q_value, valueToAdd); }
196 : T fetchAndAndOrdered(T valueToAdd) Q_DECL_NOTHROW
197 : { return Ops::fetchAndAndOrdered(_q_value, valueToAdd); }
198 :
199 : T fetchAndOrRelaxed(T valueToAdd) Q_DECL_NOTHROW
200 : { return Ops::fetchAndOrRelaxed(_q_value, valueToAdd); }
201 : T fetchAndOrAcquire(T valueToAdd) Q_DECL_NOTHROW
202 : { return Ops::fetchAndOrAcquire(_q_value, valueToAdd); }
203 : T fetchAndOrRelease(T valueToAdd) Q_DECL_NOTHROW
204 : { return Ops::fetchAndOrRelease(_q_value, valueToAdd); }
205 : T fetchAndOrOrdered(T valueToAdd) Q_DECL_NOTHROW
206 : { return Ops::fetchAndOrOrdered(_q_value, valueToAdd); }
207 :
208 : T fetchAndXorRelaxed(T valueToAdd) Q_DECL_NOTHROW
209 : { return Ops::fetchAndXorRelaxed(_q_value, valueToAdd); }
210 : T fetchAndXorAcquire(T valueToAdd) Q_DECL_NOTHROW
211 : { return Ops::fetchAndXorAcquire(_q_value, valueToAdd); }
212 : T fetchAndXorRelease(T valueToAdd) Q_DECL_NOTHROW
213 : { return Ops::fetchAndXorRelease(_q_value, valueToAdd); }
214 : T fetchAndXorOrdered(T valueToAdd) Q_DECL_NOTHROW
215 : { return Ops::fetchAndXorOrdered(_q_value, valueToAdd); }
216 :
217 : T operator++() Q_DECL_NOTHROW
218 : { return fetchAndAddOrdered(1) + 1; }
219 : T operator++(int) Q_DECL_NOTHROW
220 : { return fetchAndAddOrdered(1); }
221 : T operator--() Q_DECL_NOTHROW
222 : { return fetchAndSubOrdered(1) - 1; }
223 : T operator--(int) Q_DECL_NOTHROW
224 : { return fetchAndSubOrdered(1); }
225 :
226 : T operator+=(T v) Q_DECL_NOTHROW
227 : { return fetchAndAddOrdered(v) + v; }
228 : T operator-=(T v) Q_DECL_NOTHROW
229 : { return fetchAndSubOrdered(v) - v; }
230 : T operator&=(T v) Q_DECL_NOTHROW
231 : { return fetchAndAndOrdered(v) & v; }
232 : T operator|=(T v) Q_DECL_NOTHROW
233 : { return fetchAndOrOrdered(v) | v; }
234 : T operator^=(T v) Q_DECL_NOTHROW
235 : { return fetchAndXorOrdered(v) ^ v; }
236 :
237 :
238 : #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
239 : QBasicAtomicInteger() = default;
240 78 : constexpr QBasicAtomicInteger(T value) Q_DECL_NOTHROW : _q_value(value) {}
241 : QBasicAtomicInteger(const QBasicAtomicInteger &) = delete;
242 : QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) = delete;
243 : QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) volatile = delete;
244 : #endif
245 : };
246 : typedef QBasicAtomicInteger<int> QBasicAtomicInt;
247 :
248 : template <typename X>
249 : class QBasicAtomicPointer
250 : {
251 : public:
252 : typedef X *Type;
253 : typedef QAtomicOps<Type> Ops;
254 : typedef typename Ops::Type AtomicType;
255 :
256 : AtomicType _q_value;
257 :
258 : Type load() const Q_DECL_NOTHROW { return _q_value; }
259 : void store(Type newValue) Q_DECL_NOTHROW { _q_value = newValue; }
260 : operator Type() const Q_DECL_NOTHROW { return loadAcquire(); }
261 : Type operator=(Type newValue) Q_DECL_NOTHROW { storeRelease(newValue); return newValue; }
262 :
263 : // Atomic API, implemented in qatomic_XXX.h
264 : Type loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); }
265 : void storeRelease(Type newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); }
266 :
267 : static Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return Ops::isTestAndSetNative(); }
268 : static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return Ops::isTestAndSetWaitFree(); }
269 :
270 : bool testAndSetRelaxed(Type expectedValue, Type newValue) Q_DECL_NOTHROW
271 : { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
272 : bool testAndSetAcquire(Type expectedValue, Type newValue) Q_DECL_NOTHROW
273 : { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); }
274 : bool testAndSetRelease(Type expectedValue, Type newValue) Q_DECL_NOTHROW
275 : { return Ops::testAndSetRelease(_q_value, expectedValue, newValue); }
276 : bool testAndSetOrdered(Type expectedValue, Type newValue) Q_DECL_NOTHROW
277 : { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
278 :
279 : bool testAndSetRelaxed(Type expectedValue, Type newValue, Type ¤tValue) Q_DECL_NOTHROW
280 : { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, ¤tValue); }
281 : bool testAndSetAcquire(Type expectedValue, Type newValue, Type ¤tValue) Q_DECL_NOTHROW
282 : { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, ¤tValue); }
283 : bool testAndSetRelease(Type expectedValue, Type newValue, Type ¤tValue) Q_DECL_NOTHROW
284 : { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, ¤tValue); }
285 : bool testAndSetOrdered(Type expectedValue, Type newValue, Type ¤tValue) Q_DECL_NOTHROW
286 : { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, ¤tValue); }
287 :
288 : static Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return Ops::isFetchAndStoreNative(); }
289 : static Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndStoreWaitFree(); }
290 :
291 : Type fetchAndStoreRelaxed(Type newValue) Q_DECL_NOTHROW
292 : { return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
293 : Type fetchAndStoreAcquire(Type newValue) Q_DECL_NOTHROW
294 : { return Ops::fetchAndStoreAcquire(_q_value, newValue); }
295 : Type fetchAndStoreRelease(Type newValue) Q_DECL_NOTHROW
296 : { return Ops::fetchAndStoreRelease(_q_value, newValue); }
297 : Type fetchAndStoreOrdered(Type newValue) Q_DECL_NOTHROW
298 : { return Ops::fetchAndStoreOrdered(_q_value, newValue); }
299 :
300 : static Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return Ops::isFetchAndAddNative(); }
301 : static Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return Ops::isFetchAndAddWaitFree(); }
302 :
303 : Type fetchAndAddRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW
304 : { return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
305 : Type fetchAndAddAcquire(qptrdiff valueToAdd) Q_DECL_NOTHROW
306 : { return Ops::fetchAndAddAcquire(_q_value, valueToAdd); }
307 : Type fetchAndAddRelease(qptrdiff valueToAdd) Q_DECL_NOTHROW
308 : { return Ops::fetchAndAddRelease(_q_value, valueToAdd); }
309 : Type fetchAndAddOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW
310 : { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
311 :
312 : Type fetchAndSubRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW
313 : { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
314 : Type fetchAndSubAcquire(qptrdiff valueToAdd) Q_DECL_NOTHROW
315 : { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
316 : Type fetchAndSubRelease(qptrdiff valueToAdd) Q_DECL_NOTHROW
317 : { return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
318 : Type fetchAndSubOrdered(qptrdiff valueToAdd) Q_DECL_NOTHROW
319 : { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
320 :
321 : Type operator++() Q_DECL_NOTHROW
322 : { return fetchAndAddOrdered(1) + 1; }
323 : Type operator++(int) Q_DECL_NOTHROW
324 : { return fetchAndAddOrdered(1); }
325 : Type operator--() Q_DECL_NOTHROW
326 : { return fetchAndSubOrdered(1) - 1; }
327 : Type operator--(int) Q_DECL_NOTHROW
328 : { return fetchAndSubOrdered(1); }
329 : Type operator+=(qptrdiff valueToAdd) Q_DECL_NOTHROW
330 : { return fetchAndAddOrdered(valueToAdd) + valueToAdd; }
331 : Type operator-=(qptrdiff valueToSub) Q_DECL_NOTHROW
332 : { return fetchAndSubOrdered(valueToSub) - valueToSub; }
333 :
334 : #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
335 : QBasicAtomicPointer() = default;
336 : constexpr QBasicAtomicPointer(Type value) Q_DECL_NOTHROW : _q_value(value) {}
337 : QBasicAtomicPointer(const QBasicAtomicPointer &) = delete;
338 : QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) = delete;
339 : QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) volatile = delete;
340 : #endif
341 : };
342 :
343 : #ifndef Q_BASIC_ATOMIC_INITIALIZER
344 : # define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) }
345 : #endif
346 :
347 : QT_END_NAMESPACE
348 :
349 : #endif // QBASICATOMIC_H
|