wait_ops_windows.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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-2025 Andrey Semashev
  7. */
  8. /*!
  9. * \file atomic/detail/wait_ops_windows.hpp
  10. *
  11. * This header contains implementation of the waiting/notifying atomic operations on Windows.
  12. */
  13. #ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_WINDOWS_HPP_INCLUDED_
  14. #define BOOST_ATOMIC_DETAIL_WAIT_OPS_WINDOWS_HPP_INCLUDED_
  15. #include <cstddef>
  16. #include <cstdint>
  17. #include <chrono>
  18. #include <boost/memory_order.hpp>
  19. #include <boost/atomic/detail/config.hpp>
  20. #include <boost/atomic/detail/chrono.hpp>
  21. #include <boost/atomic/detail/wait_operations_fwd.hpp>
  22. #include <boost/atomic/detail/wait_capabilities.hpp>
  23. #include <boost/winapi/wait_constants.hpp>
  24. #include <boost/winapi/wait_on_address.hpp>
  25. #if (defined(BOOST_ATOMIC_FORCE_AUTO_LINK) || (!defined(BOOST_ALL_NO_LIB) && !defined(BOOST_ATOMIC_NO_LIB)))
  26. #define BOOST_LIB_NAME "synchronization"
  27. #if defined(BOOST_AUTO_LINK_NOMANGLE)
  28. #include <boost/config/auto_link.hpp>
  29. #else // defined(BOOST_AUTO_LINK_NOMANGLE)
  30. #define BOOST_AUTO_LINK_NOMANGLE
  31. #include <boost/config/auto_link.hpp>
  32. #undef BOOST_AUTO_LINK_NOMANGLE
  33. #endif // defined(BOOST_AUTO_LINK_NOMANGLE)
  34. #endif // (defined(BOOST_ATOMIC_FORCE_AUTO_LINK) || (!defined(BOOST_ALL_NO_LIB) && !defined(BOOST_ATOMIC_NO_LIB)))
  35. #include <boost/atomic/detail/header.hpp>
  36. #ifdef BOOST_HAS_PRAGMA_ONCE
  37. #pragma once
  38. #endif
  39. namespace boost {
  40. namespace atomics {
  41. namespace detail {
  42. template< typename Base, std::size_t Size >
  43. struct wait_operations_windows :
  44. public Base
  45. {
  46. using base_type = Base;
  47. using storage_type = typename base_type::storage_type;
  48. static constexpr bool always_has_native_wait_notify = true;
  49. static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) noexcept
  50. {
  51. return true;
  52. }
  53. static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) noexcept
  54. {
  55. storage_type new_val = base_type::load(storage, order);
  56. while (new_val == old_val)
  57. {
  58. boost::winapi::WaitOnAddress(const_cast< storage_type* >(&storage), &old_val, Size, boost::winapi::infinite);
  59. new_val = base_type::load(storage, order);
  60. }
  61. return new_val;
  62. }
  63. private:
  64. template< typename Clock >
  65. static BOOST_FORCEINLINE storage_type wait_until_impl
  66. (
  67. storage_type const volatile& storage,
  68. storage_type old_val,
  69. typename Clock::time_point timeout,
  70. typename Clock::time_point now,
  71. memory_order order,
  72. bool& timed_out
  73. ) noexcept(noexcept(Clock::now()))
  74. {
  75. storage_type new_val = base_type::load(storage, order);
  76. while (new_val == old_val)
  77. {
  78. const std::int64_t msec = atomics::detail::chrono::ceil< std::chrono::milliseconds >(timeout - now).count();
  79. if (msec <= 0)
  80. {
  81. timed_out = true;
  82. break;
  83. }
  84. boost::winapi::WaitOnAddress
  85. (
  86. const_cast< storage_type* >(&storage),
  87. &old_val,
  88. Size,
  89. msec <= static_cast< std::int64_t >(boost::winapi::max_non_infinite_wait) ?
  90. static_cast< boost::winapi::DWORD_ >(msec) : boost::winapi::max_non_infinite_wait
  91. );
  92. now = Clock::now();
  93. new_val = base_type::load(storage, order);
  94. }
  95. return new_val;
  96. }
  97. public:
  98. template< typename Clock, typename Duration >
  99. static BOOST_FORCEINLINE storage_type wait_until
  100. (
  101. storage_type const volatile& storage,
  102. storage_type old_val,
  103. std::chrono::time_point< Clock, Duration > timeout,
  104. memory_order order,
  105. bool& timed_out
  106. ) noexcept(noexcept(Clock::now()))
  107. {
  108. return wait_until_impl< Clock >(storage, old_val, timeout, Clock::now(), order, timed_out);
  109. }
  110. template< typename Rep, typename Period >
  111. static BOOST_FORCEINLINE storage_type wait_for
  112. (
  113. storage_type const volatile& storage,
  114. storage_type old_val,
  115. std::chrono::duration< Rep, Period > timeout,
  116. memory_order order,
  117. bool& timed_out
  118. ) noexcept
  119. {
  120. const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
  121. return wait_until_impl< std::chrono::steady_clock >(storage, old_val, now + timeout, now, order, timed_out);
  122. }
  123. static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) noexcept
  124. {
  125. boost::winapi::WakeByAddressSingle(const_cast< storage_type* >(&storage));
  126. }
  127. static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) noexcept
  128. {
  129. boost::winapi::WakeByAddressAll(const_cast< storage_type* >(&storage));
  130. }
  131. };
  132. template< typename Base >
  133. struct wait_operations< Base, 1u, true, false > :
  134. public wait_operations_windows< Base, 1u >
  135. {
  136. };
  137. template< typename Base >
  138. struct wait_operations< Base, 2u, true, false > :
  139. public wait_operations_windows< Base, 2u >
  140. {
  141. };
  142. template< typename Base >
  143. struct wait_operations< Base, 4u, true, false > :
  144. public wait_operations_windows< Base, 4u >
  145. {
  146. };
  147. template< typename Base >
  148. struct wait_operations< Base, 8u, true, false > :
  149. public wait_operations_windows< Base, 8u >
  150. {
  151. };
  152. } // namespace detail
  153. } // namespace atomics
  154. } // namespace boost
  155. #include <boost/atomic/detail/footer.hpp>
  156. #endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_WINDOWS_HPP_INCLUDED_