#pragma once #include "atomic.h" #include template inline TAtomic* AsAtomicPtr(T volatile* target) { return reinterpret_cast(target); } template inline const TAtomic* AsAtomicPtr(T const volatile* target) { return reinterpret_cast(target); } // integral types template struct TAtomicTraits { enum { Castable = std::is_integral::value && sizeof(T) == sizeof(TAtomicBase) && !std::is_const::value, }; }; template using TEnableIfCastable = std::enable_if_t::Castable, TT>; template inline TEnableIfCastable AtomicGet(T const volatile& target) { return static_cast(AtomicGet(*AsAtomicPtr(&target))); } template inline TEnableIfCastable AtomicSet(T volatile& target, TAtomicBase value) { AtomicSet(*AsAtomicPtr(&target), value); } template inline TEnableIfCastable AtomicIncrement(T volatile& target) { return static_cast(AtomicIncrement(*AsAtomicPtr(&target))); } template inline TEnableIfCastable AtomicGetAndIncrement(T volatile& target) { return static_cast(AtomicGetAndIncrement(*AsAtomicPtr(&target))); } template inline TEnableIfCastable AtomicDecrement(T volatile& target) { return static_cast(AtomicDecrement(*AsAtomicPtr(&target))); } template inline TEnableIfCastable AtomicGetAndDecrement(T volatile& target) { return static_cast(AtomicGetAndDecrement(*AsAtomicPtr(&target))); } template inline TEnableIfCastable AtomicAdd(T volatile& target, TAtomicBase value) { return static_cast(AtomicAdd(*AsAtomicPtr(&target), value)); } template inline TEnableIfCastable AtomicGetAndAdd(T volatile& target, TAtomicBase value) { return static_cast(AtomicGetAndAdd(*AsAtomicPtr(&target), value)); } template inline TEnableIfCastable AtomicSub(T volatile& target, TAtomicBase value) { return static_cast(AtomicSub(*AsAtomicPtr(&target), value)); } template inline TEnableIfCastable AtomicGetAndSub(T volatile& target, TAtomicBase value) { return static_cast(AtomicGetAndSub(*AsAtomicPtr(&target), value)); } template inline TEnableIfCastable AtomicSwap(T volatile* target, TAtomicBase exchange) { return static_cast(AtomicSwap(AsAtomicPtr(target), exchange)); } template inline TEnableIfCastable AtomicCas(T volatile* target, TAtomicBase exchange, TAtomicBase compare) { return AtomicCas(AsAtomicPtr(target), exchange, compare); } template inline TEnableIfCastable AtomicGetAndCas(T volatile* target, TAtomicBase exchange, TAtomicBase compare) { return static_cast(AtomicGetAndCas(AsAtomicPtr(target), exchange, compare)); } template inline TEnableIfCastable AtomicTryLock(T volatile* target) { return AtomicTryLock(AsAtomicPtr(target)); } template inline TEnableIfCastable AtomicTryAndTryLock(T volatile* target) { return AtomicTryAndTryLock(AsAtomicPtr(target)); } template inline TEnableIfCastable AtomicUnlock(T volatile* target) { AtomicUnlock(AsAtomicPtr(target)); } template inline TEnableIfCastable AtomicOr(T volatile& target, TAtomicBase value) { return static_cast(AtomicOr(*AsAtomicPtr(&target), value)); } template inline TEnableIfCastable AtomicAnd(T volatile& target, TAtomicBase value) { return static_cast(AtomicAnd(*AsAtomicPtr(&target), value)); } template inline TEnableIfCastable AtomicXor(T volatile& target, TAtomicBase value) { return static_cast(AtomicXor(*AsAtomicPtr(&target), value)); } // pointer types template inline T* AtomicGet(T* const volatile& target) { return reinterpret_cast(AtomicGet(*AsAtomicPtr(&target))); } template inline void AtomicSet(T* volatile& target, T* value) { AtomicSet(*AsAtomicPtr(&target), reinterpret_cast(value)); } using TNullPtr = decltype(nullptr); template inline void AtomicSet(T* volatile& target, TNullPtr) { AtomicSet(*AsAtomicPtr(&target), 0); } template inline T* AtomicSwap(T* volatile* target, T* exchange) { return reinterpret_cast(AtomicSwap(AsAtomicPtr(target), reinterpret_cast(exchange))); } template inline T* AtomicSwap(T* volatile* target, TNullPtr) { return reinterpret_cast(AtomicSwap(AsAtomicPtr(target), 0)); } template inline bool AtomicCas(T* volatile* target, T* exchange, T* compare) { return AtomicCas(AsAtomicPtr(target), reinterpret_cast(exchange), reinterpret_cast(compare)); } template inline T* AtomicGetAndCas(T* volatile* target, T* exchange, T* compare) { return reinterpret_cast(AtomicGetAndCas(AsAtomicPtr(target), reinterpret_cast(exchange), reinterpret_cast(compare))); } template inline bool AtomicCas(T* volatile* target, T* exchange, TNullPtr) { return AtomicCas(AsAtomicPtr(target), reinterpret_cast(exchange), 0); } template inline T* AtomicGetAndCas(T* volatile* target, T* exchange, TNullPtr) { return reinterpret_cast(AtomicGetAndCas(AsAtomicPtr(target), reinterpret_cast(exchange), 0)); } template inline bool AtomicCas(T* volatile* target, TNullPtr, T* compare) { return AtomicCas(AsAtomicPtr(target), 0, reinterpret_cast(compare)); } template inline T* AtomicGetAndCas(T* volatile* target, TNullPtr, T* compare) { return reinterpret_cast(AtomicGetAndCas(AsAtomicPtr(target), 0, reinterpret_cast(compare))); } template inline bool AtomicCas(T* volatile* target, TNullPtr, TNullPtr) { return AtomicCas(AsAtomicPtr(target), 0, 0); } template inline T* AtomicGetAndCas(T* volatile* target, TNullPtr, TNullPtr) { return reinterpret_cast(AtomicGetAndCas(AsAtomicPtr(target), 0, 0)); }