Line data Source code
1 : /****************************************************************************
2 : **
3 : ** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
4 : ** Copyright (C) 2016 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 : #ifndef QATOMIC_CXX11_H
42 : #define QATOMIC_CXX11_H
43 :
44 : #include <QtCore/qgenericatomic.h>
45 : #include <atomic>
46 :
47 : QT_BEGIN_NAMESPACE
48 :
49 : #if 0
50 : // silence syncqt warnings
51 : QT_END_NAMESPACE
52 : #pragma qt_sync_skip_header_check
53 : #pragma qt_sync_stop_processing
54 : #endif
55 :
56 : /* Attempt to detect whether the atomic operations exist in hardware
57 : * or whether they are emulated by way of a lock.
58 : *
59 : * C++11 29.4 [atomics.lockfree] p1 says
60 : *
61 : * The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the
62 : * corresponding atomic types, with the signed and unsigned variants grouped
63 : * together. The properties also apply to the corresponding (partial)
64 : * specializations of the atomic template. A value of 0 indicates that the
65 : * types are never lock-free. A value of 1 indicates that the types are
66 : * sometimes lock-free. A value of 2 indicates that the types are always
67 : * lock-free.
68 : *
69 : * We have a problem when the value is 1: we'd need to check at runtime, but
70 : * QAtomicInteger requires a constexpr answer (defect introduced in Qt 5.0). So
71 : * we'll err in the side of caution and say it isn't.
72 : */
73 :
74 : // ### Qt 6: make non-constexpr (see above)
75 : template <int N> struct QAtomicTraits
76 : { static Q_DECL_CONSTEXPR inline bool isLockFree(); };
77 :
78 : #define Q_ATOMIC_INT32_IS_SUPPORTED
79 : #if ATOMIC_INT_LOCK_FREE == 2
80 : # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
81 : # define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
82 : # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
83 : # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
84 : # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
85 : # define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE
86 : # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
87 : # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
88 :
89 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree()
90 : { return true; }
91 : #elif ATOMIC_INT_LOCK_FREE == 1
92 : # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
93 : # define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE
94 : # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
95 : # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
96 : # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
97 : # define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE
98 : # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
99 : # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
100 :
101 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree()
102 : { return false; }
103 : #else
104 : # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NEVER_NATIVE
105 : # define Q_ATOMIC_INT_TEST_AND_SET_IS_NEVER_NATIVE
106 : # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NEVER_NATIVE
107 : # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NEVER_NATIVE
108 : # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NEVER_NATIVE
109 : # define Q_ATOMIC_INT32_TEST_AND_SET_IS_NEVER_NATIVE
110 : # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NEVER_NATIVE
111 : # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NEVER_NATIVE
112 :
113 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree()
114 : { return false; }
115 : #endif
116 :
117 : #if ATOMIC_POINTER_LOCK_FREE == 2
118 : # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
119 : # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
120 : # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
121 : # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
122 : #elif ATOMIC_POINTER_LOCK_FREE == 1
123 : # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
124 : # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE
125 : # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
126 : # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
127 : #else
128 : # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_NEVER_NATIVE
129 : # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NEVER_NATIVE
130 : # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NEVER_NATIVE
131 : # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NEVER_NATIVE
132 : #endif
133 :
134 : template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; };
135 : #define Q_ATOMIC_INT8_IS_SUPPORTED
136 : #if ATOMIC_CHAR_LOCK_FREE == 2
137 : # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
138 : # define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE
139 : # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE
140 : # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE
141 :
142 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree()
143 : { return true; }
144 : #elif ATOMIC_CHAR_LOCK_FREE == 1
145 : # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
146 : # define Q_ATOMIC_INT8_TEST_AND_SET_IS_SOMETIMES_NATIVE
147 : # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
148 : # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
149 :
150 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree()
151 : { return false; }
152 : #else
153 : # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_NEVER_NATIVE
154 : # define Q_ATOMIC_INT8_TEST_AND_SET_IS_NEVER_NATIVE
155 : # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_NEVER_NATIVE
156 : # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_NEVER_NATIVE
157 :
158 : template <> Q_DECL_CONSTEXPR bool QAtomicTraits<1>::isLockFree()
159 : { return false; }
160 : #endif
161 :
162 : template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; };
163 : #define Q_ATOMIC_INT16_IS_SUPPORTED
164 : #if ATOMIC_SHORT_LOCK_FREE == 2
165 : # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
166 : # define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
167 : # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
168 : # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
169 :
170 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
171 : { return false; }
172 : #elif ATOMIC_SHORT_LOCK_FREE == 1
173 : # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
174 : # define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE
175 : # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
176 : # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
177 :
178 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
179 : { return false; }
180 : #else
181 : # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE
182 : # define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE
183 : # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE
184 : # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE
185 :
186 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree()
187 : { return false; }
188 : #endif
189 :
190 : #if QT_CONFIG(std_atomic64)
191 : template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
192 : # define Q_ATOMIC_INT64_IS_SUPPORTED
193 : # if ATOMIC_LLONG_LOCK_FREE == 2
194 : # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
195 : # define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
196 : # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
197 : # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
198 :
199 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
200 : { return true; }
201 : # elif ATOMIC_LLONG_LOCK_FREE == 1
202 : # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
203 : # define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE
204 : # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
205 : # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
206 :
207 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
208 : { return false; }
209 : # else
210 : # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE
211 : # define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE
212 : # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE
213 : # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE
214 :
215 : template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree()
216 : { return false; }
217 : # endif
218 : #endif
219 :
220 : template <typename X> struct QAtomicOps
221 : {
222 : typedef std::atomic<X> Type;
223 :
224 : template <typename T> static inline
225 24643 : T load(const std::atomic<T> &_q_value) Q_DECL_NOTHROW
226 : {
227 49263 : return _q_value.load(std::memory_order_relaxed);
228 : }
229 :
230 : template <typename T> static inline
231 : T load(const volatile std::atomic<T> &_q_value) Q_DECL_NOTHROW
232 : {
233 : return _q_value.load(std::memory_order_relaxed);
234 : }
235 :
236 : template <typename T> static inline
237 : T loadAcquire(const std::atomic<T> &_q_value) Q_DECL_NOTHROW
238 : {
239 : return _q_value.load(std::memory_order_acquire);
240 : }
241 :
242 : template <typename T> static inline
243 : T loadAcquire(const volatile std::atomic<T> &_q_value) Q_DECL_NOTHROW
244 : {
245 : return _q_value.load(std::memory_order_acquire);
246 : }
247 :
248 : template <typename T> static inline
249 : void store(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
250 : {
251 : _q_value.store(newValue, std::memory_order_relaxed);
252 : }
253 :
254 : template <typename T> static inline
255 : void storeRelease(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
256 : {
257 : _q_value.store(newValue, std::memory_order_release);
258 : }
259 :
260 : static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
261 : static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return false; }
262 : template <typename T>
263 5747 : static inline bool ref(std::atomic<T> &_q_value)
264 : {
265 5747 : return ++_q_value != 0;
266 : }
267 :
268 : template <typename T>
269 10336 : static inline bool deref(std::atomic<T> &_q_value) Q_DECL_NOTHROW
270 : {
271 10336 : return --_q_value != 0;
272 : }
273 :
274 : static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW
275 : { return QAtomicTraits<sizeof(X)>::isLockFree(); }
276 : static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; }
277 :
278 : template <typename T>
279 : static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW
280 : {
281 : bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
282 : if (currentValue)
283 : *currentValue = expectedValue;
284 : return tmp;
285 : }
286 :
287 : template <typename T>
288 : static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW
289 : {
290 : bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire);
291 : if (currentValue)
292 : *currentValue = expectedValue;
293 : return tmp;
294 : }
295 :
296 : template <typename T>
297 : static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW
298 : {
299 : bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed);
300 : if (currentValue)
301 : *currentValue = expectedValue;
302 : return tmp;
303 : }
304 :
305 : template <typename T>
306 : static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = Q_NULLPTR) Q_DECL_NOTHROW
307 : {
308 : bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire);
309 : if (currentValue)
310 : *currentValue = expectedValue;
311 : return tmp;
312 : }
313 :
314 : static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
315 : static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; }
316 :
317 : template <typename T>
318 : static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
319 : {
320 : return _q_value.exchange(newValue, std::memory_order_relaxed);
321 : }
322 :
323 : template <typename T>
324 : static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
325 : {
326 : return _q_value.exchange(newValue, std::memory_order_acquire);
327 : }
328 :
329 : template <typename T>
330 : static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
331 : {
332 : return _q_value.exchange(newValue, std::memory_order_release);
333 : }
334 :
335 : template <typename T>
336 : static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) Q_DECL_NOTHROW
337 : {
338 : return _q_value.exchange(newValue, std::memory_order_acq_rel);
339 : }
340 :
341 : static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return isTestAndSetNative(); }
342 : static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; }
343 :
344 : template <typename T> static inline
345 : T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
346 : {
347 : return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed);
348 : }
349 :
350 : template <typename T> static inline
351 : T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
352 : {
353 : return _q_value.fetch_add(valueToAdd, std::memory_order_acquire);
354 : }
355 :
356 : template <typename T> static inline
357 : T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
358 : {
359 : return _q_value.fetch_add(valueToAdd, std::memory_order_release);
360 : }
361 :
362 : template <typename T> static inline
363 : T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
364 : {
365 : return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel);
366 : }
367 :
368 : template <typename T> static inline
369 : T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
370 : {
371 : return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed);
372 : }
373 :
374 : template <typename T> static inline
375 : T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
376 : {
377 : return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire);
378 : }
379 :
380 : template <typename T> static inline
381 : T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
382 : {
383 : return _q_value.fetch_sub(valueToAdd, std::memory_order_release);
384 : }
385 :
386 : template <typename T> static inline
387 : T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
388 : {
389 : return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel);
390 : }
391 :
392 : template <typename T> static inline
393 : T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
394 : {
395 : return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed);
396 : }
397 :
398 : template <typename T> static inline
399 : T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
400 : {
401 : return _q_value.fetch_and(valueToAdd, std::memory_order_acquire);
402 : }
403 :
404 : template <typename T> static inline
405 : T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
406 : {
407 : return _q_value.fetch_and(valueToAdd, std::memory_order_release);
408 : }
409 :
410 : template <typename T> static inline
411 : T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
412 : {
413 : return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel);
414 : }
415 :
416 : template <typename T> static inline
417 : T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
418 : {
419 : return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed);
420 : }
421 :
422 : template <typename T> static inline
423 : T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
424 : {
425 : return _q_value.fetch_or(valueToAdd, std::memory_order_acquire);
426 : }
427 :
428 : template <typename T> static inline
429 : T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
430 : {
431 : return _q_value.fetch_or(valueToAdd, std::memory_order_release);
432 : }
433 :
434 : template <typename T> static inline
435 : T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
436 : {
437 : return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel);
438 : }
439 :
440 : template <typename T> static inline
441 : T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
442 : {
443 : return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed);
444 : }
445 :
446 : template <typename T> static inline
447 : T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
448 : {
449 : return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire);
450 : }
451 :
452 : template <typename T> static inline
453 : T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
454 : {
455 : return _q_value.fetch_xor(valueToAdd, std::memory_order_release);
456 : }
457 :
458 : template <typename T> static inline
459 : T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW
460 : {
461 : return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel);
462 : }
463 : };
464 :
465 : #if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
466 : # define Q_BASIC_ATOMIC_INITIALIZER(a) { a }
467 : #else
468 : # define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) }
469 : #endif
470 :
471 : QT_END_NAMESPACE
472 :
473 : #endif // QATOMIC_CXX0X_H
|