00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright (c) 2000-2009 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef _AtomicWrapper_H__ 00029 #define _AtomicWrapper_H__ 00030 00031 #include <signal.h> 00032 #include "OgrePrerequisites.h" 00033 #include "OgreException.h" 00034 00035 namespace Ogre { 00036 00043 template <class T> class AtomicObject { 00044 00045 public: 00046 00047 AtomicObject (const T &initial) 00048 : mField(initial) 00049 { } 00050 00051 AtomicObject (const AtomicObject<T> &cousin) 00052 : mField(cousin.get()) 00053 { } 00054 00055 AtomicObject () 00056 { } 00057 00058 void operator= (const AtomicObject<T> &cousin) 00059 { 00060 set(cousin.get()); 00061 } 00062 00063 T get (void) const 00064 { 00065 OGRE_LOCK_AUTO_MUTEX 00066 return mField; 00067 } 00068 00069 void set (const T &v) 00070 { 00071 OGRE_LOCK_AUTO_MUTEX 00072 mField = v; 00073 } 00074 00075 bool cas (const T &old, const T &nu) 00076 { 00077 OGRE_LOCK_AUTO_MUTEX 00078 if (mField != old) return false; 00079 mField = nu; 00080 return true; 00081 } 00082 00083 T operator++ (void) 00084 { 00085 OGRE_LOCK_AUTO_MUTEX 00086 return ++mField; 00087 } 00088 00089 T operator++ (int) 00090 { 00091 OGRE_LOCK_AUTO_MUTEX 00092 return mField++; 00093 } 00094 00095 T operator-- (int) 00096 { 00097 OGRE_LOCK_AUTO_MUTEX 00098 return mField--; 00099 } 00100 00101 protected: 00102 00103 OGRE_AUTO_MUTEX 00104 00105 volatile T mField; 00106 00107 }; 00111 } 00112 00113 // These GCC instrinsics are not supported on ARM - masterfalcon 00114 #if OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 && OGRE_THREAD_SUPPORT && OGRE_CPU != OGRE_CPU_ARM 00115 00116 namespace Ogre { 00117 00124 template<class T> class AtomicScalar 00125 { 00126 00127 public: 00128 00129 AtomicScalar (const T &initial) 00130 : mField(initial) 00131 { } 00132 00133 AtomicScalar (const AtomicScalar<T> &cousin) 00134 : mField(cousin.mField) 00135 { } 00136 00137 AtomicScalar () 00138 { } 00139 00140 void operator= (const AtomicScalar<T> &cousin) 00141 { 00142 mField = cousin.mField; 00143 } 00144 00145 T get (void) const 00146 { 00147 return mField; 00148 } 00149 00150 void set (const T &v) 00151 { 00152 mField = v; 00153 } 00154 00155 bool cas (const T &old, const T &nu) 00156 { 00157 return __sync_bool_compare_and_swap (&mField, old, nu); 00158 } 00159 00160 T operator++ (void) 00161 { 00162 __sync_add_and_fetch (&mField, 1); 00163 } 00164 00165 T operator-- (void) 00166 { 00167 __sync_add_and_fetch (&mField, -1); 00168 } 00169 00170 T operator++ (int) 00171 { 00172 __sync_fetch_and_add (&mField, 1); 00173 } 00174 00175 T operator-- (int) 00176 { 00177 __sync_fetch_and_add (&mField, -1); 00178 } 00179 00180 00181 volatile T mField; 00182 00183 }; 00187 } 00188 00189 #elif OGRE_COMPILER == OGRE_COMPILER_MSVC && OGRE_COMP_VER >= 1400 && OGRE_THREAD_SUPPORT 00190 00191 #ifndef WIN32_LEAN_AND_MEAN 00192 # define WIN32_LEAN_AND_MEAN 00193 #endif 00194 #if !defined(NOMINMAX) && defined(_MSC_VER) 00195 # define NOMINMAX // required to stop windows.h messing up std::min 00196 #endif 00197 #include <windows.h> 00198 #include <intrin.h> 00199 00200 namespace Ogre { 00201 00208 template<class T> class AtomicScalar 00209 { 00210 00211 public: 00212 00213 AtomicScalar (const T &initial) 00214 : mField(initial) 00215 { } 00216 00217 AtomicScalar (const AtomicScalar<T> &cousin) 00218 : mField(cousin.mField) 00219 { } 00220 00221 AtomicScalar () 00222 { } 00223 00224 void operator= (const AtomicScalar<T> &cousin) 00225 { 00226 mField = cousin.mField; 00227 } 00228 00229 T get (void) const 00230 { 00231 return mField; 00232 } 00233 00234 void set (const T &v) 00235 { 00236 mField = v; 00237 } 00238 00239 bool cas (const T &old, const T &nu) 00240 { 00241 if (sizeof(T)==2) { 00242 return _InterlockedCompareExchange16((SHORT*)&mField, static_cast<SHORT>(nu), static_cast<SHORT>(old)) == static_cast<SHORT>(old); 00243 } 00244 else if (sizeof(T)==4) 00245 { 00246 return _InterlockedCompareExchange((LONG*)&mField, static_cast<LONG>(nu), static_cast<LONG>(old)) == static_cast<LONG>(old); 00247 } 00248 else if (sizeof(T)==8) { 00249 return _InterlockedCompareExchange64((LONGLONG*)&mField, static_cast<LONGLONG>(nu), static_cast<LONGLONG>(old)) == static_cast<LONGLONG>(old); 00250 } 00251 else { 00252 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::cas"); 00253 } 00254 } 00255 00256 T operator++ (void) 00257 { 00258 if (sizeof(T)==2) { 00259 return InterlockedIncrement16((SHORT*)&mField); 00260 } else if (sizeof(T)==4) { 00261 return InterlockedIncrement((LONG*)&mField); 00262 } else if (sizeof(T)==8) { 00263 return InterlockedIncrement64((LONGLONG*)&mField); 00264 } else { 00265 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator++(prefix)"); 00266 } 00267 } 00268 00269 T operator-- (void) 00270 { 00271 if (sizeof(T)==2) { 00272 return InterlockedDecrement16((SHORT*)&mField); 00273 } else if (sizeof(T)==4) { 00274 return InterlockedDecrement((LONG*)&mField); 00275 } else if (sizeof(T)==8) { 00276 return InterlockedDecrement64((LONGLONG*)&mField); 00277 } else { 00278 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator--(prefix)"); 00279 } 00280 } 00281 00282 T operator++ (int) 00283 { 00284 if (sizeof(T)==2) { 00285 return InterlockedIncrement16((SHORT*)&mField)-1; 00286 } else if (sizeof(T)==4) { 00287 return InterlockedIncrement((LONG*)&mField)-1; 00288 } else if (sizeof(T)==8) { 00289 return InterlockedIncrement64((LONGLONG*)&mField)-1; 00290 } else { 00291 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator++(postfix)"); 00292 } 00293 } 00294 00295 T operator-- (int) 00296 { 00297 if (sizeof(T)==2) { 00298 return InterlockedDecrement16((SHORT*)&mField)+1; 00299 } else if (sizeof(T)==4) { 00300 return InterlockedDecrement((LONG*)&mField)+1; 00301 } else if (sizeof(T)==8) { 00302 return InterlockedDecrement64((LONGLONG*)&mField)+1; 00303 } else { 00304 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator--(postfix)"); 00305 } 00306 } 00307 00308 volatile T mField; 00309 00310 }; 00314 } 00315 00316 #else 00317 00318 namespace Ogre { 00319 00326 template <class T> class AtomicScalar { 00327 00328 public: 00329 00330 AtomicScalar (const T &initial) 00331 : mField(initial) 00332 { } 00333 00334 AtomicScalar (const AtomicScalar<T> &cousin) 00335 : mField(cousin.mField) 00336 { } 00337 00338 AtomicScalar () 00339 { } 00340 00341 void operator= (const AtomicScalar<T> &cousin) 00342 { 00343 OGRE_LOCK_AUTO_MUTEX 00344 mField = cousin.mField; 00345 } 00346 00347 T get (void) const 00348 { 00349 // no lock required here 00350 // since get will not interfere with set or cas 00351 // we may get a stale value, but this is ok 00352 return mField; 00353 } 00354 00355 void set (const T &v) 00356 { 00357 OGRE_LOCK_AUTO_MUTEX 00358 mField = v; 00359 } 00360 00361 bool cas (const T &old, const T &nu) 00362 { 00363 OGRE_LOCK_AUTO_MUTEX 00364 if (mField != old) return false; 00365 mField = nu; 00366 return true; 00367 } 00368 00369 T operator++ (void) 00370 { 00371 OGRE_LOCK_AUTO_MUTEX 00372 return ++mField; 00373 } 00374 00375 T operator-- (void) 00376 { 00377 OGRE_LOCK_AUTO_MUTEX 00378 return --mField; 00379 } 00380 00381 T operator++ (int) 00382 { 00383 OGRE_LOCK_AUTO_MUTEX 00384 return mField++; 00385 } 00386 00387 T operator-- (int) 00388 { 00389 OGRE_LOCK_AUTO_MUTEX 00390 return mField--; 00391 } 00392 00393 protected: 00394 00395 OGRE_AUTO_MUTEX 00396 00397 volatile T mField; 00398 00399 }; 00403 } 00404 00405 #endif 00406 00407 00408 #endif 00409
Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Wed Nov 3 2010 19:24:51