OgreHapticsAtomic.h

Go to the documentation of this file.
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