Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre_src_v1-9-0/OgreMain/include/OgreAtomicScalar.h @ 148

Last change on this file since 148 was 148, checked in by patricwi, 6 years ago

Added new dependencies for ogre1.9 and cegui0.8

File size: 13.6 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2013 Torus Knot Software Ltd
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25THE SOFTWARE.
26-----------------------------------------------------------------------------
27*/
28#ifndef __AtomicScalar_H__
29#define __AtomicScalar_H__
30
31#include <signal.h>
32#include "OgrePrerequisites.h"
33#include "OgreException.h"
34#include "OgrePlatformInformation.h"
35
36#if (((OGRE_COMPILER == OGRE_COMPILER_GNUC) && (OGRE_COMP_VER >= 412)) || (OGRE_COMPILER == OGRE_COMPILER_CLANG)) && OGRE_THREAD_SUPPORT
37
38// Atomics are not yet supported for the unsigned long long int(ResourceHandle) type as of Clang 5.0. So only GCC for now.
39#if ((OGRE_COMPILER == OGRE_COMPILER_GNUC) && (OGRE_COMP_VER >= 473))
40    #define BUILTIN_FETCH_ADD(var, add) __atomic_fetch_add (var, add, __ATOMIC_SEQ_CST);
41    #define BUILTIN_ADD_FETCH(var, add) __atomic_add_fetch (var, add, __ATOMIC_SEQ_CST);
42    #define BUILTIN_SUB_FETCH(var, sub) __atomic_sub_fetch (var, sub, __ATOMIC_SEQ_CST);
43#else
44    #define BUILTIN_FETCH_ADD(var, add) __sync_fetch_and_add (var, add);
45    #define BUILTIN_ADD_FETCH(var, add) __sync_add_and_fetch (var, add);
46    #define BUILTIN_SUB_FETCH(var, sub) __sync_sub_and_fetch (var, sub);
47#endif
48
49namespace Ogre {
50
51        /** \addtogroup Core
52        *  @{
53        */
54        /** \addtogroup General
55        *  @{
56        */
57    template<class T> class AtomicScalar
58    {
59
60        public:
61
62        AtomicScalar (const T &initial)
63            : mField(initial)
64        {   }
65
66        AtomicScalar (const AtomicScalar<T> &cousin)
67            : mField(cousin.mField)
68        {   }
69
70        AtomicScalar () 
71        {   }
72
73        void operator= (const AtomicScalar<T> &cousin)
74        {
75            mField = cousin.mField;
76        }
77
78        T get (void) const
79        {
80            return mField;
81        }
82
83        void set (const T &v)
84        {
85            mField = v; 
86        }   
87
88        bool cas (const T &old, const T &nu)
89        {
90            return __sync_bool_compare_and_swap (&mField, old, nu);
91        }
92           
93        T operator++ (void)
94        {
95            return BUILTIN_ADD_FETCH (&mField, 1);
96        }
97           
98        T operator-- (void)
99        {
100            return BUILTIN_ADD_FETCH (&mField, -1);
101        }
102
103        T operator++ (int)
104        {
105            return BUILTIN_FETCH_ADD (&mField, 1);
106        }
107           
108        T operator-- (int)
109        {
110            return BUILTIN_FETCH_ADD (&mField, -1);
111        }
112
113                T operator+=(const T &add)
114                {
115                        return BUILTIN_ADD_FETCH (&mField, add);
116                }
117
118                T operator-=(const T &sub)
119                {
120                        return BUILTIN_SUB_FETCH (&mField, sub);
121                }
122
123        // Need special alignment for atomic functions on ARM CPU's
124#if OGRE_CPU == OGRE_CPU_ARM
125#   if OGRE_COMPILER == OGRE_COMPILER_MSVC
126        __declspec(align(16)) volatile T mField;
127#   elif (OGRE_COMPILER == OGRE_COMPILER_GNUC) || (OGRE_COMPILER == OGRE_COMPILER_CLANG)
128        volatile T mField __attribute__((__aligned__(16)));
129#   endif
130#else
131        volatile T mField;
132#endif
133
134    };
135        /** @} */
136        /** @} */
137
138}
139
140
141 #elif OGRE_COMPILER == OGRE_COMPILER_MSVC && OGRE_COMP_VER >= 1400 && OGRE_THREAD_SUPPORT
142
143#ifndef WIN32_LEAN_AND_MEAN
144#  define WIN32_LEAN_AND_MEAN
145#endif
146#if !defined(NOMINMAX) && defined(_MSC_VER)
147#       define NOMINMAX // required to stop windows.h messing up std::min
148#endif
149#include <windows.h>
150#include <intrin.h>
151#include "Threading/OgreThreadHeaders.h"
152
153// Save warnings state
154#   pragma warning (push)
155#   pragma warning (disable : 4244)
156
157
158
159namespace Ogre {
160
161    // a hack so we can support windows xp.
162#define NEED_TO_INIT_INTERLOCKEDCOMPAREEXCHANGE64WRAPPER
163    struct _OgreExport InterlockedCompareExchange64Wrapper
164    {
165        InterlockedCompareExchange64Wrapper();
166
167        typedef 
168            LONGLONG
169            (WINAPI *func_InterlockedCompareExchange64)( 
170            __inout LONGLONG volatile *Destination,
171            __in    LONGLONG Exchange,
172            __in    LONGLONG Comperand) ;
173
174        static func_InterlockedCompareExchange64 Ogre_InterlockedCompareExchange64;
175
176        static FORCEINLINE
177            LONGLONG
178            Ogre_InterlockedIncrement64 (
179            __inout LONGLONG volatile *Addend
180            )
181        {
182            LONGLONG Old;
183
184            do {
185                Old = *Addend;
186            } while (Ogre_InterlockedCompareExchange64(Addend,
187                Old + 1,
188                Old) != Old);
189
190            return Old + 1;
191        }
192
193        static FORCEINLINE
194            LONGLONG
195            Ogre_InterlockedDecrement64 (
196            __inout LONGLONG volatile *Addend
197            )
198        {
199            LONGLONG Old;
200
201            do {
202                Old = *Addend;
203            } while (Ogre_InterlockedCompareExchange64(Addend,
204                Old - 1,
205                Old) != Old);
206
207            return Old - 1;
208        }
209
210    };
211
212    /** \addtogroup Core
213        *  @{
214        */
215        /** \addtogroup General
216        *  @{
217        */
218    template<class T> class AtomicScalar
219    {
220
221        public:
222
223        AtomicScalar (const T &initial)
224            : mField(initial)
225        {   }
226
227        AtomicScalar (const AtomicScalar<T> &cousin)
228            : mField(cousin.mField)
229        {   }
230
231        AtomicScalar () 
232        {   }
233
234        void operator= (const AtomicScalar<T> &cousin)
235        {
236            mField = cousin.mField;
237        }
238
239        T get (void) const
240        {
241            return mField;
242        }
243
244        void set (const T &v)
245        {
246            mField = v;
247        }   
248
249        bool cas (const T &old, const T &nu)
250        {
251            if (sizeof(T)==2) {
252                return _InterlockedCompareExchange16((SHORT*)&mField, static_cast<SHORT>(nu), static_cast<SHORT>(old)) == static_cast<SHORT>(old);
253            } 
254                        else if (sizeof(T)==4) 
255                        {
256                return _InterlockedCompareExchange((LONG*)&mField, static_cast<LONG>(nu), static_cast<LONG>(old)) == static_cast<LONG>(old);
257                        } 
258                        else if (sizeof(T)==8 && InterlockedCompareExchange64Wrapper::Ogre_InterlockedCompareExchange64 != NULL) {
259                return InterlockedCompareExchange64Wrapper::Ogre_InterlockedCompareExchange64((LONGLONG*)&mField, static_cast<LONGLONG>(nu), static_cast<LONGLONG>(old)) == static_cast<LONGLONG>(old);
260            } 
261                        else {
262                OGRE_LOCK_AUTO_MUTEX;
263                if (mField != old) return false;
264                mField = nu;
265                return true;
266            }
267        }
268           
269        T operator++ (void)
270        {
271            if (sizeof(T)==2) {
272                return _InterlockedIncrement16((SHORT*)&mField);
273            } else if (sizeof(T)==4) {
274                return InterlockedIncrement((LONG*)&mField);
275            } else if (sizeof(T)==8 && InterlockedCompareExchange64Wrapper::Ogre_InterlockedCompareExchange64 != NULL) {
276                return InterlockedCompareExchange64Wrapper::Ogre_InterlockedIncrement64((LONGLONG*)&mField);
277            } else {
278                OGRE_LOCK_AUTO_MUTEX;
279                return ++mField;
280            }
281        }
282           
283        T operator-- (void)
284        {
285            if (sizeof(T)==2) {
286                return _InterlockedDecrement16((SHORT*)&mField);
287            } else if (sizeof(T)==4) {
288                return InterlockedDecrement((LONG*)&mField);
289            } else if (sizeof(T)==8 && InterlockedCompareExchange64Wrapper::Ogre_InterlockedCompareExchange64 != NULL) {
290                return InterlockedCompareExchange64Wrapper::Ogre_InterlockedDecrement64((LONGLONG*)&mField);
291            } else {
292                OGRE_LOCK_AUTO_MUTEX;
293                return --mField;
294            }
295        }
296
297        T operator++ (int)
298        {
299            if (sizeof(T)==2) {
300                return _InterlockedIncrement16((SHORT*)&mField)-1;
301            } else if (sizeof(T)==4) {
302                return InterlockedIncrement((LONG*)&mField)-1;
303            } else if (sizeof(T)==8 && InterlockedCompareExchange64Wrapper::Ogre_InterlockedCompareExchange64 != NULL) {
304                return InterlockedCompareExchange64Wrapper::Ogre_InterlockedIncrement64((LONGLONG*)&mField)-1;
305            } else {
306                OGRE_LOCK_AUTO_MUTEX;
307                return mField++;
308            }
309        }
310           
311        T operator-- (int)
312        {
313            if (sizeof(T)==2) {
314                return _InterlockedDecrement16((SHORT*)&mField)+1;
315            } else if (sizeof(T)==4) {
316                return InterlockedDecrement((LONG*)&mField)+1;
317            } else if (sizeof(T)==8 && InterlockedCompareExchange64Wrapper::Ogre_InterlockedCompareExchange64 != NULL) {
318                return InterlockedCompareExchange64Wrapper::Ogre_InterlockedDecrement64((LONGLONG*)&mField)+1;
319            } else {
320                OGRE_LOCK_AUTO_MUTEX;
321                return mField--;
322            }
323        }
324
325                T operator+=(const T &add)
326                {
327            if ((sizeof(T)==2) || (sizeof(T)==4) || (sizeof(T)==8 && InterlockedCompareExchange64Wrapper::Ogre_InterlockedCompareExchange64 != NULL)) {
328                //The function InterlockedExchangeAdd is not available for 64 and 16 bit version
329                //We will use the cas operation instead.
330                T newVal;
331                do {
332                    //Create a value of the current field plus the added value
333                    newVal = mField + add;
334                    //Replace the current field value with the new value. Ensure that the value
335                    //of the field hasn't changed in the mean time by comparing it to the new value
336                    //minus the added value.
337                } while (!cas(newVal - add, newVal)); //repeat until successful
338                return newVal;
339            }
340            else
341            {
342                OGRE_LOCK_AUTO_MUTEX;
343                mField += add;
344                return mField;
345            }
346                }
347
348                T operator-=(const T &sub)
349                {
350            if ((sizeof(T)==2) || (sizeof(T)==4) || (sizeof(T)==8 && InterlockedCompareExchange64Wrapper::Ogre_InterlockedCompareExchange64 != NULL)) {
351                //The function InterlockedExchangeAdd is not available for 64 and 16 bit version
352                //We will use the cas operation instead.
353                T newVal;
354                do {
355                    //Create a value of the current field plus the added value
356                    newVal = mField - sub;
357                    //Replace the current field value with the new value. Ensure that the value
358                    //of the field hasn't changed in the mean time by comparing it to the new value
359                    //minus the added value.
360                } while (!cas(newVal + sub, newVal)); //repeat until successful
361                return newVal;
362            }
363            else
364            {
365                OGRE_LOCK_AUTO_MUTEX;
366                mField -= sub;
367                return mField;
368            }
369                }
370
371        protected:
372
373        OGRE_AUTO_MUTEX;
374
375        volatile T mField;
376
377    };
378        /** @} */
379        /** @} */
380
381}
382
383#   pragma warning (pop)
384
385#else
386
387#include "Threading/OgreThreadHeaders.h"
388
389namespace Ogre {
390
391        /** \addtogroup Core
392        *  @{
393        */
394        /** \addtogroup General
395        *  @{
396        */
397    template <class T> class AtomicScalar {
398
399        public:
400
401        AtomicScalar (const T &initial)
402            : mField(initial)
403        {   }
404
405        AtomicScalar (const AtomicScalar<T> &cousin)
406            : mField(cousin.mField)
407        {   }
408
409        AtomicScalar ()
410        {   }
411
412        void operator= (const AtomicScalar<T> &cousin)
413        {
414            mField = cousin.mField;
415        }
416
417        T get (void) const
418        {
419            // no lock required here
420            // since get will not interfere with set or cas
421            // we may get a stale value, but this is ok
422            return mField;
423        }
424
425        void set (const T &v)
426        {
427            mField = v;
428        }
429
430        bool cas (const T &old, const T &nu)
431        {
432            OGRE_LOCK_AUTO_MUTEX;
433            if (mField != old) return false;
434            mField = nu;
435            return true;
436        }
437
438        T operator++ (void)
439        {
440            OGRE_LOCK_AUTO_MUTEX;
441            return ++mField;
442        }
443
444        T operator-- (void)
445        {
446            OGRE_LOCK_AUTO_MUTEX;
447            return --mField;
448        }
449
450        T operator++ (int)
451        {
452            OGRE_LOCK_AUTO_MUTEX;
453            return mField++;
454        }
455
456        T operator-- (int)
457        {
458            OGRE_LOCK_AUTO_MUTEX;
459            return mField--;
460        }
461
462                T operator+=(const T &add)
463                {
464            OGRE_LOCK_AUTO_MUTEX;
465                        mField += add;
466                        return mField;
467                }
468
469                T operator-=(const T &sub)
470                {
471            OGRE_LOCK_AUTO_MUTEX;
472                        mField -= sub;
473                        return mField;
474                }
475
476        protected:
477
478        OGRE_AUTO_MUTEX;
479
480        volatile T mField;
481
482    };
483        /** @} */
484        /** @} */
485
486}
487
488#endif
489
490#endif
491
Note: See TracBrowser for help on using the repository browser.