MPMA Framework 0.4
|
00001 //Thread Locking Constructs 00002 //Luke Lenhart, 2007 00003 //See /docs/License.txt for details on how this code may be used. 00004 00005 #pragma once 00006 00007 namespace MPMA 00008 { 00009 //Atomically increments an integer 00010 inline void AtomicIntInc(volatile nuint *pint) 00011 { 00012 #ifdef _WIN64 00013 _InterlockedIncrement64((volatile __int64*)pint); 00014 #else //WIN32 00015 __asm 00016 { 00017 mov eax, pint; 00018 lock inc dword ptr [eax]; 00019 } 00020 #endif 00021 } 00022 00023 //Atomically decrements an integer 00024 inline void AtomicIntDec(volatile nuint *pint) 00025 { 00026 #ifdef _WIN64 00027 _InterlockedDecrement64((volatile __int64*)pint); 00028 #else //WIN32 00029 __asm 00030 { 00031 mov eax, pint; 00032 lock dec dword ptr [eax]; 00033 } 00034 #endif 00035 } 00036 00037 //Atomically adds one integer to another and returns the value of the original 00038 inline nsint AtomicIntAdd(volatile nsint *pint, nsint addValue) 00039 { 00040 #ifdef _WIN64 00041 return _InterlockedExchangeAdd64((volatile __int64*)pint, addValue); 00042 #else //WIN32 00043 int rval; 00044 __asm 00045 { 00046 mov eax, addValue; 00047 mov ebx, pint; 00048 lock xadd dword ptr [ebx], eax; 00049 mov rval, eax; 00050 } 00051 return rval; 00052 #endif 00053 } 00054 00055 //Compares expectedValue with the value at pInt, and if they are the same, sets pInt to newValue and returns true with outResultValue set to newValue. If they are different then pInt is unaffected, and returns false with outResultValue set to the value that was found at pInt. 00056 inline bool AtomicCompareExchange(volatile nuint *pInt, nuint expectedValue, nuint newValue, volatile nuint &outResultValue) 00057 { 00058 #ifdef _WIN64 00059 nuint rval; 00060 rval=_InterlockedCompareExchange64((volatile __int64*)pInt, newValue, expectedValue); 00061 if (rval==expectedValue) 00062 { 00063 outResultValue=newValue; 00064 return true; 00065 } 00066 else 00067 { 00068 outResultValue=rval; 00069 return false; 00070 } 00071 00072 #else //WIN32 00073 nuint rval; 00074 nuint changed=0; 00075 __asm 00076 { 00077 mov eax, expectedValue; 00078 mov ebx, pInt; 00079 mov ecx, newValue; 00080 lock cmpxchg [ebx], ecx; 00081 jnz AtomCmpExch_Diff; 00082 mov eax,ecx; 00083 inc changed; 00084 AtomCmpExch_Diff: 00085 mov rval, eax; 00086 } 00087 outResultValue=rval; 00088 return changed!=0; 00089 #endif 00090 } 00091 00092 }; //namespace Platform