File indexing completed on 2026-05-11 08:50:22
0001
0002
0003
0004
0005
0006 #ifndef QATOMIC_CXX11_H
0007 #define QATOMIC_CXX11_H
0008
0009 #include <QtCore/qgenericatomic.h>
0010 #include <QtCore/qyieldcpu.h>
0011 #include <atomic>
0012
0013 QT_BEGIN_NAMESPACE
0014
0015 #if 0
0016
0017 QT_END_NAMESPACE
0018 #pragma qt_sync_skip_header_check
0019 #pragma qt_sync_stop_processing
0020 #endif
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 template <int N> struct QAtomicTraits
0040 { static inline bool isLockFree(); };
0041
0042 #define Q_ATOMIC_INT32_IS_SUPPORTED
0043 #if ATOMIC_INT_LOCK_FREE == 2
0044 # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0045 # define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
0046 # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0047 # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0048 # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0049 # define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE
0050 # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0051 # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0052
0053 template <> inline bool QAtomicTraits<4>::isLockFree()
0054 { return true; }
0055 #elif ATOMIC_INT_LOCK_FREE == 1
0056 # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0057 # define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE
0058 # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0059 # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0060 # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0061 # define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE
0062 # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0063 # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0064
0065 template <> inline bool QAtomicTraits<4>::isLockFree()
0066 { return false; }
0067 #else
0068 # define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NEVER_NATIVE
0069 # define Q_ATOMIC_INT_TEST_AND_SET_IS_NEVER_NATIVE
0070 # define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NEVER_NATIVE
0071 # define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NEVER_NATIVE
0072 # define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NEVER_NATIVE
0073 # define Q_ATOMIC_INT32_TEST_AND_SET_IS_NEVER_NATIVE
0074 # define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NEVER_NATIVE
0075 # define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NEVER_NATIVE
0076
0077 template <> inline bool QAtomicTraits<4>::isLockFree()
0078 { return false; }
0079 #endif
0080
0081 #if ATOMIC_POINTER_LOCK_FREE == 2
0082 # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0083 # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
0084 # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0085 # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0086 #elif ATOMIC_POINTER_LOCK_FREE == 1
0087 # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0088 # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE
0089 # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0090 # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0091 #else
0092 # define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_NEVER_NATIVE
0093 # define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NEVER_NATIVE
0094 # define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NEVER_NATIVE
0095 # define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NEVER_NATIVE
0096 #endif
0097
0098 template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; };
0099 #define Q_ATOMIC_INT8_IS_SUPPORTED
0100 #if ATOMIC_CHAR_LOCK_FREE == 2
0101 # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0102 # define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE
0103 # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0104 # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0105
0106 template <> inline bool QAtomicTraits<1>::isLockFree()
0107 { return true; }
0108 #elif ATOMIC_CHAR_LOCK_FREE == 1
0109 # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0110 # define Q_ATOMIC_INT8_TEST_AND_SET_IS_SOMETIMES_NATIVE
0111 # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0112 # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0113
0114 template <> inline bool QAtomicTraits<1>::isLockFree()
0115 { return false; }
0116 #else
0117 # define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_NEVER_NATIVE
0118 # define Q_ATOMIC_INT8_TEST_AND_SET_IS_NEVER_NATIVE
0119 # define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_NEVER_NATIVE
0120 # define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_NEVER_NATIVE
0121
0122 template <> bool QAtomicTraits<1>::isLockFree()
0123 { return false; }
0124 #endif
0125
0126 template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; };
0127 #define Q_ATOMIC_INT16_IS_SUPPORTED
0128 #if ATOMIC_SHORT_LOCK_FREE == 2
0129 # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0130 # define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE
0131 # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0132 # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0133
0134 template <> inline bool QAtomicTraits<2>::isLockFree()
0135 { return false; }
0136 #elif ATOMIC_SHORT_LOCK_FREE == 1
0137 # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0138 # define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE
0139 # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0140 # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0141
0142 template <> inline bool QAtomicTraits<2>::isLockFree()
0143 { return false; }
0144 #else
0145 # define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE
0146 # define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE
0147 # define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE
0148 # define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE
0149
0150 template <> inline bool QAtomicTraits<2>::isLockFree()
0151 { return false; }
0152 #endif
0153
0154 #if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(std_atomic64)
0155 template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
0156 # define Q_ATOMIC_INT64_IS_SUPPORTED
0157 # if ATOMIC_LLONG_LOCK_FREE == 2
0158 # define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
0159 # define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE
0160 # define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
0161 # define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
0162
0163 template <> inline bool QAtomicTraits<8>::isLockFree()
0164 { return true; }
0165 # elif ATOMIC_LLONG_LOCK_FREE == 1
0166 # define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE
0167 # define Q_ATOMIC_INT64_TEST_AND_SET_IS_SOMETIMES_NATIVE
0168 # define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_SOMETIMES_NATIVE
0169 # define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_SOMETIMES_NATIVE
0170
0171 template <> inline bool QAtomicTraits<8>::isLockFree()
0172 { return false; }
0173 # else
0174 # define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_NEVER_NATIVE
0175 # define Q_ATOMIC_INT64_TEST_AND_SET_IS_NEVER_NATIVE
0176 # define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_NEVER_NATIVE
0177 # define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_NEVER_NATIVE
0178
0179 template <> inline bool QAtomicTraits<8>::isLockFree()
0180 { return false; }
0181 # endif
0182 #endif
0183
0184 template <typename X> struct QAtomicOps
0185 {
0186 typedef std::atomic<X> Type;
0187
0188 template <typename T> static inline
0189 T load(const std::atomic<T> &_q_value) noexcept
0190 {
0191 return _q_value.load(std::memory_order_relaxed);
0192 }
0193
0194 template <typename T> static inline
0195 T load(const volatile std::atomic<T> &_q_value) noexcept
0196 {
0197 return _q_value.load(std::memory_order_relaxed);
0198 }
0199
0200 template <typename T> static inline
0201 T loadRelaxed(const std::atomic<T> &_q_value) noexcept
0202 {
0203 return _q_value.load(std::memory_order_relaxed);
0204 }
0205
0206 template <typename T> static inline
0207 T loadRelaxed(const volatile std::atomic<T> &_q_value) noexcept
0208 {
0209 return _q_value.load(std::memory_order_relaxed);
0210 }
0211
0212 template <typename T> static inline
0213 T loadAcquire(const std::atomic<T> &_q_value) noexcept
0214 {
0215 return _q_value.load(std::memory_order_acquire);
0216 }
0217
0218 template <typename T> static inline
0219 T loadAcquire(const volatile std::atomic<T> &_q_value) noexcept
0220 {
0221 return _q_value.load(std::memory_order_acquire);
0222 }
0223
0224 template <typename T> static inline
0225 void store(std::atomic<T> &_q_value, T newValue) noexcept
0226 {
0227 _q_value.store(newValue, std::memory_order_relaxed);
0228 }
0229
0230 template <typename T> static inline
0231 void storeRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
0232 {
0233 _q_value.store(newValue, std::memory_order_relaxed);
0234 }
0235
0236 template <typename T> static inline
0237 void storeRelease(std::atomic<T> &_q_value, T newValue) noexcept
0238 {
0239 _q_value.store(newValue, std::memory_order_release);
0240 }
0241
0242 static inline bool isReferenceCountingNative() noexcept { return isTestAndSetNative(); }
0243 static inline constexpr bool isReferenceCountingWaitFree() noexcept { return false; }
0244 template <typename T>
0245 static inline bool ref(std::atomic<T> &_q_value)
0246 {
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 return _q_value.fetch_add(1, std::memory_order_acq_rel) != T(-1);
0261 }
0262
0263 template <typename T>
0264 static inline bool deref(std::atomic<T> &_q_value) noexcept
0265 {
0266
0267 return _q_value.fetch_sub(1, std::memory_order_acq_rel) != T(1);
0268 }
0269
0270 static inline bool isTestAndSetNative() noexcept
0271 { return QAtomicTraits<sizeof(X)>::isLockFree(); }
0272 static inline constexpr bool isTestAndSetWaitFree() noexcept { return false; }
0273
0274 template <typename T>
0275 static bool testAndSetRelaxed(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
0276 {
0277 bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_relaxed, std::memory_order_relaxed);
0278 if (currentValue)
0279 *currentValue = expectedValue;
0280 return tmp;
0281 }
0282
0283 template <typename T>
0284 static bool testAndSetAcquire(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
0285 {
0286 bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acquire, std::memory_order_acquire);
0287 if (currentValue)
0288 *currentValue = expectedValue;
0289 return tmp;
0290 }
0291
0292 template <typename T>
0293 static bool testAndSetRelease(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
0294 {
0295 bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_release, std::memory_order_relaxed);
0296 if (currentValue)
0297 *currentValue = expectedValue;
0298 return tmp;
0299 }
0300
0301 template <typename T>
0302 static bool testAndSetOrdered(std::atomic<T> &_q_value, T expectedValue, T newValue, T *currentValue = nullptr) noexcept
0303 {
0304 bool tmp = _q_value.compare_exchange_strong(expectedValue, newValue, std::memory_order_acq_rel, std::memory_order_acquire);
0305 if (currentValue)
0306 *currentValue = expectedValue;
0307 return tmp;
0308 }
0309
0310 static inline bool isFetchAndStoreNative() noexcept { return isTestAndSetNative(); }
0311 static inline constexpr bool isFetchAndStoreWaitFree() noexcept { return false; }
0312
0313 template <typename T>
0314 static T fetchAndStoreRelaxed(std::atomic<T> &_q_value, T newValue) noexcept
0315 {
0316 return _q_value.exchange(newValue, std::memory_order_relaxed);
0317 }
0318
0319 template <typename T>
0320 static T fetchAndStoreAcquire(std::atomic<T> &_q_value, T newValue) noexcept
0321 {
0322 return _q_value.exchange(newValue, std::memory_order_acquire);
0323 }
0324
0325 template <typename T>
0326 static T fetchAndStoreRelease(std::atomic<T> &_q_value, T newValue) noexcept
0327 {
0328 return _q_value.exchange(newValue, std::memory_order_release);
0329 }
0330
0331 template <typename T>
0332 static T fetchAndStoreOrdered(std::atomic<T> &_q_value, T newValue) noexcept
0333 {
0334 return _q_value.exchange(newValue, std::memory_order_acq_rel);
0335 }
0336
0337 static inline bool isFetchAndAddNative() noexcept { return isTestAndSetNative(); }
0338 static inline constexpr bool isFetchAndAddWaitFree() noexcept { return false; }
0339
0340 template <typename T> static inline
0341 T fetchAndAddRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0342 {
0343 return _q_value.fetch_add(valueToAdd, std::memory_order_relaxed);
0344 }
0345
0346 template <typename T> static inline
0347 T fetchAndAddAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0348 {
0349 return _q_value.fetch_add(valueToAdd, std::memory_order_acquire);
0350 }
0351
0352 template <typename T> static inline
0353 T fetchAndAddRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0354 {
0355 return _q_value.fetch_add(valueToAdd, std::memory_order_release);
0356 }
0357
0358 template <typename T> static inline
0359 T fetchAndAddOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0360 {
0361 return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel);
0362 }
0363
0364 template <typename T> static inline
0365 T fetchAndSubRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0366 {
0367 return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed);
0368 }
0369
0370 template <typename T> static inline
0371 T fetchAndSubAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0372 {
0373 return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire);
0374 }
0375
0376 template <typename T> static inline
0377 T fetchAndSubRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0378 {
0379 return _q_value.fetch_sub(valueToAdd, std::memory_order_release);
0380 }
0381
0382 template <typename T> static inline
0383 T fetchAndSubOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0384 {
0385 return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel);
0386 }
0387
0388 template <typename T> static inline
0389 T fetchAndAndRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0390 {
0391 return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed);
0392 }
0393
0394 template <typename T> static inline
0395 T fetchAndAndAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0396 {
0397 return _q_value.fetch_and(valueToAdd, std::memory_order_acquire);
0398 }
0399
0400 template <typename T> static inline
0401 T fetchAndAndRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0402 {
0403 return _q_value.fetch_and(valueToAdd, std::memory_order_release);
0404 }
0405
0406 template <typename T> static inline
0407 T fetchAndAndOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0408 {
0409 return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel);
0410 }
0411
0412 template <typename T> static inline
0413 T fetchAndOrRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0414 {
0415 return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed);
0416 }
0417
0418 template <typename T> static inline
0419 T fetchAndOrAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0420 {
0421 return _q_value.fetch_or(valueToAdd, std::memory_order_acquire);
0422 }
0423
0424 template <typename T> static inline
0425 T fetchAndOrRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0426 {
0427 return _q_value.fetch_or(valueToAdd, std::memory_order_release);
0428 }
0429
0430 template <typename T> static inline
0431 T fetchAndOrOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0432 {
0433 return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel);
0434 }
0435
0436 template <typename T> static inline
0437 T fetchAndXorRelaxed(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0438 {
0439 return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed);
0440 }
0441
0442 template <typename T> static inline
0443 T fetchAndXorAcquire(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0444 {
0445 return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire);
0446 }
0447
0448 template <typename T> static inline
0449 T fetchAndXorRelease(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0450 {
0451 return _q_value.fetch_xor(valueToAdd, std::memory_order_release);
0452 }
0453
0454 template <typename T> static inline
0455 T fetchAndXorOrdered(std::atomic<T> &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) noexcept
0456 {
0457 return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel);
0458 }
0459 };
0460
0461 # define Q_BASIC_ATOMIC_INITIALIZER(a) { a }
0462
0463 QT_END_NAMESPACE
0464
0465 #endif