//----------------------------------------------------------------------------- // This is free and unencumbered software released into the public domain. // // Anyone is free to copy, modify, publish, use, compile, sell, or distribute // this software, either in source code form or as a compiled binary, for any // purpose, commercial or non-commercial, and by any means. // // In jurisdictions that recognize copyright laws, the author or authors of // this software dedicate any and all copyright interest in the software to the // public domain. We make this dedication for the benefit of the public at // large and to the detriment of our heirs and successors. We intend this // dedication to be an overt act of relinquishment in perpetuity of all present // and future rights to this software under copyright law. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // For more information, please refer to //----------------------------------------------------------------------------- // SRT Project information: // This file was adopted from a Public Domain project from // https://github.com/mbitsnbites/atomic // Only namespaces were changed to adopt it for SRT project. #ifndef SRT_SYNC_ATOMIC_MSVC_H_ #define SRT_SYNC_ATOMIC_MSVC_H_ // Define which functions we need (don't include ). extern "C" { short _InterlockedIncrement16(short volatile*); long _InterlockedIncrement(long volatile*); __int64 _InterlockedIncrement64(__int64 volatile*); short _InterlockedDecrement16(short volatile*); long _InterlockedDecrement(long volatile*); __int64 _InterlockedDecrement64(__int64 volatile*); char _InterlockedExchange8(char volatile*, char); short _InterlockedExchange16(short volatile*, short); long __cdecl _InterlockedExchange(long volatile*, long); __int64 _InterlockedExchange64(__int64 volatile*, __int64); char _InterlockedCompareExchange8(char volatile*, char, char); short _InterlockedCompareExchange16(short volatile*, short, short); long __cdecl _InterlockedCompareExchange(long volatile*, long, long); __int64 _InterlockedCompareExchange64(__int64 volatile*, __int64, __int64); }; // Define which functions we want to use as inline intriniscs. #pragma intrinsic(_InterlockedIncrement) #pragma intrinsic(_InterlockedIncrement16) #pragma intrinsic(_InterlockedDecrement) #pragma intrinsic(_InterlockedDecrement16) #pragma intrinsic(_InterlockedCompareExchange) #pragma intrinsic(_InterlockedCompareExchange8) #pragma intrinsic(_InterlockedCompareExchange16) #pragma intrinsic(_InterlockedExchange) #pragma intrinsic(_InterlockedExchange8) #pragma intrinsic(_InterlockedExchange16) #if defined(_M_X64) #pragma intrinsic(_InterlockedIncrement64) #pragma intrinsic(_InterlockedDecrement64) #pragma intrinsic(_InterlockedCompareExchange64) #pragma intrinsic(_InterlockedExchange64) #endif // _M_X64 namespace srt { namespace sync { namespace msvc { template struct interlocked { }; template struct interlocked { static inline T increment(T volatile* x) { // There's no _InterlockedIncrement8(). char old_val, new_val; do { old_val = static_cast(*x); new_val = old_val + static_cast(1); } while (_InterlockedCompareExchange8(reinterpret_cast(x), new_val, old_val) != old_val); return static_cast(new_val); } static inline T decrement(T volatile* x) { // There's no _InterlockedDecrement8(). char old_val, new_val; do { old_val = static_cast(*x); new_val = old_val - static_cast(1); } while (_InterlockedCompareExchange8(reinterpret_cast(x), new_val, old_val) != old_val); return static_cast(new_val); } static inline T compare_exchange(T volatile* x, const T new_val, const T expected_val) { return static_cast( _InterlockedCompareExchange8(reinterpret_cast(x), static_cast(new_val), static_cast(expected_val))); } static inline T exchange(T volatile* x, const T new_val) { return static_cast(_InterlockedExchange8( reinterpret_cast(x), static_cast(new_val))); } }; template struct interlocked { static inline T increment(T volatile* x) { return static_cast( _InterlockedIncrement16(reinterpret_cast(x))); } static inline T decrement(T volatile* x) { return static_cast( _InterlockedDecrement16(reinterpret_cast(x))); } static inline T compare_exchange(T volatile* x, const T new_val, const T expected_val) { return static_cast( _InterlockedCompareExchange16(reinterpret_cast(x), static_cast(new_val), static_cast(expected_val))); } static inline T exchange(T volatile* x, const T new_val) { return static_cast( _InterlockedExchange16(reinterpret_cast(x), static_cast(new_val))); } }; template struct interlocked { static inline T increment(T volatile* x) { return static_cast( _InterlockedIncrement(reinterpret_cast(x))); } static inline T decrement(T volatile* x) { return static_cast( _InterlockedDecrement(reinterpret_cast(x))); } static inline T compare_exchange(T volatile* x, const T new_val, const T expected_val) { return static_cast( _InterlockedCompareExchange(reinterpret_cast(x), static_cast(new_val), static_cast(expected_val))); } static inline T exchange(T volatile* x, const T new_val) { return static_cast(_InterlockedExchange( reinterpret_cast(x), static_cast(new_val))); } }; template struct interlocked { static inline T increment(T volatile* x) { #if defined(_M_X64) return static_cast( _InterlockedIncrement64(reinterpret_cast(x))); #else // There's no _InterlockedIncrement64() for 32-bit x86. __int64 old_val, new_val; do { old_val = static_cast<__int64>(*x); new_val = old_val + static_cast<__int64>(1); } while (_InterlockedCompareExchange64( reinterpret_cast(x), new_val, old_val) != old_val); return static_cast(new_val); #endif // _M_X64 } static inline T decrement(T volatile* x) { #if defined(_M_X64) return static_cast( _InterlockedDecrement64(reinterpret_cast(x))); #else // There's no _InterlockedDecrement64() for 32-bit x86. __int64 old_val, new_val; do { old_val = static_cast<__int64>(*x); new_val = old_val - static_cast<__int64>(1); } while (_InterlockedCompareExchange64( reinterpret_cast(x), new_val, old_val) != old_val); return static_cast(new_val); #endif // _M_X64 } static inline T compare_exchange(T volatile* x, const T new_val, const T expected_val) { return static_cast(_InterlockedCompareExchange64( reinterpret_cast(x), static_cast(new_val), static_cast(expected_val))); } static inline T exchange(T volatile* x, const T new_val) { #if defined(_M_X64) return static_cast( _InterlockedExchange64(reinterpret_cast(x), static_cast(new_val))); #else // There's no _InterlockedExchange64 for 32-bit x86. __int64 old_val; do { old_val = static_cast<__int64>(*x); } while (_InterlockedCompareExchange64( reinterpret_cast(x), new_val, old_val) != old_val); return static_cast(old_val); #endif // _M_X64 } }; } // namespace msvc } // namespace sync } // namespace srt #endif // ATOMIC_ATOMIC_MSVC_H_