VTK
vtkAtomic.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkAtomic.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
37 #ifndef vtkAtomic_h
38 #define vtkAtomic_h
39 
40 #include "vtkCommonCoreModule.h" // For export macro
41 #include "vtkAtomicTypeConcepts.h"
42 #include "vtkConfigure.h"
43 #include "vtkSystemIncludes.h"
44 #include "vtkType.h"
45 
46 #include <cstddef>
47 
48 
49 // Assume 64-bit atomic operations are not available on 32 bit platforms
50 #if defined(VTK_HAVE_SYNC_BUILTINS)
51 # define VTK_GCC_ATOMICS_32
52 # if VTK_SIZEOF_VOID_P == 8
53 # define VTK_GCC_ATOMICS_64
54 # endif
55 #elif defined(__APPLE__)
56 # include <libkern/OSAtomic.h>
57 # define VTK_APPLE_ATOMICS_32
58 # if VTK_SIZEOF_VOID_P == 8
59 # define VTK_APPLE_ATOMICS_64
60 # endif
61 #elif defined(_WIN32) && defined(_MSC_VER)
62 # define VTK_WINDOWS_ATOMICS_32
63 # if VTK_SIZEOF_VOID_P == 8
64 # define VTK_WINDOWS_ATOMICS_64
65 # endif
66 #endif
67 
68 
69 #if defined(_WIN32) && defined(_MSC_VER)
70 // disable warning about the padding due to alignment
71 # pragma warning(disable:4324)
72 # define VTK_ALIGN(X) __declspec(align(X))
73 #elif defined(__GNUC__) // gcc compatible compiler
74 # define VTK_ALIGN(X) __attribute__ ((aligned (X)))
75 #else
76 # define VTK_ALIGN(X)
77 #endif
78 
79 
81 
82 
83 #ifndef __WRAP__
84 namespace detail
85 {
86 
87 template <size_t size> class AtomicOps;
88 
89 #if defined(VTK_GCC_ATOMICS_64)
90 template <> class AtomicOps<8>
91 {
92 public:
93  typedef vtkTypeInt64 VTK_ALIGN(8) atomic_type;
94  typedef vtkTypeInt64 value_type;
95 
96  static value_type AddAndFetch(value_type *ref, value_type val)
97  {
98  return __sync_add_and_fetch(ref, val);
99  }
100 
102  {
103  return __sync_sub_and_fetch(ref, val);
104  }
105 
107  {
108  return __sync_add_and_fetch(ref, 1);
109  }
110 
112  {
113  return __sync_sub_and_fetch(ref, 1);
114  }
115 
117  {
118  return __sync_fetch_and_add(ref, 1);
119  }
120 
122  {
123  return __sync_fetch_and_sub(ref, 1);
124  }
125 
126  static value_type Load(const value_type *ref)
127  {
128  __sync_synchronize();
129  return *static_cast<const volatile value_type *>(ref);
130  }
131 
132  static void Store(value_type *ref, value_type val)
133  {
134  *static_cast<volatile value_type*>(ref) = val;
135  __sync_synchronize();
136  }
137 };
138 
139 #elif defined(VTK_APPLE_ATOMICS_64)
140 template <> class AtomicOps<8>
141 {
142 public:
143  typedef vtkTypeInt64 VTK_ALIGN(8) atomic_type;
144  typedef vtkTypeInt64 value_type;
145 
146  static vtkTypeInt64 AddAndFetch(vtkTypeInt64 *ref, vtkTypeInt64 val)
147  {
148  return OSAtomicAdd64Barrier(val, ref);
149  }
150 
151  static vtkTypeInt64 SubAndFetch(vtkTypeInt64 *ref, vtkTypeInt64 val)
152  {
153  return OSAtomicAdd64Barrier(-val, ref);
154  }
155 
156  static vtkTypeInt64 PreIncrement(vtkTypeInt64 *ref)
157  {
158  return OSAtomicIncrement64Barrier(ref);
159  }
160 
161  static vtkTypeInt64 PreDecrement(vtkTypeInt64 *ref)
162  {
163  return OSAtomicDecrement64Barrier(ref);
164  }
165 
166  static vtkTypeInt64 PostIncrement(vtkTypeInt64 *ref)
167  {
168  vtkTypeInt64 val = OSAtomicIncrement64Barrier(ref);
169  return --val;
170  }
171 
172  static vtkTypeInt64 PostDecrement(vtkTypeInt64 *ref)
173  {
174  vtkTypeInt64 val = OSAtomicDecrement64Barrier(ref);
175  return ++val;
176  }
177 
178  static vtkTypeInt64 Load(const vtkTypeInt64 *ref);
179  {
180  OSMemoryBarrier();
181  return *static_cast<const volatile vtkTypeInt64*>(ref);
182  }
183 
184  static void Store(vtkTypeInt64 *ref, vtkTypeInt64 val);
185  {
186  *static_cast<volatile vtkTypeInt64*>(ref) = val;
187  OSMemoryBarrier();
188  }
189 };
190 
191 #else
192 
193 template <> class VTKCOMMONCORE_EXPORT AtomicOps<8>
194 {
195 public:
196 #if defined(VTK_WINDOWS_ATOMICS_64)
197  typedef vtkTypeInt64 VTK_ALIGN(8) atomic_type;
198 #else
199  struct VTKCOMMONCORE_EXPORT atomic_type
200  {
201  vtkTypeInt64 var;
203 
204  atomic_type(vtkTypeInt64 init);
205  ~atomic_type();
206  };
207 #endif
208  typedef vtkTypeInt64 value_type;
209 
210  static vtkTypeInt64 AddAndFetch(atomic_type *ref, vtkTypeInt64 val);
211  static vtkTypeInt64 SubAndFetch(atomic_type *ref, vtkTypeInt64 val);
212  static vtkTypeInt64 PreIncrement(atomic_type *ref);
213  static vtkTypeInt64 PreDecrement(atomic_type *ref);
214  static vtkTypeInt64 PostIncrement(atomic_type *ref);
215  static vtkTypeInt64 PostDecrement(atomic_type *ref);
216  static vtkTypeInt64 Load(const atomic_type *ref);
217  static void Store(atomic_type *ref, vtkTypeInt64 val);
218 };
219 
220 #endif
221 
222 #if defined(VTK_GCC_ATOMICS_32)
223 template <> class AtomicOps<4>
224 {
225 public:
226  typedef vtkTypeInt32 VTK_ALIGN(4) atomic_type;
227  typedef vtkTypeInt32 value_type;
228 
229  static value_type AddAndFetch(value_type *ref, value_type val)
230  {
231  return __sync_add_and_fetch(ref, val);
232  }
233 
235  {
236  return __sync_sub_and_fetch(ref, val);
237  }
238 
240  {
241  return __sync_add_and_fetch(ref, 1);
242  }
243 
245  {
246  return __sync_sub_and_fetch(ref, 1);
247  }
248 
250  {
251  return __sync_fetch_and_add(ref, 1);
252  }
253 
255  {
256  return __sync_fetch_and_sub(ref, 1);
257  }
258 
259  static value_type Load(const value_type *ref)
260  {
261  __sync_synchronize();
262  return *static_cast<const volatile value_type *>(ref);
263  }
264 
265  static void Store(value_type *ref, value_type val)
266  {
267  *static_cast<volatile value_type*>(ref) = val;
268  __sync_synchronize();
269  }
270 };
271 
272 #elif defined(VTK_APPLE_ATOMICS_32)
273 template <> class AtomicOps<4>
274 {
275 public:
276  typedef vtkTypeInt32 VTK_ALIGN(4) atomic_type;
277  typedef vtkTypeInt32 value_type;
278 
279  static vtkTypeInt32 AddAndFetch(vtkTypeInt32 *ref, vtkTypeInt32 val)
280  {
281  return OSAtomicAdd32Barrier(val, ref);
282  }
283 
284  static vtkTypeInt32 SubAndFetch(vtkTypeInt32 *ref, vtkTypeInt32 val)
285  {
286  return OSAtomicAdd32Barrier(-val, ref);
287  }
288 
289  static vtkTypeInt32 PreIncrement(vtkTypeInt32 *ref)
290  {
291  return OSAtomicIncrement32Barrier(ref);
292  }
293 
294  static vtkTypeInt32 PreDecrement(vtkTypeInt32 *ref)
295  {
296  return OSAtomicDecrement32Barrier(ref);
297  }
298 
299  static vtkTypeInt32 PostIncrement(vtkTypeInt32 *ref)
300  {
301  vtkTypeInt32 val = OSAtomicIncrement32Barrier(ref);
302  return --val;
303  }
304 
305  static vtkTypeInt32 PostDecrement(vtkTypeInt32 *ref)
306  {
307  vtkTypeInt32 val = OSAtomicDecrement32Barrier(ref);
308  return ++val;
309  }
310 
311  static vtkTypeInt32 Load(const vtkTypeInt32 *ref);
312  {
313  OSMemoryBarrier();
314  return *static_cast<const volatile vtkTypeInt32*>(ref);
315  }
316 
317  static void Store(vtkTypeInt32 *ref, vtkTypeInt32 val);
318  {
319  *static_cast<volatile vtkTypeInt32*>(ref) = val;
320  OSMemoryBarrier();
321  }
322 };
323 
324 #else
325 
326 template <> class VTKCOMMONCORE_EXPORT AtomicOps<4>
327 {
328 public:
329 #if defined(VTK_WINDOWS_ATOMICS_32)
330  typedef vtkTypeInt32 VTK_ALIGN(4) atomic_type;
331 #else
332  struct VTKCOMMONCORE_EXPORT atomic_type
333  {
334  vtkTypeInt32 var;
336 
337  atomic_type(vtkTypeInt32 init);
338  ~atomic_type();
339  };
340 #endif
341  typedef vtkTypeInt32 value_type;
342 
343  static vtkTypeInt32 AddAndFetch(atomic_type *ref, vtkTypeInt32 val);
344  static vtkTypeInt32 SubAndFetch(atomic_type *ref, vtkTypeInt32 val);
345  static vtkTypeInt32 PreIncrement(atomic_type *ref);
346  static vtkTypeInt32 PreDecrement(atomic_type *ref);
347  static vtkTypeInt32 PostIncrement(atomic_type *ref);
348  static vtkTypeInt32 PostDecrement(atomic_type *ref);
349  static vtkTypeInt32 Load(const atomic_type *ref);
350  static void Store(atomic_type *ref, vtkTypeInt32 val);
351 };
352 
353 #endif
354 }
355 #endif // __WRAP__
356 
357 template <typename T> class vtkAtomic : vtk::atomic::detail::IntegralType<T>
358 {
359 private:
361 
362 public:
363  vtkAtomic() : Atomic(0)
364  {
365  }
366 
367  vtkAtomic(T val) : Atomic(static_cast<typename Impl::value_type>(val))
368  {
369  }
370 
371  vtkAtomic(const vtkAtomic<T> &atomic)
372  : Atomic(static_cast<typename Impl::value_type>(atomic.load()))
373  {
374  }
375 
377  {
378  return static_cast<T>(Impl::PreIncrement(&this->Atomic));
379  }
380 
381  T operator++(int)
382  {
383  return static_cast<T>(Impl::PostIncrement(&this->Atomic));
384  }
385 
387  {
388  return static_cast<T>(Impl::PreDecrement(&this->Atomic));
389  }
390 
391  T operator--(int)
392  {
393  return static_cast<T>(Impl::PostDecrement(&this->Atomic));
394  }
395 
396  T operator+=(T val)
397  {
398  return static_cast<T>(Impl::AddAndFetch(&this->Atomic,
399  static_cast<typename Impl::value_type>(val)));
400  }
401 
402  T operator-=(T val)
403  {
404  return static_cast<T>(Impl::SubAndFetch(&this->Atomic,
405  static_cast<typename Impl::value_type>(val)));
406  }
407 
408  operator T() const
409  {
410  return static_cast<T>(Impl::Load(&this->Atomic));
411  }
412 
413  T operator=(T val)
414  {
415  Impl::Store(&this->Atomic, static_cast<typename Impl::value_type>(val));
416  return val;
417  }
418 
420  {
421  this->store(atomic.load());
422  return *this;
423  }
424 
425  T load() const
426  {
427  return static_cast<T>(Impl::Load(&this->Atomic));
428  }
429 
430  void store(T val)
431  {
432  Impl::Store(&this->Atomic, static_cast<typename Impl::value_type>(val));
433  }
434 
435 private:
436  typename Impl::atomic_type Atomic;
437 };
438 
439 
440 template <typename T> class vtkAtomic<T*>
441 {
442 private:
444 
445 public:
446  vtkAtomic() : Atomic(0)
447  {
448  }
449 
450  vtkAtomic(T* val)
451  : Atomic(reinterpret_cast<typename Impl::value_type>(val))
452  {
453  }
454 
455  vtkAtomic(const vtkAtomic<T*> &atomic)
456  : Atomic(reinterpret_cast<typename Impl::value_type>(atomic.load()))
457  {
458  }
459 
461  {
462  return reinterpret_cast<T*>(Impl::AddAndFetch(&this->Atomic, sizeof(T)));
463  }
464 
465  T* operator++(int)
466  {
467  T* val = reinterpret_cast<T*>(Impl::AddAndFetch(&this->Atomic, sizeof(T)));
468  return --val;
469  }
470 
472  {
473  return reinterpret_cast<T*>(Impl::SubAndFetch(&this->Atomic, sizeof(T)));
474  }
475 
476  T* operator--(int)
477  {
478  T* val = reinterpret_cast<T*>(Impl::AddAndFetch(&this->Atomic, sizeof(T)));
479  return ++val;
480  }
481 
482  T* operator+=(std::ptrdiff_t val)
483  {
484  return reinterpret_cast<T*>(Impl::AddAndFetch(&this->Atomic,
485  val * sizeof(T)));
486  }
487 
488  T* operator-=(std::ptrdiff_t val)
489  {
490  return reinterpret_cast<T*>(Impl::SubAndFetch(&this->Atomic,
491  val * sizeof(T)));
492  }
493 
494  operator T*() const
495  {
496  return reinterpret_cast<T*>(Impl::Load(&this->Atomic));
497  }
498 
499  T* operator=(T* val)
500  {
501  Impl::Store(&this->Atomic,
502  reinterpret_cast<typename Impl::value_type>(val));
503  return val;
504  }
505 
507  {
508  this->store(atomic.load());
509  return *this;
510  }
511 
512  T* load() const
513  {
514  return reinterpret_cast<T*>(Impl::Load(&this->Atomic));
515  }
516 
517  void store(T* val)
518  {
519  Impl::Store(&this->Atomic,
520  reinterpret_cast<typename Impl::value_type>(val));
521  }
522 
523 private:
524  typename Impl::atomic_type Atomic;
525 };
526 
527 
528 template <> class vtkAtomic<void*>
529 {
530 private:
532 
533 public:
534  vtkAtomic() : Atomic(0)
535  {
536  }
537 
538  vtkAtomic(void* val)
539  : Atomic(reinterpret_cast<Impl::value_type>(val))
540  {
541  }
542 
544  : Atomic(reinterpret_cast<Impl::value_type>(atomic.load()))
545  {
546  }
547 
548  operator void*() const
549  {
550  return reinterpret_cast<void*>(Impl::Load(&this->Atomic));
551  }
552 
553  void* operator=(void* val)
554  {
555  Impl::Store(&this->Atomic,
556  reinterpret_cast<Impl::value_type>(val));
557  return val;
558  }
559 
561  {
562  this->store(atomic.load());
563  return *this;
564  }
565 
566  void* load() const
567  {
568  return reinterpret_cast<void*>(Impl::Load(&this->Atomic));
569  }
570 
571  void store(void* val)
572  {
573  Impl::Store(&this->Atomic,
574  reinterpret_cast<Impl::value_type>(val));
575  }
576 
577 private:
578  Impl::atomic_type Atomic;
579 };
580 
581 #endif
582 // VTK-HeaderTest-Exclude: vtkAtomic.h
vtkAtomic< T > & operator=(const vtkAtomic< T > &atomic)
Definition: vtkAtomic.h:419
T operator++()
Definition: vtkAtomic.h:376
T * operator--(int)
Definition: vtkAtomic.h:476
vtkAtomic(T val)
Definition: vtkAtomic.h:367
static value_type Load(const value_type *ref)
Definition: vtkAtomic.h:126
T operator--(int)
Definition: vtkAtomic.h:391
T load() const
Definition: vtkAtomic.h:425
static value_type Load(const value_type *ref)
Definition: vtkAtomic.h:259
T * operator+=(std::ptrdiff_t val)
Definition: vtkAtomic.h:482
#define VTKCOMMONCORE_EXPORT
static value_type PostIncrement(value_type *ref)
Definition: vtkAtomic.h:249
#define VTK_ALIGN(X)
Definition: vtkAtomic.h:76
static value_type PostDecrement(value_type *ref)
Definition: vtkAtomic.h:121
T operator-=(T val)
Definition: vtkAtomic.h:402
static void Store(value_type *ref, value_type val)
Definition: vtkAtomic.h:265
Provides support for atomic integers.
Definition: vtkAtomic.h:357
vtkAtomic(const vtkAtomic< T > &atomic)
Definition: vtkAtomic.h:371
static value_type PostDecrement(value_type *ref)
Definition: vtkAtomic.h:254
static value_type PreDecrement(value_type *ref)
Definition: vtkAtomic.h:244
T * load() const
Definition: vtkAtomic.h:512
vtkAtomic< T * > & operator=(const vtkAtomic< T * > &atomic)
Definition: vtkAtomic.h:506
static value_type PostIncrement(value_type *ref)
Definition: vtkAtomic.h:116
static value_type SubAndFetch(value_type *ref, value_type val)
Definition: vtkAtomic.h:234
static value_type PreIncrement(value_type *ref)
Definition: vtkAtomic.h:239
T * operator-=(std::ptrdiff_t val)
Definition: vtkAtomic.h:488
void store(T *val)
Definition: vtkAtomic.h:517
static value_type PreDecrement(value_type *ref)
Definition: vtkAtomic.h:111
static void Store(value_type *ref, value_type val)
Definition: vtkAtomic.h:132
vtkAtomic(T *val)
Definition: vtkAtomic.h:450
T operator--()
Definition: vtkAtomic.h:386
void store(T val)
Definition: vtkAtomic.h:430
vtkTypeInt32 VTK_ALIGN(4) atomic_type
Definition: vtkAtomic.h:226
vtkAtomic< void * > & operator=(const vtkAtomic< void * > &atomic)
Definition: vtkAtomic.h:560
vtkTypeInt64 value_type
Definition: vtkAtomic.h:94
static value_type SubAndFetch(value_type *ref, value_type val)
Definition: vtkAtomic.h:101
void store(void *val)
Definition: vtkAtomic.h:571
Critical section locking class.
vtkTypeInt32 value_type
Definition: vtkAtomic.h:227
T * operator=(T *val)
Definition: vtkAtomic.h:499
vtkAtomic(const vtkAtomic< void * > &atomic)
Definition: vtkAtomic.h:543
static value_type PreIncrement(value_type *ref)
Definition: vtkAtomic.h:106
void * load() const
Definition: vtkAtomic.h:566
T operator=(T val)
Definition: vtkAtomic.h:413
vtkAtomic(void *val)
Definition: vtkAtomic.h:538
T operator++(int)
Definition: vtkAtomic.h:381
T operator+=(T val)
Definition: vtkAtomic.h:396
void * operator=(void *val)
Definition: vtkAtomic.h:553
vtkTypeInt64 VTK_ALIGN(8) atomic_type
Definition: vtkAtomic.h:93
T * operator++(int)
Definition: vtkAtomic.h:465
vtkAtomic(const vtkAtomic< T * > &atomic)
Definition: vtkAtomic.h:455