# 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-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