00001 /* 00002 This source file is part of OgreHaptics 00003 (a library for wrapping haptics devices for use with the open-source 00004 graphics engine OGRE, http://www.ogre3d.org) 00005 00006 Copyright (c) 2006 - 2008 Jorrit de Vries 00007 Also see acknowledgements in Readme.html 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public License 00011 as published by the Free Software Foundation; either version 2.1 00012 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public 00020 License along with this library; if not, write to the 00021 Free Software Foundation, Inc., 00022 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 */ 00024 #ifndef _OgreHapticsAtomic_H__ 00025 #define _OgreHapticsAtomic_H__ 00026 00027 #include "OgreHapticsPrerequisites.h" 00028 00029 #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 00030 # define WIN32_LEAN_AND_MEAN 00031 # include <windows.h> 00032 # include <intrin.h> 00033 // Define intrinsics 00034 # pragma intrinsic(_ReadWriteBarrier) 00035 # pragma intrinsic(_InterlockedIncrement) 00036 # pragma intrinsic(_InterlockedDecrement) 00037 # pragma intrinsic(_InterlockedExchange) 00038 # pragma intrinsic(_InterlockedExchangeAdd) 00039 # pragma intrinsic(_InterlockedCompareExchange) 00040 # if OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_64 00041 # pragma intrinsic(_InterlockedExchangePointer) 00042 # pragma intrinsic(_InterlockedCompareExchangePointer) 00043 # endif 00044 #endif 00045 00046 namespace OgreHaptics { 00047 00048 // Platform & compiler dependent routines 00049 // Note: the GCC compiler implementation has not been tested 00050 00052 inline void memoryReadWriteBarrier(void) 00053 { 00054 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00055 _ReadWriteBarrier(); 00056 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00057 __sync_synchronize(); 00058 #endif 00059 } 00060 00066 template<typename T> inline T atomicIncrement(volatile T* ptr) 00067 { 00068 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00069 return (T)_InterlockedIncrement((volatile long*)ptr); 00070 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00071 return __sync_fetch_and_add(ptr, 1); 00072 #endif 00073 } 00074 00080 template<typename T> inline T atomicDecrement(volatile T* ptr) 00081 { 00082 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00083 return (T)_InterlockedDecrement((volatile long*)ptr); 00084 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00085 return __synch_fetch_and_sub(ptr, 1); 00086 #endif 00087 } 00088 00094 template<typename T> inline T atomicExchange(volatile T* ptr, 00095 T value) 00096 { 00097 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00098 return (T)_InterlockedExchange((volatile long*)ptr, (long)value); 00099 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00100 // Since __sync_lock_test_and_set is an acquire barrier, we force a 00101 // full barrier 00102 __sync_synchronize(); 00103 return __sync_lock_test_and_set(ptr, value); 00104 #endif 00105 } 00106 00112 template<typename T> inline T* atomicExchangePtr(T* volatile* ptr, 00113 T* value) 00114 { 00115 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00116 # if OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_64 00117 return (T*)_InterlockedExchangePointer((void* volatile*)ptr, (void*)value); 00118 # else 00119 return (T*)_InterlockedExchange((volatile long*)ptr, (long)value); 00120 # endif 00121 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00122 // Since __sync_lock_test_and_set is an acquire barrier, we force a 00123 // full barrier 00124 __sync_synchronize(); 00125 return __sync_lock_test_and_set(ptr, value); 00126 #endif 00127 } 00128 00134 template<typename T> inline T atomicExchangeAndAdd(volatile T* ptr, 00135 T value) 00136 { 00137 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00138 return (T)_InterlockedExchangeAdd((volatile long*)ptr, (long)value); 00139 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00140 return __sync_fetch_and_add(ptr, value); 00141 #endif 00142 } 00143 00149 template<typename T> inline T atomicExchangeAndSubtract(volatile T* ptr, 00150 T value) 00151 { 00152 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00153 return (T)_InterlockedExchangeAdd((volatile long*)ptr, -((long)value)); 00154 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00155 return __sync_fetch_and_sub(ptr, value); 00156 #endif 00157 } 00158 00165 template<typename T> inline bool atomicCompareAndSwap(volatile T* ptr, 00166 T oldValue, T newValue) 00167 { 00168 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00169 return _InterlockedCompareExchange((volatile long*)ptr, (long)newValue, 00170 (long)oldValue) == (long)oldValue; 00171 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00172 return __sync_bool_compare_and_swap(ptr, oldValue, newValue); 00173 #endif 00174 } 00175 00182 template<typename T> inline bool atomicCompareAndSwapPtr(T* volatile* ptr, 00183 T* oldValue, T* newValue) 00184 { 00185 #if OGRE_COMPILER == OGRE_COMPILER_MSVC 00186 # if OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_64 00187 return _InterlockedCompareExchangePointer((void* volatile*)ptr, (void*)newValue, 00188 (void*)oldValue) == (void*)oldValue; 00189 # else 00190 return _InterlockedCompareExchange((volatile long*)ptr, (long)newValue, 00191 (long)oldValue) == (long)oldValue; 00192 # endif 00193 #elif OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 00194 return __sync_bool_compare_and_swap(ptr, oldValue, newValue); 00195 #endif 00196 } 00197 00198 // Compiler independent routines 00199 00204 template<typename T> class AtomicScalar 00205 { 00206 protected: 00207 volatile T value; 00208 public: 00209 inline AtomicScalar() {} 00210 00211 inline AtomicScalar(const T& val) 00212 : value(val) 00213 {} 00214 00215 inline AtomicScalar(const AtomicScalar<T>& rhs) 00216 : value(rhs.get()) 00217 {} 00218 00219 inline void operator = (const AtomicScalar<T>& rhs) 00220 { 00221 atomicExchange(&value, rhs.get()); 00222 } 00223 00224 inline T operator += (T val) 00225 { 00226 return atomicExchangeAndAdd(&value, val) + val; 00227 } 00228 00229 inline T operator -= (T val) 00230 { 00231 return atomicExchangeAndSubtract(&value, val) - val; 00232 } 00233 00234 inline T operator ++ (void) 00235 { 00236 return atomicIncrement(&value) - 1; 00237 } 00238 00239 inline T operator ++ (int) 00240 { 00241 return atomicIncrement(&value); 00242 } 00243 00244 inline T operator -- (void) 00245 { 00246 return atomicDecrement(&value) + 1; 00247 } 00248 00249 inline T operator -- (int) 00250 { 00251 return atomicDecrement(&value); 00252 } 00253 00254 inline void set(T rhs) 00255 { 00256 atomicExchange(&value, rhs); 00257 } 00258 00259 inline T get(void) const 00260 { 00261 return value; 00262 } 00263 00264 inline bool compareAndSwap(T oldValue, T newValue) 00265 { 00266 return atomicCompareAndSwap(&value, oldValue, newValue); 00267 } 00268 }; 00269 00270 } 00271 00272 #endif
Last modified Tue Jan 6 22:31:25 2009