atomic_ref_template.hpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. /*
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * Copyright (c) 2020 Andrey Semashev
  7. */
  8. /*!
  9. * \file atomic/detail/atomic_ref_template.hpp
  10. *
  11. * This header contains interface definition of \c atomic_ref template.
  12. */
  13. #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_REF_TEMPLATE_HPP_INCLUDED_
  14. #define BOOST_ATOMIC_DETAIL_ATOMIC_REF_TEMPLATE_HPP_INCLUDED_
  15. #include <cstddef>
  16. #include <boost/cstdint.hpp>
  17. #include <boost/assert.hpp>
  18. #include <boost/static_assert.hpp>
  19. #include <boost/memory_order.hpp>
  20. #include <boost/atomic/detail/config.hpp>
  21. #include <boost/atomic/detail/intptr.hpp>
  22. #include <boost/atomic/detail/classify.hpp>
  23. #include <boost/atomic/detail/addressof.hpp>
  24. #include <boost/atomic/detail/storage_traits.hpp>
  25. #include <boost/atomic/detail/bitwise_cast.hpp>
  26. #include <boost/atomic/detail/integral_conversions.hpp>
  27. #include <boost/atomic/detail/operations.hpp>
  28. #include <boost/atomic/detail/extra_operations.hpp>
  29. #include <boost/atomic/detail/memory_order_utils.hpp>
  30. #include <boost/atomic/detail/type_traits/is_signed.hpp>
  31. #include <boost/atomic/detail/type_traits/is_trivially_copyable.hpp>
  32. #include <boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp>
  33. #include <boost/atomic/detail/type_traits/alignment_of.hpp>
  34. #include <boost/atomic/detail/type_traits/conditional.hpp>
  35. #include <boost/atomic/detail/type_traits/integral_constant.hpp>
  36. #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
  37. #include <boost/atomic/detail/bitwise_fp_cast.hpp>
  38. #include <boost/atomic/detail/fp_operations.hpp>
  39. #include <boost/atomic/detail/extra_fp_operations.hpp>
  40. #endif
  41. #ifdef BOOST_HAS_PRAGMA_ONCE
  42. #pragma once
  43. #endif
  44. #if defined(BOOST_MSVC)
  45. #pragma warning(push)
  46. // 'boost::atomics::atomic_ref<T>' : multiple assignment operators specified
  47. #pragma warning(disable: 4522)
  48. #endif
  49. /*
  50. * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE,
  51. * see comment for convert_memory_order_to_gcc in ops_gcc_atomic.hpp.
  52. */
  53. namespace boost {
  54. namespace atomics {
  55. namespace detail {
  56. template< typename T, bool IsSigned >
  57. struct is_atomic_ref_lock_free
  58. {
  59. typedef T value_type;
  60. typedef atomics::detail::operations< sizeof(value_type), IsSigned > operations;
  61. typedef typename operations::storage_type storage_type;
  62. static BOOST_CONSTEXPR_OR_CONST bool value = sizeof(value_type) == sizeof(storage_type) && operations::is_always_lock_free;
  63. };
  64. template< typename T, bool IsSigned >
  65. class base_atomic_ref_common
  66. {
  67. public:
  68. typedef T value_type;
  69. protected:
  70. typedef typename atomics::detail::conditional<
  71. atomics::detail::is_atomic_ref_lock_free< T, IsSigned >::value,
  72. atomics::detail::operations< sizeof(value_type), IsSigned >,
  73. atomics::detail::emulated_operations< sizeof(value_type), atomics::detail::alignment_of< value_type >::value, IsSigned >
  74. >::type operations;
  75. typedef typename atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type;
  76. typedef typename operations::storage_type storage_type;
  77. public:
  78. static BOOST_CONSTEXPR_OR_CONST std::size_t required_alignment = atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment ? operations::storage_alignment : atomics::detail::alignment_of< value_type >::value;
  79. static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = operations::is_always_lock_free;
  80. protected:
  81. value_type* m_value;
  82. public:
  83. BOOST_FORCEINLINE explicit base_atomic_ref_common(value_type& v) BOOST_NOEXCEPT : m_value(atomics::detail::addressof(v))
  84. {
  85. }
  86. protected:
  87. BOOST_FORCEINLINE storage_type& storage() const BOOST_NOEXCEPT
  88. {
  89. return *reinterpret_cast< storage_type* >(m_value);
  90. }
  91. };
  92. #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
  93. template< typename T, bool IsSigned >
  94. BOOST_CONSTEXPR_OR_CONST std::size_t base_atomic_ref_common< T, IsSigned >::required_alignment;
  95. template< typename T, bool IsSigned >
  96. BOOST_CONSTEXPR_OR_CONST bool base_atomic_ref_common< T, IsSigned >::is_always_lock_free;
  97. #endif
  98. template< typename T, typename Kind >
  99. class base_atomic_ref;
  100. //! General template. Implementation for user-defined types, such as structs and enums, and pointers to non-object types
  101. template< typename T >
  102. class base_atomic_ref< T, void > :
  103. public base_atomic_ref_common< T, false >
  104. {
  105. private:
  106. typedef base_atomic_ref_common< T, false > base_type;
  107. public:
  108. typedef typename base_type::value_type value_type;
  109. protected:
  110. typedef typename base_type::operations operations;
  111. typedef typename base_type::storage_type storage_type;
  112. typedef typename base_type::value_arg_type value_arg_type;
  113. private:
  114. typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
  115. public:
  116. BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {})
  117. BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
  118. {
  119. }
  120. BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  121. {
  122. BOOST_ASSERT(order != memory_order_consume);
  123. BOOST_ASSERT(order != memory_order_acquire);
  124. BOOST_ASSERT(order != memory_order_acq_rel);
  125. operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order);
  126. }
  127. BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  128. {
  129. BOOST_ASSERT(order != memory_order_release);
  130. BOOST_ASSERT(order != memory_order_acq_rel);
  131. return atomics::detail::bitwise_cast< value_type >(operations::load(this->storage(), order));
  132. }
  133. BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  134. {
  135. return atomics::detail::bitwise_cast< value_type >(operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order));
  136. }
  137. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT
  138. {
  139. BOOST_ASSERT(failure_order != memory_order_release);
  140. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  141. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  142. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  143. }
  144. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  145. {
  146. return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
  147. }
  148. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT
  149. {
  150. BOOST_ASSERT(failure_order != memory_order_release);
  151. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  152. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  153. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  154. }
  155. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  156. {
  157. return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
  158. }
  159. BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
  160. private:
  161. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  162. {
  163. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  164. return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
  165. #else
  166. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  167. #endif
  168. }
  169. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  170. {
  171. storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
  172. const bool res = operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
  173. expected = atomics::detail::bitwise_cast< value_type >(old_value);
  174. return res;
  175. }
  176. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  177. {
  178. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  179. return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
  180. #else
  181. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  182. #endif
  183. }
  184. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  185. {
  186. storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
  187. const bool res = operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
  188. expected = atomics::detail::bitwise_cast< value_type >(old_value);
  189. return res;
  190. }
  191. };
  192. //! Implementation for integers
  193. template< typename T >
  194. class base_atomic_ref< T, int > :
  195. public base_atomic_ref_common< T, atomics::detail::is_signed< T >::value >
  196. {
  197. private:
  198. typedef base_atomic_ref_common< T, atomics::detail::is_signed< T >::value > base_type;
  199. public:
  200. typedef typename base_type::value_type value_type;
  201. typedef typename base_type::value_type difference_type;
  202. protected:
  203. typedef typename base_type::operations operations;
  204. typedef atomics::detail::extra_operations< operations, operations::storage_size, operations::is_signed > extra_operations;
  205. typedef typename base_type::storage_type storage_type;
  206. typedef value_type value_arg_type;
  207. private:
  208. typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
  209. public:
  210. BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {})
  211. BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
  212. {
  213. }
  214. // Standard methods
  215. BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  216. {
  217. BOOST_ASSERT(order != memory_order_consume);
  218. BOOST_ASSERT(order != memory_order_acquire);
  219. BOOST_ASSERT(order != memory_order_acq_rel);
  220. operations::store(this->storage(), static_cast< storage_type >(v), order);
  221. }
  222. BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  223. {
  224. BOOST_ASSERT(order != memory_order_release);
  225. BOOST_ASSERT(order != memory_order_acq_rel);
  226. return atomics::detail::integral_truncate< value_type >(operations::load(this->storage(), order));
  227. }
  228. BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  229. {
  230. return atomics::detail::integral_truncate< value_type >(operations::fetch_add(this->storage(), static_cast< storage_type >(v), order));
  231. }
  232. BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  233. {
  234. return atomics::detail::integral_truncate< value_type >(operations::fetch_sub(this->storage(), static_cast< storage_type >(v), order));
  235. }
  236. BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  237. {
  238. return atomics::detail::integral_truncate< value_type >(operations::exchange(this->storage(), static_cast< storage_type >(v), order));
  239. }
  240. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  241. {
  242. BOOST_ASSERT(failure_order != memory_order_release);
  243. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  244. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  245. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  246. }
  247. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  248. {
  249. return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
  250. }
  251. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  252. {
  253. BOOST_ASSERT(failure_order != memory_order_release);
  254. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  255. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  256. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  257. }
  258. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  259. {
  260. return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
  261. }
  262. BOOST_FORCEINLINE value_type fetch_and(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  263. {
  264. return atomics::detail::integral_truncate< value_type >(operations::fetch_and(this->storage(), static_cast< storage_type >(v), order));
  265. }
  266. BOOST_FORCEINLINE value_type fetch_or(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  267. {
  268. return atomics::detail::integral_truncate< value_type >(operations::fetch_or(this->storage(), static_cast< storage_type >(v), order));
  269. }
  270. BOOST_FORCEINLINE value_type fetch_xor(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  271. {
  272. return atomics::detail::integral_truncate< value_type >(operations::fetch_xor(this->storage(), static_cast< storage_type >(v), order));
  273. }
  274. // Boost.Atomic extensions
  275. BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  276. {
  277. return atomics::detail::integral_truncate< value_type >(extra_operations::fetch_negate(this->storage(), order));
  278. }
  279. BOOST_FORCEINLINE value_type fetch_complement(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  280. {
  281. return atomics::detail::integral_truncate< value_type >(extra_operations::fetch_complement(this->storage(), order));
  282. }
  283. BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  284. {
  285. return atomics::detail::integral_truncate< value_type >(extra_operations::add(this->storage(), static_cast< storage_type >(v), order));
  286. }
  287. BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  288. {
  289. return atomics::detail::integral_truncate< value_type >(extra_operations::sub(this->storage(), static_cast< storage_type >(v), order));
  290. }
  291. BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  292. {
  293. return atomics::detail::integral_truncate< value_type >(extra_operations::negate(this->storage(), order));
  294. }
  295. BOOST_FORCEINLINE value_type bitwise_and(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  296. {
  297. return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_and(this->storage(), static_cast< storage_type >(v), order));
  298. }
  299. BOOST_FORCEINLINE value_type bitwise_or(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  300. {
  301. return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_or(this->storage(), static_cast< storage_type >(v), order));
  302. }
  303. BOOST_FORCEINLINE value_type bitwise_xor(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  304. {
  305. return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_xor(this->storage(), static_cast< storage_type >(v), order));
  306. }
  307. BOOST_FORCEINLINE value_type bitwise_complement(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  308. {
  309. return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_complement(this->storage(), order));
  310. }
  311. BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  312. {
  313. extra_operations::opaque_add(this->storage(), static_cast< storage_type >(v), order);
  314. }
  315. BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  316. {
  317. extra_operations::opaque_sub(this->storage(), static_cast< storage_type >(v), order);
  318. }
  319. BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  320. {
  321. extra_operations::opaque_negate(this->storage(), order);
  322. }
  323. BOOST_FORCEINLINE void opaque_and(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  324. {
  325. extra_operations::opaque_and(this->storage(), static_cast< storage_type >(v), order);
  326. }
  327. BOOST_FORCEINLINE void opaque_or(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  328. {
  329. extra_operations::opaque_or(this->storage(), static_cast< storage_type >(v), order);
  330. }
  331. BOOST_FORCEINLINE void opaque_xor(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  332. {
  333. extra_operations::opaque_xor(this->storage(), static_cast< storage_type >(v), order);
  334. }
  335. BOOST_FORCEINLINE void opaque_complement(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  336. {
  337. extra_operations::opaque_complement(this->storage(), order);
  338. }
  339. BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  340. {
  341. return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v), order);
  342. }
  343. BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  344. {
  345. return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v), order);
  346. }
  347. BOOST_FORCEINLINE bool negate_and_test(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  348. {
  349. return extra_operations::negate_and_test(this->storage(), order);
  350. }
  351. BOOST_FORCEINLINE bool and_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  352. {
  353. return extra_operations::and_and_test(this->storage(), static_cast< storage_type >(v), order);
  354. }
  355. BOOST_FORCEINLINE bool or_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  356. {
  357. return extra_operations::or_and_test(this->storage(), static_cast< storage_type >(v), order);
  358. }
  359. BOOST_FORCEINLINE bool xor_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  360. {
  361. return extra_operations::xor_and_test(this->storage(), static_cast< storage_type >(v), order);
  362. }
  363. BOOST_FORCEINLINE bool complement_and_test(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  364. {
  365. return extra_operations::complement_and_test(this->storage(), order);
  366. }
  367. BOOST_FORCEINLINE bool bit_test_and_set(unsigned int bit_number, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  368. {
  369. BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
  370. return extra_operations::bit_test_and_set(this->storage(), bit_number, order);
  371. }
  372. BOOST_FORCEINLINE bool bit_test_and_reset(unsigned int bit_number, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  373. {
  374. BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
  375. return extra_operations::bit_test_and_reset(this->storage(), bit_number, order);
  376. }
  377. BOOST_FORCEINLINE bool bit_test_and_complement(unsigned int bit_number, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  378. {
  379. BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
  380. return extra_operations::bit_test_and_complement(this->storage(), bit_number, order);
  381. }
  382. // Operators
  383. BOOST_FORCEINLINE value_type operator++(int) BOOST_NOEXCEPT
  384. {
  385. return fetch_add(1);
  386. }
  387. BOOST_FORCEINLINE value_type operator++() BOOST_NOEXCEPT
  388. {
  389. return add(1);
  390. }
  391. BOOST_FORCEINLINE value_type operator--(int) BOOST_NOEXCEPT
  392. {
  393. return fetch_sub(1);
  394. }
  395. BOOST_FORCEINLINE value_type operator--() BOOST_NOEXCEPT
  396. {
  397. return sub(1);
  398. }
  399. BOOST_FORCEINLINE value_type operator+=(difference_type v) BOOST_NOEXCEPT
  400. {
  401. return add(v);
  402. }
  403. BOOST_FORCEINLINE value_type operator-=(difference_type v) BOOST_NOEXCEPT
  404. {
  405. return sub(v);
  406. }
  407. BOOST_FORCEINLINE value_type operator&=(value_type v) BOOST_NOEXCEPT
  408. {
  409. return bitwise_and(v);
  410. }
  411. BOOST_FORCEINLINE value_type operator|=(value_type v) BOOST_NOEXCEPT
  412. {
  413. return bitwise_or(v);
  414. }
  415. BOOST_FORCEINLINE value_type operator^=(value_type v) BOOST_NOEXCEPT
  416. {
  417. return bitwise_xor(v);
  418. }
  419. BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
  420. private:
  421. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  422. {
  423. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  424. return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
  425. #else
  426. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  427. #endif
  428. }
  429. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  430. {
  431. storage_type old_value = static_cast< storage_type >(expected);
  432. const bool res = operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
  433. expected = atomics::detail::integral_truncate< value_type >(old_value);
  434. return res;
  435. }
  436. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  437. {
  438. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  439. return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
  440. #else
  441. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  442. #endif
  443. }
  444. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  445. {
  446. storage_type old_value = static_cast< storage_type >(expected);
  447. const bool res = operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
  448. expected = atomics::detail::integral_truncate< value_type >(old_value);
  449. return res;
  450. }
  451. };
  452. //! Implementation for bool
  453. template< >
  454. class base_atomic_ref< bool, int > :
  455. public base_atomic_ref_common< bool, false >
  456. {
  457. private:
  458. typedef base_atomic_ref_common< bool, false > base_type;
  459. public:
  460. typedef bool value_type;
  461. protected:
  462. typedef base_type::operations operations;
  463. typedef atomics::detail::extra_operations< operations, operations::storage_size, operations::is_signed > extra_operations;
  464. typedef base_type::storage_type storage_type;
  465. typedef value_type value_arg_type;
  466. private:
  467. typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
  468. public:
  469. BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {})
  470. BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
  471. {
  472. }
  473. // Standard methods
  474. BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  475. {
  476. BOOST_ASSERT(order != memory_order_consume);
  477. BOOST_ASSERT(order != memory_order_acquire);
  478. BOOST_ASSERT(order != memory_order_acq_rel);
  479. operations::store(this->storage(), static_cast< storage_type >(v), order);
  480. }
  481. BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  482. {
  483. BOOST_ASSERT(order != memory_order_release);
  484. BOOST_ASSERT(order != memory_order_acq_rel);
  485. return !!operations::load(this->storage(), order);
  486. }
  487. BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  488. {
  489. return !!operations::exchange(this->storage(), static_cast< storage_type >(v), order);
  490. }
  491. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  492. {
  493. BOOST_ASSERT(failure_order != memory_order_release);
  494. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  495. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  496. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  497. }
  498. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  499. {
  500. return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
  501. }
  502. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  503. {
  504. BOOST_ASSERT(failure_order != memory_order_release);
  505. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  506. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  507. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  508. }
  509. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  510. {
  511. return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
  512. }
  513. BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
  514. private:
  515. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  516. {
  517. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  518. return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
  519. #else
  520. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  521. #endif
  522. }
  523. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  524. {
  525. storage_type old_value = static_cast< storage_type >(expected);
  526. const bool res = operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
  527. expected = !!old_value;
  528. return res;
  529. }
  530. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  531. {
  532. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  533. return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
  534. #else
  535. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  536. #endif
  537. }
  538. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  539. {
  540. storage_type old_value = static_cast< storage_type >(expected);
  541. const bool res = operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
  542. expected = !!old_value;
  543. return res;
  544. }
  545. };
  546. #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
  547. //! Implementation for floating point types
  548. template< typename T >
  549. class base_atomic_ref< T, float > :
  550. public base_atomic_ref_common< T, false >
  551. {
  552. private:
  553. typedef base_atomic_ref_common< T, false > base_type;
  554. public:
  555. typedef typename base_type::value_type value_type;
  556. typedef typename base_type::value_type difference_type;
  557. protected:
  558. typedef typename base_type::operations operations;
  559. typedef atomics::detail::extra_operations< operations, operations::storage_size, operations::is_signed > extra_operations;
  560. typedef atomics::detail::fp_operations< extra_operations, value_type, operations::storage_size > fp_operations;
  561. typedef atomics::detail::extra_fp_operations< fp_operations, value_type, operations::storage_size > extra_fp_operations;
  562. typedef typename base_type::storage_type storage_type;
  563. typedef value_type value_arg_type;
  564. private:
  565. typedef atomics::detail::integral_constant< bool, atomics::detail::value_sizeof< value_type >::value != sizeof(storage_type) > has_padding_bits;
  566. typedef atomics::detail::integral_constant< bool, has_padding_bits::value || atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
  567. public:
  568. BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {})
  569. BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
  570. {
  571. this->clear_padding_bits(has_padding_bits());
  572. }
  573. BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  574. {
  575. BOOST_ASSERT(order != memory_order_consume);
  576. BOOST_ASSERT(order != memory_order_acquire);
  577. BOOST_ASSERT(order != memory_order_acq_rel);
  578. operations::store(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order);
  579. }
  580. BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  581. {
  582. BOOST_ASSERT(order != memory_order_release);
  583. BOOST_ASSERT(order != memory_order_acq_rel);
  584. return atomics::detail::bitwise_fp_cast< value_type >(operations::load(this->storage(), order));
  585. }
  586. BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  587. {
  588. return fp_operations::fetch_add(this->storage(), v, order);
  589. }
  590. BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  591. {
  592. return fp_operations::fetch_sub(this->storage(), v, order);
  593. }
  594. BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  595. {
  596. return atomics::detail::bitwise_fp_cast< value_type >(operations::exchange(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order));
  597. }
  598. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  599. {
  600. BOOST_ASSERT(failure_order != memory_order_release);
  601. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  602. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  603. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  604. }
  605. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  606. {
  607. return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
  608. }
  609. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  610. {
  611. BOOST_ASSERT(failure_order != memory_order_release);
  612. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  613. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  614. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  615. }
  616. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  617. {
  618. return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
  619. }
  620. // Boost.Atomic extensions
  621. BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  622. {
  623. return extra_fp_operations::fetch_negate(this->storage(), order);
  624. }
  625. BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  626. {
  627. return extra_fp_operations::add(this->storage(), v, order);
  628. }
  629. BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  630. {
  631. return extra_fp_operations::sub(this->storage(), v, order);
  632. }
  633. BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  634. {
  635. return extra_fp_operations::negate(this->storage(), order);
  636. }
  637. BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  638. {
  639. extra_fp_operations::opaque_add(this->storage(), v, order);
  640. }
  641. BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  642. {
  643. extra_fp_operations::opaque_sub(this->storage(), v, order);
  644. }
  645. BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  646. {
  647. extra_fp_operations::opaque_negate(this->storage(), order);
  648. }
  649. // Operators
  650. BOOST_FORCEINLINE value_type operator+=(difference_type v) BOOST_NOEXCEPT
  651. {
  652. return add(v);
  653. }
  654. BOOST_FORCEINLINE value_type operator-=(difference_type v) BOOST_NOEXCEPT
  655. {
  656. return sub(v);
  657. }
  658. BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
  659. private:
  660. BOOST_FORCEINLINE void clear_padding_bits(atomics::detail::false_type) const BOOST_NOEXCEPT
  661. {
  662. }
  663. BOOST_FORCEINLINE void clear_padding_bits(atomics::detail::true_type) const BOOST_NOEXCEPT
  664. {
  665. storage_type old_value = operations::load(this->storage(), boost::memory_order_relaxed);
  666. while (true)
  667. {
  668. storage_type new_value = old_value;
  669. atomics::detail::clear_tail_padding_bits< atomics::detail::value_sizeof< value_type >::value >(new_value);
  670. bool res = operations::compare_exchange_weak(this->storage(), old_value, new_value, boost::memory_order_relaxed, boost::memory_order_relaxed);
  671. if (BOOST_LIKELY(res))
  672. break;
  673. }
  674. }
  675. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  676. {
  677. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  678. return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
  679. #else
  680. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  681. #endif
  682. }
  683. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  684. {
  685. storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected);
  686. const bool res = operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
  687. expected = atomics::detail::bitwise_fp_cast< value_type >(old_value);
  688. return res;
  689. }
  690. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  691. {
  692. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  693. return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
  694. #else
  695. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  696. #endif
  697. }
  698. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  699. {
  700. storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected);
  701. const bool res = operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
  702. expected = atomics::detail::bitwise_fp_cast< value_type >(old_value);
  703. return res;
  704. }
  705. };
  706. #endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
  707. //! Implementation for pointers to object types
  708. template< typename T >
  709. class base_atomic_ref< T*, void* > :
  710. public base_atomic_ref_common< T*, false >
  711. {
  712. private:
  713. typedef base_atomic_ref_common< T*, false > base_type;
  714. public:
  715. typedef typename base_type::value_type value_type;
  716. typedef std::ptrdiff_t difference_type;
  717. protected:
  718. typedef typename base_type::operations operations;
  719. typedef atomics::detail::extra_operations< operations, operations::storage_size, operations::is_signed > extra_operations;
  720. typedef typename base_type::storage_type storage_type;
  721. typedef value_type value_arg_type;
  722. private:
  723. typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
  724. // uintptr_storage_type is the minimal storage type that is enough to store pointers. The actual storage_type theoretically may be larger,
  725. // if the target architecture only supports atomic ops on larger data. Typically, though, they are the same type.
  726. typedef atomics::detail::uintptr_t uintptr_storage_type;
  727. public:
  728. BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {})
  729. BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
  730. {
  731. }
  732. // Standard methods
  733. BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  734. {
  735. BOOST_ASSERT(order != memory_order_consume);
  736. BOOST_ASSERT(order != memory_order_acquire);
  737. BOOST_ASSERT(order != memory_order_acq_rel);
  738. operations::store(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(v), order);
  739. }
  740. BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
  741. {
  742. BOOST_ASSERT(order != memory_order_release);
  743. BOOST_ASSERT(order != memory_order_acq_rel);
  744. return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::load(this->storage(), order)));
  745. }
  746. BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  747. {
  748. return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::fetch_add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order)));
  749. }
  750. BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  751. {
  752. return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::fetch_sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order)));
  753. }
  754. BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  755. {
  756. return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::exchange(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(v), order)));
  757. }
  758. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  759. {
  760. BOOST_ASSERT(failure_order != memory_order_release);
  761. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  762. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  763. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  764. }
  765. BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  766. {
  767. return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
  768. }
  769. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
  770. {
  771. BOOST_ASSERT(failure_order != memory_order_release);
  772. BOOST_ASSERT(failure_order != memory_order_acq_rel);
  773. BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
  774. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
  775. }
  776. BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  777. {
  778. return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
  779. }
  780. // Boost.Atomic extensions
  781. BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  782. {
  783. return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(extra_operations::add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order)));
  784. }
  785. BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  786. {
  787. return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(extra_operations::sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order)));
  788. }
  789. BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  790. {
  791. extra_operations::opaque_add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
  792. }
  793. BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  794. {
  795. extra_operations::opaque_sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
  796. }
  797. BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  798. {
  799. return extra_operations::add_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
  800. }
  801. BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
  802. {
  803. return extra_operations::sub_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
  804. }
  805. // Operators
  806. BOOST_FORCEINLINE value_type operator++(int) BOOST_NOEXCEPT
  807. {
  808. return fetch_add(1);
  809. }
  810. BOOST_FORCEINLINE value_type operator++() BOOST_NOEXCEPT
  811. {
  812. return add(1);
  813. }
  814. BOOST_FORCEINLINE value_type operator--(int) BOOST_NOEXCEPT
  815. {
  816. return fetch_sub(1);
  817. }
  818. BOOST_FORCEINLINE value_type operator--() BOOST_NOEXCEPT
  819. {
  820. return sub(1);
  821. }
  822. BOOST_FORCEINLINE value_type operator+=(difference_type v) BOOST_NOEXCEPT
  823. {
  824. return add(v);
  825. }
  826. BOOST_FORCEINLINE value_type operator-=(difference_type v) BOOST_NOEXCEPT
  827. {
  828. return sub(v);
  829. }
  830. BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
  831. private:
  832. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  833. {
  834. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  835. return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
  836. #else
  837. return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  838. #endif
  839. }
  840. BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  841. {
  842. storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected);
  843. const bool res = operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
  844. expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value));
  845. return res;
  846. }
  847. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT
  848. {
  849. #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
  850. return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
  851. #else
  852. return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
  853. #endif
  854. }
  855. BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT
  856. {
  857. storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected);
  858. const bool res = operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
  859. expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value));
  860. return res;
  861. }
  862. };
  863. } // namespace detail
  864. template< typename T >
  865. class atomic_ref :
  866. public atomics::detail::base_atomic_ref< T, typename atomics::detail::classify< T >::type >
  867. {
  868. private:
  869. typedef atomics::detail::base_atomic_ref< T, typename atomics::detail::classify< T >::type > base_type;
  870. typedef typename base_type::value_arg_type value_arg_type;
  871. public:
  872. typedef typename base_type::value_type value_type;
  873. BOOST_STATIC_ASSERT_MSG(sizeof(value_type) > 0u, "boost::atomic_ref<T> requires T to be a complete type");
  874. #if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE)
  875. BOOST_STATIC_ASSERT_MSG(atomics::detail::is_trivially_copyable< value_type >::value, "boost::atomic_ref<T> requires T to be a trivially copyable type");
  876. #endif
  877. private:
  878. typedef typename base_type::storage_type storage_type;
  879. public:
  880. BOOST_DEFAULTED_FUNCTION(atomic_ref(atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {})
  881. BOOST_FORCEINLINE explicit atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
  882. {
  883. // Check that referenced object alignment satisfies required alignment
  884. BOOST_ASSERT((((atomics::detail::uintptr_t)this->m_value) & (base_type::required_alignment - 1u)) == 0u);
  885. }
  886. BOOST_FORCEINLINE value_type operator= (value_arg_type v) BOOST_NOEXCEPT
  887. {
  888. this->store(v);
  889. return v;
  890. }
  891. BOOST_FORCEINLINE operator value_type() const BOOST_NOEXCEPT
  892. {
  893. return this->load();
  894. }
  895. BOOST_FORCEINLINE bool is_lock_free() const BOOST_NOEXCEPT
  896. {
  897. // C++20 specifies that is_lock_free returns true if operations on *all* objects of the atomic_ref<T> type are lock-free.
  898. // This does not allow to return true or false depending on the referenced object runtime alignment. Currently, Boost.Atomic
  899. // follows this specification, although we may support runtime alignment checking in the future.
  900. return base_type::is_always_lock_free;
  901. }
  902. BOOST_FORCEINLINE value_type& value() const BOOST_NOEXCEPT { return *this->m_value; }
  903. BOOST_DELETED_FUNCTION(atomic_ref& operator= (atomic_ref const&))
  904. };
  905. } // namespace atomics
  906. } // namespace boost
  907. #if defined(BOOST_MSVC)
  908. #pragma warning(pop)
  909. #endif
  910. #endif // BOOST_ATOMIC_DETAIL_ATOMIC_REF_TEMPLATE_HPP_INCLUDED_