OgreAtomicWrappers.h

Go to the documentation of this file.
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-2006 Torus Knot Software Ltd
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 
00024 You may alternatively use this source under the terms of a specific version of
00025 the OGRE Unrestricted License provided you have obtained such a license from
00026 Torus Knot Software Ltd.
00027 -----------------------------------------------------------------------------
00028 */
00029 #ifndef _AtomicWrapper_H__
00030 #define _AtomicWrapper_H__
00031 
00032 #include <signal.h>
00033 #include "OgrePrerequisites.h"
00034 #include "OgreException.h"
00035 
00036 namespace Ogre {
00037 
00038     template <class T> class AtomicObject {
00039 
00040         public:
00041 
00042         AtomicObject (const T &initial)
00043             : mField(initial)
00044         {   }
00045 
00046         AtomicObject (const AtomicObject<T> &cousin)
00047             : mField(cousin.get())
00048         {   }
00049 
00050         AtomicObject ()
00051         {   }
00052 
00053         void operator= (const AtomicObject<T> &cousin)
00054         {
00055             set(cousin.get());
00056         }
00057 
00058         T get (void) const
00059         {
00060             OGRE_LOCK_AUTO_MUTEX
00061             return mField;
00062         }
00063 
00064         void set (const T &v)
00065         {
00066             OGRE_LOCK_AUTO_MUTEX
00067             mField = v;
00068         }
00069 
00070         bool cas (const T &old, const T &nu)
00071         {
00072             OGRE_LOCK_AUTO_MUTEX
00073             if (mField != old) return false;
00074             mField = nu;
00075             return true;
00076         }
00077 
00078         T operator++ (void)
00079         {
00080             OGRE_LOCK_AUTO_MUTEX
00081             return ++mField;
00082         }
00083 
00084         T operator++ (int)
00085         {
00086             OGRE_LOCK_AUTO_MUTEX
00087             return mField++;
00088         }
00089 
00090         T operator-- (int)
00091         {
00092             OGRE_LOCK_AUTO_MUTEX
00093             return mField--;
00094         }
00095 
00096         protected:
00097 
00098         OGRE_AUTO_MUTEX
00099 
00100         volatile T mField;
00101 
00102     };
00103 
00104 }
00105 
00106 #if OGRE_COMPILER == OGRE_COMPILER_GNUC && OGRE_COMP_VER >= 412 && OGRE_THREAD_SUPPORT
00107 
00108 namespace Ogre {
00109 
00110     template<class T> class AtomicScalar
00111     {
00112 
00113         public:
00114 
00115         AtomicScalar (const T &initial)
00116             : mField(initial)
00117         {   }
00118 
00119         AtomicScalar (const AtomicScalar<T> &cousin)
00120             : mField(cousin.mField)
00121         {   }
00122 
00123         AtomicScalar () 
00124         {   }
00125 
00126         void operator= (const AtomicScalar<T> &cousin)
00127         {
00128             mField = cousin.mField;
00129         }
00130 
00131         T get (void) const
00132         {
00133             return mField;
00134         }
00135 
00136         void set (const T &v)
00137         {
00138             mField = v; 
00139         }   
00140 
00141         bool cas (const T &old, const T &nu)
00142         {
00143             return __sync_bool_compare_and_swap (&mField, old, nu);
00144         }
00145             
00146         T operator++ (void)
00147         {
00148             __sync_add_and_fetch (&mField, 1);
00149         }
00150             
00151         T operator-- (void)
00152         {
00153             __sync_add_and_fetch (&mField, -1);
00154         }
00155 
00156         T operator++ (int)
00157         {
00158             __sync_fetch_and_add (&mField, 1);
00159         }
00160             
00161         T operator-- (int)
00162         {
00163             __sync_fetch_and_add (&mField, -1);
00164         }
00165 
00166 
00167         volatile T mField;
00168 
00169     };
00170 
00171 }
00172 
00173  #elif OGRE_COMPILER == OGRE_COMPILER_MSVC && OGRE_COMP_VER >= 1400 && OGRE_THREAD_SUPPORT
00174 
00175 #define WIN32_LEAN_AND_MEAN
00176 #define NOMINMAX // required to stop windows.h messing up std::min
00177 #include <windows.h>
00178 #include <intrin.h>
00179 
00180 namespace Ogre {
00181 
00182     template<class T> class AtomicScalar
00183     {
00184 
00185         public:
00186 
00187         AtomicScalar (const T &initial)
00188             : mField(initial)
00189         {   }
00190 
00191         AtomicScalar (const AtomicScalar<T> &cousin)
00192             : mField(cousin.mField)
00193         {   }
00194 
00195         AtomicScalar () 
00196         {   }
00197 
00198         void operator= (const AtomicScalar<T> &cousin)
00199         {
00200             mField = cousin.mField;
00201         }
00202 
00203         T get (void) const
00204         {
00205             return mField;
00206         }
00207 
00208         void set (const T &v)
00209         {
00210             mField = v;
00211         }   
00212 
00213         bool cas (const T &old, const T &nu)
00214         {
00215             if (sizeof(T)==2) {
00216                 return _InterlockedCompareExchange16((SHORT*)&mField, static_cast<SHORT>(nu), static_cast<SHORT>(old)) == static_cast<SHORT>(old);
00217             } 
00218             else if (sizeof(T)==4) 
00219             {
00220                 return _InterlockedCompareExchange((LONG*)&mField, static_cast<LONG>(nu), static_cast<LONG>(old)) == static_cast<LONG>(old);
00221             } 
00222             else if (sizeof(T)==8) {
00223                 return _InterlockedCompareExchange64((LONGLONG*)&mField, static_cast<LONGLONG>(nu), static_cast<LONGLONG>(old)) == static_cast<LONGLONG>(old);
00224             } 
00225             else {
00226                 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::cas");
00227             }
00228         }
00229             
00230         T operator++ (void)
00231         {
00232             if (sizeof(T)==2) {
00233                 return InterlockedIncrement16((SHORT*)&mField);
00234             } else if (sizeof(T)==4) {
00235                 return InterlockedIncrement((LONG*)&mField);
00236             } else if (sizeof(T)==8) {
00237                 return InterlockedIncrement64((LONGLONG*)&mField);
00238             } else {
00239                 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator++(prefix)");
00240             }
00241         }
00242             
00243         T operator-- (void)
00244         {
00245             if (sizeof(T)==2) {
00246                 return InterlockedDecrement16((SHORT*)&mField);
00247             } else if (sizeof(T)==4) {
00248                 return InterlockedDecrement((LONG*)&mField);
00249             } else if (sizeof(T)==8) {
00250                 return InterlockedDecrement64((LONGLONG*)&mField);
00251             } else {
00252                 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator--(prefix)");
00253             }
00254         }
00255 
00256         T operator++ (int)
00257         {
00258             if (sizeof(T)==2) {
00259                 return InterlockedIncrement16((SHORT*)&mField)-1;
00260             } else if (sizeof(T)==4) {
00261                 return InterlockedIncrement((LONG*)&mField)-1;
00262             } else if (sizeof(T)==8) {
00263                 return InterlockedIncrement64((LONGLONG*)&mField)-1;
00264             } else {
00265                 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator++(postfix)");
00266             }
00267         }
00268             
00269         T operator-- (int)
00270         {
00271             if (sizeof(T)==2) {
00272                 return InterlockedDecrement16((SHORT*)&mField)+1;
00273             } else if (sizeof(T)==4) {
00274                 return InterlockedDecrement((LONG*)&mField)+1;
00275             } else if (sizeof(T)==8) {
00276                 return InterlockedDecrement64((LONGLONG*)&mField)+1;
00277             } else {
00278                 OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator--(postfix)");
00279             }
00280         }
00281 
00282         volatile T mField;
00283 
00284     };
00285 
00286 }
00287 
00288 #else
00289 
00290 namespace Ogre {
00291 
00292     template <class T> class AtomicScalar {
00293 
00294         public:
00295 
00296         AtomicScalar (const T &initial)
00297             : mField(initial)
00298         {   }
00299 
00300         AtomicScalar (const AtomicScalar<T> &cousin)
00301             : mField(cousin.mField)
00302         {   }
00303 
00304         AtomicScalar ()
00305         {   }
00306 
00307         void operator= (const AtomicScalar<T> &cousin)
00308         {
00309             OGRE_LOCK_AUTO_MUTEX
00310             mField = cousin.mField;
00311         }
00312 
00313         T get (void) const
00314         {
00315             // no lock required here
00316             // since get will not interfere with set or cas
00317             // we may get a stale value, but this is ok
00318             return mField;
00319         }
00320 
00321         void set (const T &v)
00322         {
00323             OGRE_LOCK_AUTO_MUTEX
00324             mField = v;
00325         }
00326 
00327         bool cas (const T &old, const T &nu)
00328         {
00329             OGRE_LOCK_AUTO_MUTEX
00330             if (mField != old) return false;
00331             mField = nu;
00332             return true;
00333         }
00334 
00335         T operator++ (void)
00336         {
00337             OGRE_LOCK_AUTO_MUTEX
00338             return ++mField;
00339         }
00340 
00341         T operator-- (void)
00342         {
00343             OGRE_LOCK_AUTO_MUTEX
00344             return --mField;
00345         }
00346 
00347         T operator++ (int)
00348         {
00349             OGRE_LOCK_AUTO_MUTEX
00350             return mField++;
00351         }
00352 
00353         T operator-- (int)
00354         {
00355             OGRE_LOCK_AUTO_MUTEX
00356             return mField--;
00357         }
00358 
00359         protected:
00360 
00361         OGRE_AUTO_MUTEX
00362 
00363         volatile T mField;
00364 
00365     };
00366 
00367 }
00368 
00369 #endif
00370 
00371 
00372 #endif
00373 

Copyright © 2008 Torus Knot Software Ltd
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 27 22:02:22 2009