cas128strong.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. #ifndef BOOST_ATOMIC_DETAIL_CAS128STRONG_HPP
  2. #define BOOST_ATOMIC_DETAIL_CAS128STRONG_HPP
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Copyright (c) 2011 Helge Bahmann
  8. // Copyright (c) 2013 Tim Blechmann, Andrey Semashev
  9. // Build 128-bit atomic operation on integers/UDTs from platform_cmpxchg128_strong
  10. // primitive. It is assumed that 128-bit loads/stores are not
  11. // atomic, so they are implemented through platform_load128/platform_store128.
  12. #include <string.h>
  13. #include <cstddef>
  14. #include <boost/cstdint.hpp>
  15. #include <boost/memory_order.hpp>
  16. #include <boost/atomic/detail/config.hpp>
  17. #include <boost/atomic/detail/base.hpp>
  18. #ifdef BOOST_HAS_PRAGMA_ONCE
  19. #pragma once
  20. #endif
  21. namespace boost {
  22. namespace atomics {
  23. namespace detail {
  24. /* integral types */
  25. template<typename T, bool Sign>
  26. class base_atomic<T, int, 16, Sign>
  27. {
  28. private:
  29. typedef base_atomic this_type;
  30. typedef T value_type;
  31. typedef T difference_type;
  32. protected:
  33. typedef value_type value_arg_type;
  34. public:
  35. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  36. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  37. void
  38. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  39. {
  40. platform_fence_before_store(order);
  41. platform_store128(v, &v_);
  42. platform_fence_after_store(order);
  43. }
  44. value_type
  45. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  46. {
  47. value_type v = platform_load128(&v_);
  48. platform_fence_after_load(order);
  49. return v;
  50. }
  51. value_type
  52. exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  53. {
  54. value_type original = load(memory_order_relaxed);
  55. do {
  56. } while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
  57. return original;
  58. }
  59. bool
  60. compare_exchange_weak(
  61. value_type & expected,
  62. value_type desired,
  63. memory_order success_order,
  64. memory_order failure_order) volatile BOOST_NOEXCEPT
  65. {
  66. return compare_exchange_strong(expected, desired, success_order, failure_order);
  67. }
  68. bool
  69. compare_exchange_strong(
  70. value_type & expected,
  71. value_type desired,
  72. memory_order success_order,
  73. memory_order failure_order) volatile BOOST_NOEXCEPT
  74. {
  75. platform_fence_before(success_order);
  76. bool success = platform_cmpxchg128_strong(expected, desired, &v_);
  77. if (success) {
  78. platform_fence_after(success_order);
  79. } else {
  80. platform_fence_after(failure_order);
  81. }
  82. return success;
  83. }
  84. value_type
  85. fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  86. {
  87. value_type original = load(memory_order_relaxed);
  88. do {
  89. } while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed));
  90. return original;
  91. }
  92. value_type
  93. fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  94. {
  95. value_type original = load(memory_order_relaxed);
  96. do {
  97. } while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed));
  98. return original;
  99. }
  100. value_type
  101. fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  102. {
  103. value_type original = load(memory_order_relaxed);
  104. do {
  105. } while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed));
  106. return original;
  107. }
  108. value_type
  109. fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  110. {
  111. value_type original = load(memory_order_relaxed);
  112. do {
  113. } while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed));
  114. return original;
  115. }
  116. value_type
  117. fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  118. {
  119. value_type original = load(memory_order_relaxed);
  120. do {
  121. } while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed));
  122. return original;
  123. }
  124. bool
  125. is_lock_free(void) const volatile BOOST_NOEXCEPT
  126. {
  127. return true;
  128. }
  129. BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
  130. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  131. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  132. private:
  133. value_type v_;
  134. };
  135. /* generic types */
  136. #if defined(BOOST_HAS_INT128)
  137. typedef boost::uint128_type storage128_type;
  138. #else // defined(BOOST_HAS_INT128)
  139. struct BOOST_ALIGNMENT(16) storage128_type
  140. {
  141. uint64_t data[2];
  142. };
  143. inline bool operator== (storage128_type const& left, storage128_type const& right)
  144. {
  145. return left.data[0] == right.data[0] && left.data[1] == right.data[1];
  146. }
  147. inline bool operator!= (storage128_type const& left, storage128_type const& right)
  148. {
  149. return !(left == right);
  150. }
  151. #endif // defined(BOOST_HAS_INT128)
  152. template<typename T, bool Sign>
  153. class base_atomic<T, void, 16, Sign>
  154. {
  155. private:
  156. typedef base_atomic this_type;
  157. typedef T value_type;
  158. typedef storage128_type storage_type;
  159. protected:
  160. typedef value_type const& value_arg_type;
  161. public:
  162. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  163. explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0)
  164. {
  165. memcpy(&v_, &v, sizeof(value_type));
  166. }
  167. void
  168. store(value_type const& value, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  169. {
  170. storage_type value_s = 0;
  171. memcpy(&value_s, &value, sizeof(value_type));
  172. platform_fence_before_store(order);
  173. platform_store128(value_s, &v_);
  174. platform_fence_after_store(order);
  175. }
  176. value_type
  177. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  178. {
  179. storage_type value_s = platform_load128(&v_);
  180. platform_fence_after_load(order);
  181. value_type value;
  182. memcpy(&value, &value_s, sizeof(value_type));
  183. return value;
  184. }
  185. value_type
  186. exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  187. {
  188. value_type original = load(memory_order_relaxed);
  189. do {
  190. } while (!compare_exchange_weak(original, v, order, memory_order_relaxed));
  191. return original;
  192. }
  193. bool
  194. compare_exchange_weak(
  195. value_type & expected,
  196. value_type const& desired,
  197. memory_order success_order,
  198. memory_order failure_order) volatile BOOST_NOEXCEPT
  199. {
  200. return compare_exchange_strong(expected, desired, success_order, failure_order);
  201. }
  202. bool
  203. compare_exchange_strong(
  204. value_type & expected,
  205. value_type const& desired,
  206. memory_order success_order,
  207. memory_order failure_order) volatile BOOST_NOEXCEPT
  208. {
  209. storage_type expected_s = 0, desired_s = 0;
  210. memcpy(&expected_s, &expected, sizeof(value_type));
  211. memcpy(&desired_s, &desired, sizeof(value_type));
  212. platform_fence_before(success_order);
  213. bool success = platform_cmpxchg128_strong(expected_s, desired_s, &v_);
  214. if (success) {
  215. platform_fence_after(success_order);
  216. } else {
  217. platform_fence_after(failure_order);
  218. memcpy(&expected, &expected_s, sizeof(value_type));
  219. }
  220. return success;
  221. }
  222. bool
  223. is_lock_free(void) const volatile BOOST_NOEXCEPT
  224. {
  225. return true;
  226. }
  227. BOOST_ATOMIC_DECLARE_BASE_OPERATORS
  228. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  229. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  230. private:
  231. storage_type v_;
  232. };
  233. }
  234. }
  235. }
  236. #endif