VTK
|
00001 /*========================================================================= 00002 00003 Program: Visualization Toolkit 00004 Module: vtkAtomicInt.h 00005 00006 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 00007 All rights reserved. 00008 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 00009 00010 This software is distributed WITHOUT ANY WARRANTY; without even 00011 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00012 PURPOSE. See the above copyright notice for more information. 00013 00014 =========================================================================*/ 00039 #ifndef vtkAtomicInt_h 00040 #define vtkAtomicInt_h 00041 00042 #include "vtkCommonCoreModule.h" // For export macro 00043 #include "vtkSystemIncludes.h" 00044 #include "vtkConfigure.h" 00045 00046 #if defined(__APPLE__) 00047 # include <libkern/OSAtomic.h> 00048 #endif 00049 00050 #if (defined(_WIN32) && !defined(__MINGW32__)) 00051 # define VTK_WINDOWS_ATOMIC 00052 # if defined(_MSC_VER) 00053 # pragma warning(disable:4324) // disable warning about the padding due to alignment 00054 # endif 00055 #endif 00056 00057 #if defined(VTK_WINDOWS_ATOMIC) || defined(__APPLE__) || defined(VTK_HAVE_SYNC_BUILTINS) 00058 # define VTK_HAS_ATOMIC32 00059 #endif 00060 00061 // Overall, we assume that 64 bit atomic operations are not available on 32 00062 // bit systems. 00063 #if VTK_SIZEOF_VOID_P == 8 00064 # if defined(VTK_WINDOWS_ATOMIC) || defined(__APPLE__) || defined(VTK_HAVE_SYNC_BUILTINS) 00065 # define VTK_HAS_ATOMIC64 00066 # endif 00067 #endif 00068 00069 #if !defined(VTK_HAS_ATOMIC64) || !defined(VTK_HAS_ATOMIC32) 00070 class vtkSimpleCriticalSection; 00071 #endif 00072 00073 // Below are the actual implementations of 32 and 64 bit atomic operations. 00074 namespace detail 00075 { 00076 #if defined (VTK_WINDOWS_ATOMIC) 00077 # define VTK__ALIGN32 __declspec(align(32)) 00078 #else 00079 # define VTK__ALIGN32 00080 #endif 00081 00082 template <typename T> class vtkAtomicIntImpl; 00083 00084 template <> 00085 #if defined(VTK_HAS_ATOMIC32) && !defined(VTK_WINDOWS_ATOMIC) 00086 class vtkAtomicIntImpl<vtkTypeInt32> 00087 #else 00088 class VTKCOMMONCORE_EXPORT vtkAtomicIntImpl<vtkTypeInt32> 00089 #endif 00090 { 00091 public: 00092 00094 00095 #if defined(VTK_HAS_ATOMIC32) && !defined(VTK_WINDOWS_ATOMIC) 00096 vtkTypeInt32 operator++() 00097 { 00098 # if defined(__APPLE__) 00099 return OSAtomicIncrement32Barrier(&this->Value); 00101 00102 // GCC, CLANG, etc 00103 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00104 return __sync_add_and_fetch(&this->Value, 1); 00105 00106 # endif 00107 } 00108 00110 00111 vtkTypeInt32 operator--() 00112 { 00113 # if defined(__APPLE__) 00114 return OSAtomicDecrement32Barrier(&this->Value); 00116 00117 // GCC, CLANG, etc 00118 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00119 return __sync_sub_and_fetch(&this->Value, 1); 00120 00121 # endif 00122 } 00123 00125 00126 vtkTypeInt32 operator+=(vtkTypeInt32 val) 00127 { 00128 # if defined(__APPLE__) 00129 return OSAtomicAdd32Barrier(val, &this->Value); 00131 00132 // GCC, CLANG, etc 00133 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00134 return __sync_add_and_fetch(&this->Value, val); 00135 00136 # endif 00137 } 00138 00140 00141 vtkTypeInt32 load() const 00142 { 00143 # if defined(__APPLE__) 00144 vtkTypeInt32 retval = 0; 00145 OSAtomicCompareAndSwap32Barrier(retval, this->Value, &retval); 00146 return retval; 00148 00149 // GCC, CLANG, etc 00150 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00151 vtkTypeInt32 retval = 0; 00152 __sync_val_compare_and_swap(&retval, retval, this->Value); 00153 return retval; 00154 00155 # endif 00156 } 00157 00159 00160 void store(vtkTypeInt32 val) 00161 { 00162 # if defined(__APPLE__) 00163 OSAtomicCompareAndSwap32Barrier(this->Value, val, &this->Value); 00165 00166 // GCC, CLANG, etc 00167 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00168 __sync_val_compare_and_swap(&this->Value, this->Value, val); 00169 00170 #endif 00171 } 00172 00173 #else // defined(VTK_HAS_ATOMIC32) && !defined(VTK_WINDOWS_ATOMIC) 00174 00175 // These methods are for when using a mutex. Same as above. 00176 // A virtual descructor is used becase the mutex is constructed 00177 // with new to avoid including windows header in the .h file. 00178 vtkAtomicIntImpl<vtkTypeInt32>(); 00179 virtual ~vtkAtomicIntImpl<vtkTypeInt32>(); 00180 vtkTypeInt32 operator++(); 00181 vtkTypeInt32 operator--(); 00182 vtkTypeInt32 operator+=(vtkTypeInt32 val); 00183 vtkTypeInt32 load() const; 00184 void store(vtkTypeInt32 val); 00185 00186 #endif // defined(VTK_HAS_ATOMIC32) && !defined(VTK_WINDOWS_ATOMIC) 00187 00188 protected: 00189 // Explicitely aligning Value on Windows is probably not necessary 00190 // since the compiler should automatically do it. Just being extra 00191 // cautious since the InterlockedXXX() functions require alignment. 00192 VTK__ALIGN32 vtkTypeInt32 Value; 00193 00194 #if !defined(VTK_HAS_ATOMIC32) 00195 vtkSimpleCriticalSection* AtomicInt32CritSec; 00196 #endif 00197 }; 00198 00199 #if defined (VTK_WINDOWS_ATOMIC) 00200 # define VTK__ALIGN64 __declspec(align(64)) 00201 #else 00202 # define VTK__ALIGN64 00203 #endif 00204 00205 template <> 00206 #if defined(VTK_HAS_ATOMIC64) && !defined(VTK_WINDOWS_ATOMIC) 00207 class vtkAtomicIntImpl<vtkTypeInt64> 00208 #else 00209 class VTKCOMMONCORE_EXPORT vtkAtomicIntImpl<vtkTypeInt64> 00210 #endif 00211 { 00212 public: 00213 00215 00216 #if defined(VTK_HAS_ATOMIC64) && !defined(VTK_WINDOWS_ATOMIC) 00217 vtkTypeInt64 operator++() 00218 { 00219 # if defined(__APPLE__) 00220 return OSAtomicIncrement64Barrier(&this->Value); 00222 00223 // GCC, CLANG, etc 00224 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00225 return __sync_add_and_fetch(&this->Value, 1); 00226 00227 # endif 00228 } 00229 00231 00232 vtkTypeInt64 operator--() 00233 { 00234 # if defined(__APPLE__) 00235 return OSAtomicDecrement64Barrier(&this->Value); 00237 00238 // GCC, CLANG, etc 00239 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00240 return __sync_sub_and_fetch(&this->Value, 1); 00241 00242 # endif 00243 } 00244 00246 00247 vtkTypeInt64 operator+=(vtkTypeInt64 val) 00248 { 00249 # if defined(__APPLE__) 00250 return OSAtomicAdd64Barrier(val, &this->Value); 00252 00253 // GCC, CLANG, etc 00254 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00255 return __sync_add_and_fetch(&this->Value, val); 00256 00257 # endif 00258 } 00259 00261 00262 vtkTypeInt64 load() const 00263 { 00264 # if defined(__APPLE__) 00265 vtkTypeInt64 retval = 0; 00266 OSAtomicCompareAndSwap64Barrier(retval, this->Value, &retval); 00267 return retval; 00269 00270 // GCC, CLANG, etc 00271 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00272 vtkTypeInt64 retval = 0; 00273 __sync_val_compare_and_swap(&retval, retval, this->Value); 00274 return retval; 00275 00276 # endif 00277 } 00278 00280 00281 void store(vtkTypeInt64 val) 00282 { 00283 # if defined(__APPLE__) 00284 OSAtomicCompareAndSwap64Barrier(this->Value, val, &this->Value); 00286 00287 // GCC, CLANG, etc 00288 # elif defined(VTK_HAVE_SYNC_BUILTINS) 00289 __sync_val_compare_and_swap(&this->Value, this->Value, val); 00290 00291 # endif 00292 } 00293 00294 #else // defined(VTK_HAS_ATOMIC64) && !defined(VTK_WINDOWS_ATOMIC) 00295 00296 // These methods are for when using a mutex. Same as above. 00297 // A virtual descructor is used becase the mutex is constructed 00298 // with new to avoid including windows header in the .h file. 00299 vtkAtomicIntImpl<vtkTypeInt64>(); 00300 virtual ~vtkAtomicIntImpl<vtkTypeInt64>(); 00301 vtkTypeInt64 operator++(); 00302 vtkTypeInt64 operator--(); 00303 vtkTypeInt64 operator+=(vtkTypeInt64 val); 00304 vtkTypeInt64 load() const; 00305 void store(vtkTypeInt64 val); 00306 00307 #endif // defined(VTK_HAS_ATOMIC64) && !defined(VTK_WINDOWS_ATOMIC) 00308 00309 protected: 00310 // Explicitely aligning Value on Windows is probably not necessary 00311 // since the compiler should automatically do it. Just being extra 00312 // cautious since the InterlockedXXX() functions require alignment. 00313 VTK__ALIGN64 vtkTypeInt64 Value; 00314 00315 #if !defined(VTK_HAS_ATOMIC64) 00316 vtkSimpleCriticalSection* AtomicInt64CritSec; 00317 #endif 00318 }; 00319 } 00320 00321 template <typename T> 00322 class vtkAtomicInt: public detail::vtkAtomicIntImpl<T> 00323 { 00324 typedef detail::vtkAtomicIntImpl<T> Superclass; 00325 00326 public: 00328 00329 vtkAtomicInt() 00330 { 00331 this->Value = 0; 00332 } 00334 00336 00337 vtkAtomicInt(T val) 00338 { 00339 this->Value = val; 00340 } 00342 00344 00345 T operator++() 00346 { 00347 return this->Superclass::operator++(); 00348 } 00350 00352 00353 T operator++(int) 00354 { 00355 return this->operator++() - 1; 00356 } 00358 00360 00361 T operator--() 00362 { 00363 return this->Superclass::operator--(); 00364 } 00366 00368 00369 T operator--(int) 00370 { 00371 return this->operator--() + 1; 00372 } 00374 00376 00377 T operator-=(T val) 00378 { 00379 return this->operator+=(-val); 00380 } 00382 00384 00385 operator T() const 00386 { 00387 return this->load(); 00388 } 00390 00392 00393 T operator=(T val) 00394 { 00395 this->store(val); 00396 return val; 00397 } 00398 }; 00400 00401 00402 #endif 00403 // VTK-HeaderTest-Exclude: vtkAtomicInt.h