| 259 | namespace moodycamel { |
| 260 | template<typename T> |
| 261 | class weak_atomic |
| 262 | { |
| 263 | public: |
| 264 | AE_NO_TSAN weak_atomic() : value() { } |
| 265 | #ifdef AE_VCPP |
| 266 | #pragma warning(push) |
| 267 | #pragma warning(disable: 4100) // Get rid of (erroneous) 'unreferenced formal parameter' warning |
| 268 | #endif |
| 269 | template<typename U> AE_NO_TSAN weak_atomic(U&& x) : value(std::forward<U>(x)) { } |
| 270 | #ifdef __cplusplus_cli |
| 271 | // Work around bug with universal reference/nullptr combination that only appears when /clr is on |
| 272 | AE_NO_TSAN weak_atomic(nullptr_t) : value(nullptr) { } |
| 273 | #endif |
| 274 | AE_NO_TSAN weak_atomic(weak_atomic const& other) : value(other.load()) { } |
| 275 | AE_NO_TSAN weak_atomic(weak_atomic&& other) : value(std::move(other.load())) { } |
| 276 | #ifdef AE_VCPP |
| 277 | #pragma warning(pop) |
| 278 | #endif |
| 279 | |
| 280 | AE_FORCEINLINE operator T() const AE_NO_TSAN { return load(); } |
| 281 | |
| 282 | |
| 283 | #ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC |
| 284 | template<typename U> AE_FORCEINLINE weak_atomic const& operator=(U&& x) AE_NO_TSAN { value = std::forward<U>(x); return *this; } |
| 285 | AE_FORCEINLINE weak_atomic const& operator=(weak_atomic const& other) AE_NO_TSAN { value = other.value; return *this; } |
| 286 | |
| 287 | AE_FORCEINLINE T load() const AE_NO_TSAN { return value; } |
| 288 | |
| 289 | AE_FORCEINLINE T fetch_add_acquire(T increment) AE_NO_TSAN |
| 290 | { |
| 291 | #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) |
| 292 | if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment); |
| 293 | #if defined(_M_AMD64) |
| 294 | else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment); |
| 295 | #endif |
| 296 | #else |
| 297 | #error Unsupported platform |
| 298 | #endif |
| 299 | assert(false && "T must be either a 32 or 64 bit type"); |
| 300 | return value; |
| 301 | } |
| 302 | |
| 303 | AE_FORCEINLINE T fetch_add_release(T increment) AE_NO_TSAN |
| 304 | { |
| 305 | #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) |
| 306 | if (sizeof(T) == 4) return _InterlockedExchangeAdd((long volatile*)&value, (long)increment); |
| 307 | #if defined(_M_AMD64) |
| 308 | else if (sizeof(T) == 8) return _InterlockedExchangeAdd64((long long volatile*)&value, (long long)increment); |
| 309 | #endif |
| 310 | #else |
| 311 | #error Unsupported platform |
| 312 | #endif |
| 313 | assert(false && "T must be either a 32 or 64 bit type"); |
| 314 | return value; |
| 315 | } |
| 316 | #else |
| 317 | template<typename U> |
| 318 | AE_FORCEINLINE weak_atomic const& operator=(U&& x) AE_NO_TSAN |