atomic_ref_impl.hpp 58 KB

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