Atomic 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /* -*-c++-*- OpenThreads library, Copyright (C) 2008 The Open Thread Group
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef _OPENTHREADS_ATOMIC_
  14. #define _OPENTHREADS_ATOMIC_
  15. #include <OpenThreads/Config>
  16. #include <OpenThreads/Exports>
  17. #if defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC)
  18. # include <libkern/OSAtomic.h>
  19. # define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
  20. #elif defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) && defined(__i386__)
  21. # define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
  22. #elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
  23. # define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES
  24. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  25. # include <atomic.h>
  26. # include "Mutex"
  27. # include "ScopedLock"
  28. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  29. # include "Mutex"
  30. # include "ScopedLock"
  31. #endif
  32. #if defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
  33. #define _OPENTHREADS_ATOMIC_INLINE
  34. #else
  35. #define _OPENTHREADS_ATOMIC_INLINE inline
  36. #endif
  37. namespace OpenThreads {
  38. /**
  39. * @class Atomic
  40. * @brief This class provides an atomic increment and decrement operation.
  41. */
  42. class OPENTHREAD_EXPORT_DIRECTIVE Atomic {
  43. public:
  44. Atomic(unsigned value = 0) : _value(value)
  45. { }
  46. _OPENTHREADS_ATOMIC_INLINE unsigned operator++();
  47. _OPENTHREADS_ATOMIC_INLINE unsigned operator--();
  48. _OPENTHREADS_ATOMIC_INLINE unsigned AND(unsigned value);
  49. _OPENTHREADS_ATOMIC_INLINE unsigned OR(unsigned value);
  50. _OPENTHREADS_ATOMIC_INLINE unsigned XOR(unsigned value);
  51. _OPENTHREADS_ATOMIC_INLINE unsigned exchange(unsigned value = 0);
  52. _OPENTHREADS_ATOMIC_INLINE operator unsigned() const;
  53. private:
  54. Atomic(const Atomic&);
  55. Atomic& operator=(const Atomic&);
  56. #if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  57. mutable Mutex _mutex;
  58. #endif
  59. #if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
  60. volatile long _value;
  61. #elif defined(_OPENTHREADS_ATOMIC_USE_BSD_ATOMIC)
  62. volatile int32_t _value;
  63. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  64. volatile uint_t _value;
  65. mutable Mutex _mutex; // needed for xor
  66. #else
  67. volatile unsigned _value;
  68. #endif
  69. };
  70. /**
  71. * @class AtomicPtr
  72. * @brief This class provides an atomic pointer assignment using cas operations.
  73. */
  74. class OPENTHREAD_EXPORT_DIRECTIVE AtomicPtr {
  75. public:
  76. AtomicPtr(void* ptr = 0) : _ptr(ptr)
  77. { }
  78. ~AtomicPtr()
  79. { _ptr = 0; }
  80. // assigns a new pointer
  81. _OPENTHREADS_ATOMIC_INLINE bool assign(void* ptrNew, const void* const ptrOld);
  82. _OPENTHREADS_ATOMIC_INLINE void* get() const;
  83. private:
  84. AtomicPtr(const AtomicPtr&);
  85. AtomicPtr& operator=(const AtomicPtr&);
  86. #if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  87. mutable Mutex _mutex;
  88. #endif
  89. void* volatile _ptr;
  90. };
  91. #if !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
  92. _OPENTHREADS_ATOMIC_INLINE unsigned
  93. Atomic::operator++()
  94. {
  95. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  96. return __sync_add_and_fetch(&_value, 1);
  97. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  98. return __add_and_fetch(&_value, 1);
  99. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  100. return atomic_inc_uint_nv(&_value);
  101. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  102. ScopedLock<Mutex> lock(_mutex);
  103. return ++_value;
  104. #else
  105. return ++_value;
  106. #endif
  107. }
  108. _OPENTHREADS_ATOMIC_INLINE unsigned
  109. Atomic::operator--()
  110. {
  111. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  112. return __sync_sub_and_fetch(&_value, 1);
  113. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  114. return __sub_and_fetch(&_value, 1);
  115. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  116. return atomic_dec_uint_nv(&_value);
  117. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  118. ScopedLock<Mutex> lock(_mutex);
  119. return --_value;
  120. #else
  121. return --_value;
  122. #endif
  123. }
  124. _OPENTHREADS_ATOMIC_INLINE unsigned
  125. Atomic::AND(unsigned value)
  126. {
  127. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  128. return __sync_fetch_and_and(&_value, value);
  129. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  130. return __and_and_fetch(&_value, value);
  131. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  132. return atomic_and_uint_nv(&_value, value);
  133. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  134. ScopedLock<Mutex> lock(_mutex);
  135. _value &= value;
  136. return _value;
  137. #else
  138. _value &= value;
  139. return _value;
  140. #endif
  141. }
  142. _OPENTHREADS_ATOMIC_INLINE unsigned
  143. Atomic::OR(unsigned value)
  144. {
  145. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  146. return __sync_fetch_and_or(&_value, value);
  147. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  148. return __or_and_fetch(&_value, value);
  149. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  150. return atomic_or_uint_nv(&_value, value);
  151. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  152. ScopedLock<Mutex> lock(_mutex);
  153. _value |= value;
  154. return _value;
  155. #else
  156. _value |= value;
  157. return _value;
  158. #endif
  159. }
  160. _OPENTHREADS_ATOMIC_INLINE unsigned
  161. Atomic::XOR(unsigned value)
  162. {
  163. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  164. return __sync_fetch_and_xor(&_value, value);
  165. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  166. return __xor_and_fetch(&_value, value);
  167. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  168. ScopedLock<Mutex> lock(_mutex);
  169. _value ^= value;
  170. return _value;
  171. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  172. ScopedLock<Mutex> lock(_mutex);
  173. _value ^= value;
  174. return _value;
  175. #else
  176. _value ^= value;
  177. return _value;
  178. #endif
  179. }
  180. _OPENTHREADS_ATOMIC_INLINE unsigned
  181. Atomic::exchange(unsigned value)
  182. {
  183. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  184. return __sync_lock_test_and_set(&_value, value);
  185. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  186. return __compare_and_swap(&_value, _value, value);
  187. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  188. return atomic_cas_uint(&_value, _value, value);
  189. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  190. ScopedLock<Mutex> lock(_mutex);
  191. unsigned oldval = _value;
  192. _value = value;
  193. return oldval;
  194. #else
  195. unsigned oldval = _value;
  196. _value = value;
  197. return oldval;
  198. #endif
  199. }
  200. _OPENTHREADS_ATOMIC_INLINE
  201. Atomic::operator unsigned() const
  202. {
  203. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  204. __sync_synchronize();
  205. return _value;
  206. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  207. __synchronize();
  208. return _value;
  209. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  210. membar_consumer(); // Hmm, do we need???
  211. return _value;
  212. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  213. ScopedLock<Mutex> lock(_mutex);
  214. return _value;
  215. #else
  216. return _value;
  217. #endif
  218. }
  219. _OPENTHREADS_ATOMIC_INLINE bool
  220. AtomicPtr::assign(void* ptrNew, const void* const ptrOld)
  221. {
  222. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  223. return __sync_bool_compare_and_swap(&_ptr, (void *)ptrOld, ptrNew);
  224. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  225. return __compare_and_swap((unsigned long*)&_ptr, (unsigned long)ptrOld, (unsigned long)ptrNew);
  226. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  227. return ptrOld == atomic_cas_ptr(&_ptr, const_cast<void*>(ptrOld), ptrNew);
  228. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  229. ScopedLock<Mutex> lock(_mutex);
  230. if (_ptr != ptrOld)
  231. return false;
  232. _ptr = ptrNew;
  233. return true;
  234. #else
  235. if (_ptr != ptrOld)
  236. return false;
  237. _ptr = ptrNew;
  238. return true;
  239. #endif
  240. }
  241. _OPENTHREADS_ATOMIC_INLINE void*
  242. AtomicPtr::get() const
  243. {
  244. #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
  245. __sync_synchronize();
  246. return _ptr;
  247. #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
  248. __synchronize();
  249. return _ptr;
  250. #elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
  251. membar_consumer(); // Hmm, do we need???
  252. return _ptr;
  253. #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
  254. ScopedLock<Mutex> lock(_mutex);
  255. return _ptr;
  256. #else
  257. return _ptr;
  258. #endif
  259. }
  260. #endif // !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES)
  261. }
  262. #endif // _OPENTHREADS_ATOMIC_