ops_emulated.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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) 2014 Andrey Semashev
  7. */
  8. /*!
  9. * \file atomic/detail/ops_emulated.hpp
  10. *
  11. * This header contains lockpool-based implementation of the \c operations template.
  12. */
  13. #ifndef BOOST_ATOMIC_DETAIL_OPS_EMULATED_HPP_INCLUDED_
  14. #define BOOST_ATOMIC_DETAIL_OPS_EMULATED_HPP_INCLUDED_
  15. #include <cstddef>
  16. #include <boost/memory_order.hpp>
  17. #include <boost/atomic/detail/config.hpp>
  18. #include <boost/atomic/detail/storage_type.hpp>
  19. #include <boost/atomic/detail/operations_fwd.hpp>
  20. #include <boost/atomic/detail/lockpool.hpp>
  21. #include <boost/atomic/capabilities.hpp>
  22. #ifdef BOOST_HAS_PRAGMA_ONCE
  23. #pragma once
  24. #endif
  25. namespace boost {
  26. namespace atomics {
  27. namespace detail {
  28. template< std::size_t Size, bool Signed >
  29. struct emulated_operations
  30. {
  31. typedef typename make_storage_type< Size >::type storage_type;
  32. typedef typename make_storage_type< Size >::aligned aligned_storage_type;
  33. static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
  34. static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
  35. static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
  36. static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = false;
  37. static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
  38. {
  39. lockpool::scoped_lock lock(&storage);
  40. const_cast< storage_type& >(storage) = v;
  41. }
  42. static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
  43. {
  44. lockpool::scoped_lock lock(&storage);
  45. return const_cast< storage_type const& >(storage);
  46. }
  47. static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
  48. {
  49. storage_type& s = const_cast< storage_type& >(storage);
  50. lockpool::scoped_lock lock(&storage);
  51. storage_type old_val = s;
  52. s += v;
  53. return old_val;
  54. }
  55. static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
  56. {
  57. storage_type& s = const_cast< storage_type& >(storage);
  58. lockpool::scoped_lock lock(&storage);
  59. storage_type old_val = s;
  60. s -= v;
  61. return old_val;
  62. }
  63. static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
  64. {
  65. storage_type& s = const_cast< storage_type& >(storage);
  66. lockpool::scoped_lock lock(&storage);
  67. storage_type old_val = s;
  68. s = v;
  69. return old_val;
  70. }
  71. static BOOST_FORCEINLINE bool compare_exchange_strong(
  72. storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
  73. {
  74. storage_type& s = const_cast< storage_type& >(storage);
  75. lockpool::scoped_lock lock(&storage);
  76. storage_type old_val = s;
  77. const bool res = old_val == expected;
  78. if (res)
  79. s = desired;
  80. expected = old_val;
  81. return res;
  82. }
  83. static BOOST_FORCEINLINE bool compare_exchange_weak(
  84. storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
  85. {
  86. // Note: This function is the exact copy of compare_exchange_strong. The reason we're not just forwarding the call
  87. // is that MSVC-12 ICEs in this case.
  88. storage_type& s = const_cast< storage_type& >(storage);
  89. lockpool::scoped_lock lock(&storage);
  90. storage_type old_val = s;
  91. const bool res = old_val == expected;
  92. if (res)
  93. s = desired;
  94. expected = old_val;
  95. return res;
  96. }
  97. static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
  98. {
  99. storage_type& s = const_cast< storage_type& >(storage);
  100. lockpool::scoped_lock lock(&storage);
  101. storage_type old_val = s;
  102. s &= v;
  103. return old_val;
  104. }
  105. static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
  106. {
  107. storage_type& s = const_cast< storage_type& >(storage);
  108. lockpool::scoped_lock lock(&storage);
  109. storage_type old_val = s;
  110. s |= v;
  111. return old_val;
  112. }
  113. static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
  114. {
  115. storage_type& s = const_cast< storage_type& >(storage);
  116. lockpool::scoped_lock lock(&storage);
  117. storage_type old_val = s;
  118. s ^= v;
  119. return old_val;
  120. }
  121. static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
  122. {
  123. return !!exchange(storage, (storage_type)1, order);
  124. }
  125. static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
  126. {
  127. store(storage, (storage_type)0, order);
  128. }
  129. };
  130. template< std::size_t Size, bool Signed >
  131. struct operations :
  132. public emulated_operations< Size, Signed >
  133. {
  134. };
  135. } // namespace detail
  136. } // namespace atomics
  137. } // namespace boost
  138. #endif // BOOST_ATOMIC_DETAIL_OPS_EMULATED_HPP_INCLUDED_