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