OGRE  1.8
Object-Oriented Graphics Rendering Engine
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
OgreAtomicWrappers.h
Go to the documentation of this file.
1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4  (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #ifndef _AtomicWrapper_H__
29 #define _AtomicWrapper_H__
30 
31 #include <signal.h>
32 #include "OgrePrerequisites.h"
33 #include "OgreException.h"
34 
35 namespace Ogre {
36 
43  template <class T> class AtomicObject {
44 
45  public:
46 
47  AtomicObject (const T &initial)
48  : mField(initial)
49  { }
50 
51  AtomicObject (const AtomicObject<T> &cousin)
52  : mField(cousin.get())
53  { }
54 
56  { }
57 
58  void operator= (const AtomicObject<T> &cousin)
59  {
60  set(cousin.get());
61  }
62 
63  T get (void) const
64  {
66  return mField;
67  }
68 
69  void set (const T &v)
70  {
72  mField = v;
73  }
74 
75  bool cas (const T &old, const T &nu)
76  {
78  if (mField != old) return false;
79  mField = nu;
80  return true;
81  }
82 
83  T operator++ (void)
84  {
86  return ++mField;
87  }
88 
89  T operator++ (int)
90  {
92  return mField++;
93  }
94 
95  T operator-- (int)
96  {
98  return mField--;
99  }
100 
101  T operator+=(const T &add)
102  {
104  mField += add;
105  return mField;
106  }
107 
108  protected:
109 
111 
112  volatile T mField;
113 
114  };
118 }
119 
120 #if (((OGRE_COMPILER == OGRE_COMPILER_GNUC) && (OGRE_COMP_VER >= 412)) || (OGRE_COMPILER == OGRE_COMPILER_CLANG)) && OGRE_THREAD_SUPPORT
121 
122 namespace Ogre {
123 
130  template<class T> class AtomicScalar
131  {
132 
133  public:
134 
135  AtomicScalar (const T &initial)
136  : mField(initial)
137  { }
138 
139  AtomicScalar (const AtomicScalar<T> &cousin)
140  : mField(cousin.mField)
141  { }
142 
143  AtomicScalar ()
144  { }
145 
146  void operator= (const AtomicScalar<T> &cousin)
147  {
148  mField = cousin.mField;
149  }
150 
151  T get (void) const
152  {
153  return mField;
154  }
155 
156  void set (const T &v)
157  {
158  mField = v;
159  }
160 
161  bool cas (const T &old, const T &nu)
162  {
163  return __sync_bool_compare_and_swap (&mField, old, nu);
164  }
165 
166  T operator++ (void)
167  {
168  __sync_add_and_fetch (&mField, 1);
169  }
170 
171  T operator-- (void)
172  {
173  __sync_add_and_fetch (&mField, -1);
174  }
175 
176  T operator++ (int)
177  {
178  __sync_fetch_and_add (&mField, 1);
179  }
180 
181  T operator-- (int)
182  {
183  __sync_fetch_and_add (&mField, -1);
184  }
185 
186  T operator+=(const T &add)
187  {
188  return __sync_add_and_fetch (&mField, add);
189  }
190 
191  volatile T mField;
192 
193  };
197 }
198 
199  #elif OGRE_COMPILER == OGRE_COMPILER_MSVC && OGRE_COMP_VER >= 1400 && OGRE_THREAD_SUPPORT
200 
201 #ifndef WIN32_LEAN_AND_MEAN
202 # define WIN32_LEAN_AND_MEAN
203 #endif
204 #if !defined(NOMINMAX) && defined(_MSC_VER)
205 # define NOMINMAX // required to stop windows.h messing up std::min
206 #endif
207 #include <windows.h>
208 #include <intrin.h>
209 
210 namespace Ogre {
211 
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) {
259  return _InterlockedCompareExchange64((LONGLONG*)&mField, static_cast<LONGLONG>(nu), static_cast<LONGLONG>(old)) == static_cast<LONGLONG>(old);
260  }
261  else {
262  OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::cas");
263  }
264  }
265 
266  T operator++ (void)
267  {
268  if (sizeof(T)==2) {
269  return InterlockedIncrement16((SHORT*)&mField);
270  } else if (sizeof(T)==4) {
271  return InterlockedIncrement((LONG*)&mField);
272  } else if (sizeof(T)==8) {
273  return InterlockedIncrement64((LONGLONG*)&mField);
274  } else {
275  OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator++(prefix)");
276  }
277  }
278 
279  T operator-- (void)
280  {
281  if (sizeof(T)==2) {
282  return InterlockedDecrement16((SHORT*)&mField);
283  } else if (sizeof(T)==4) {
284  return InterlockedDecrement((LONG*)&mField);
285  } else if (sizeof(T)==8) {
286  return InterlockedDecrement64((LONGLONG*)&mField);
287  } else {
288  OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator--(prefix)");
289  }
290  }
291 
292  T operator++ (int)
293  {
294  if (sizeof(T)==2) {
295  return InterlockedIncrement16((SHORT*)&mField)-1;
296  } else if (sizeof(T)==4) {
297  return InterlockedIncrement((LONG*)&mField)-1;
298  } else if (sizeof(T)==8) {
299  return InterlockedIncrement64((LONGLONG*)&mField)-1;
300  } else {
301  OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator++(postfix)");
302  }
303  }
304 
305  T operator-- (int)
306  {
307  if (sizeof(T)==2) {
308  return InterlockedDecrement16((SHORT*)&mField)+1;
309  } else if (sizeof(T)==4) {
310  return InterlockedDecrement((LONG*)&mField)+1;
311  } else if (sizeof(T)==8) {
312  return InterlockedDecrement64((LONGLONG*)&mField)+1;
313  } else {
314  OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,"Only 16, 32, and 64 bit scalars supported in win32.","AtomicScalar::operator--(postfix)");
315  }
316  }
317 
318  T operator+=(const T &add)
319  {
320  //The function InterlockedExchangeAdd is not available for 64 and 16 bit version
321  //We will use the cas operation instead.
322  T newVal;
323  do {
324  //Create a value of the current field plus the added value
325  newVal = mField + add;
326  //Replace the current field value with the new value. Ensure that the value
327  //of the field hasn't changed in the mean time by comparing it to the new value
328  //minus the added value.
329  } while (!cas(newVal - add, newVal)); //repeat until successful
330  return newVal;
331  }
332 
333  volatile T mField;
334 
335  };
339 }
340 
341 #else
342 
343 namespace Ogre {
344 
351  template <class T> class AtomicScalar {
352 
353  public:
354 
355  AtomicScalar (const T &initial)
356  : mField(initial)
357  { }
358 
360  : mField(cousin.mField)
361  { }
362 
364  { }
365 
366  void operator= (const AtomicScalar<T> &cousin)
367  {
369  mField = cousin.mField;
370  }
371 
372  T get (void) const
373  {
374  // no lock required here
375  // since get will not interfere with set or cas
376  // we may get a stale value, but this is ok
377  return mField;
378  }
379 
380  void set (const T &v)
381  {
383  mField = v;
384  }
385 
386  bool cas (const T &old, const T &nu)
387  {
389  if (mField != old) return false;
390  mField = nu;
391  return true;
392  }
393 
394  T operator++ (void)
395  {
397  return ++mField;
398  }
399 
400  T operator-- (void)
401  {
403  return --mField;
404  }
405 
406  T operator++ (int)
407  {
409  return mField++;
410  }
411 
412  T operator-- (int)
413  {
415  return mField--;
416  }
417 
418  T operator+=(const T &add)
419  {
421  mField += add;
422  return mField;
423  }
424 
425  protected:
426 
428 
429  volatile T mField;
430 
431  };
435 }
436 
437 #endif
438 
439 
440 #endif
441 
#define OGRE_AUTO_MUTEX
OGRE_AUTO_MUTEX volatile T mField
AtomicObject(const T &initial)
void set(const T &v)
void operator=(const AtomicObject< T > &cousin)
AtomicObject(const AtomicObject< T > &cousin)
AtomicScalar(const AtomicScalar< T > &cousin)
bool cas(const T &old, const T &nu)
#define OGRE_LOCK_AUTO_MUTEX
#define OGRE_EXCEPT(num, desc, src)
void operator=(const AtomicScalar< T > &cousin)
bool cas(const T &old, const T &nu)
T operator+=(const T &add)
T operator+=(const T &add)
void set(const T &v)
OGRE_AUTO_MUTEX volatile T mField
AtomicScalar(const T &initial)