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