AudRecordLib
|
00001 00007 #ifndef AUDRECORD_ATOMIC_H 00008 #define AUDRECORD_ATOMIC_H 00009 00010 #pragma once 00011 00019 template<class Type, size_t size = sizeof(Type)> 00020 struct Atomic 00021 {}; 00022 00024 template<class Type> 00025 struct Atomic<Type, 4u> 00026 { 00034 Type Read(Type* a) const 00035 { 00036 // There's nothing special about the -10248 00037 // it's just an unlikely value so that in the majority of cases 00038 // the cache line won't be dirtied by a memory write. In the words of Raymond Chen: 00039 // 00040 // This trick doesn't help on all architectures, but it doesn't hurt. 00041 // http://blogs.msdn.com/b/oldnewthing/archive/2011/04/12/10152296.aspx 00042 return reinterpret_cast<Type>(_InterlockedCompareExchange(reinterpret_cast<LONG*>(a), -10248L, -10248L)); 00043 } 00044 00053 Type Exchange(Type* a, Type b) const 00054 { 00055 return static_cast<Type>(_InterlockedExchange(reinterpret_cast<LONG*>(a), b)); 00056 } 00057 }; 00058 00059 #ifdef WIN64 00060 00064 template<class Type> 00065 struct Atomic<Type, 8u> 00066 { 00074 Type Read(Type* a) const 00075 { 00076 // see the Read method in the 4 byte class for a discussion of this 00077 return reinterpret_cast<Type>(_InterlockedCompareExchange64(reinterpret_cast<LONG*>(a), -10248LL, -10248LL)); 00078 } 00079 00088 Type Exchange(Type* a, Type b) const 00089 { 00090 return static_cast<Type>(_InterlockedExchange64(reinterpret_cast<__int64*>(a), b)); 00091 } 00092 }; 00093 #endif 00094 00102 template<class Type> 00103 Type InterlockedExchange(Type* a, Type b) 00104 { 00105 return Atomic<Type>().Exchange(a, b); 00106 } 00107 00114 template<class Type> 00115 Type InterlockedRead(Type* a) 00116 { 00117 return Atomic<Type>.Read(a); 00118 } 00119 00122 #endif