atomic_ref_impl.hpp 53 KB

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