Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
7.3KB

  1. //
  2. // detail/deadline_timer_service.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
  11. #define ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include <cstddef>
  17. #include "asio/error.hpp"
  18. #include "asio/io_context.hpp"
  19. #include "asio/detail/bind_handler.hpp"
  20. #include "asio/detail/fenced_block.hpp"
  21. #include "asio/detail/memory.hpp"
  22. #include "asio/detail/noncopyable.hpp"
  23. #include "asio/detail/socket_ops.hpp"
  24. #include "asio/detail/socket_types.hpp"
  25. #include "asio/detail/timer_queue.hpp"
  26. #include "asio/detail/timer_scheduler.hpp"
  27. #include "asio/detail/wait_handler.hpp"
  28. #include "asio/detail/wait_op.hpp"
  29. #if defined(ASIO_WINDOWS_RUNTIME)
  30. # include <chrono>
  31. # include <thread>
  32. #endif // defined(ASIO_WINDOWS_RUNTIME)
  33. #include "asio/detail/push_options.hpp"
  34. namespace asio {
  35. namespace detail {
  36. template <typename Time_Traits>
  37. class deadline_timer_service
  38. {
  39. public:
  40. // The time type.
  41. typedef typename Time_Traits::time_type time_type;
  42. // The duration type.
  43. typedef typename Time_Traits::duration_type duration_type;
  44. // The implementation type of the timer. This type is dependent on the
  45. // underlying implementation of the timer service.
  46. struct implementation_type
  47. : private asio::detail::noncopyable
  48. {
  49. time_type expiry;
  50. bool might_have_pending_waits;
  51. typename timer_queue<Time_Traits>::per_timer_data timer_data;
  52. };
  53. // Constructor.
  54. deadline_timer_service(asio::io_context& io_context)
  55. : scheduler_(asio::use_service<timer_scheduler>(io_context))
  56. {
  57. scheduler_.init_task();
  58. scheduler_.add_timer_queue(timer_queue_);
  59. }
  60. // Destructor.
  61. ~deadline_timer_service()
  62. {
  63. scheduler_.remove_timer_queue(timer_queue_);
  64. }
  65. // Destroy all user-defined handler objects owned by the service.
  66. void shutdown()
  67. {
  68. }
  69. // Construct a new timer implementation.
  70. void construct(implementation_type& impl)
  71. {
  72. impl.expiry = time_type();
  73. impl.might_have_pending_waits = false;
  74. }
  75. // Destroy a timer implementation.
  76. void destroy(implementation_type& impl)
  77. {
  78. asio::error_code ec;
  79. cancel(impl, ec);
  80. }
  81. // Move-construct a new serial port implementation.
  82. void move_construct(implementation_type& impl,
  83. implementation_type& other_impl)
  84. {
  85. scheduler_.move_timer(timer_queue_, impl.timer_data, other_impl.timer_data);
  86. impl.expiry = other_impl.expiry;
  87. other_impl.expiry = time_type();
  88. impl.might_have_pending_waits = other_impl.might_have_pending_waits;
  89. other_impl.might_have_pending_waits = false;
  90. }
  91. // Move-assign from another serial port implementation.
  92. void move_assign(implementation_type& impl,
  93. deadline_timer_service& other_service,
  94. implementation_type& other_impl)
  95. {
  96. if (this != &other_service)
  97. if (impl.might_have_pending_waits)
  98. scheduler_.cancel_timer(timer_queue_, impl.timer_data);
  99. other_service.scheduler_.move_timer(other_service.timer_queue_,
  100. impl.timer_data, other_impl.timer_data);
  101. impl.expiry = other_impl.expiry;
  102. other_impl.expiry = time_type();
  103. impl.might_have_pending_waits = other_impl.might_have_pending_waits;
  104. other_impl.might_have_pending_waits = false;
  105. }
  106. // Cancel any asynchronous wait operations associated with the timer.
  107. std::size_t cancel(implementation_type& impl, asio::error_code& ec)
  108. {
  109. if (!impl.might_have_pending_waits)
  110. {
  111. ec = asio::error_code();
  112. return 0;
  113. }
  114. ASIO_HANDLER_OPERATION((scheduler_.context(),
  115. "deadline_timer", &impl, 0, "cancel"));
  116. std::size_t count = scheduler_.cancel_timer(timer_queue_, impl.timer_data);
  117. impl.might_have_pending_waits = false;
  118. ec = asio::error_code();
  119. return count;
  120. }
  121. // Cancels one asynchronous wait operation associated with the timer.
  122. std::size_t cancel_one(implementation_type& impl,
  123. asio::error_code& ec)
  124. {
  125. if (!impl.might_have_pending_waits)
  126. {
  127. ec = asio::error_code();
  128. return 0;
  129. }
  130. ASIO_HANDLER_OPERATION((scheduler_.context(),
  131. "deadline_timer", &impl, 0, "cancel_one"));
  132. std::size_t count = scheduler_.cancel_timer(
  133. timer_queue_, impl.timer_data, 1);
  134. if (count == 0)
  135. impl.might_have_pending_waits = false;
  136. ec = asio::error_code();
  137. return count;
  138. }
  139. // Get the expiry time for the timer as an absolute time.
  140. time_type expiry(const implementation_type& impl) const
  141. {
  142. return impl.expiry;
  143. }
  144. // Set the expiry time for the timer as an absolute time.
  145. std::size_t expires_at(implementation_type& impl,
  146. const time_type& expiry_time, asio::error_code& ec)
  147. {
  148. std::size_t count = cancel(impl, ec);
  149. impl.expiry = expiry_time;
  150. ec = asio::error_code();
  151. return count;
  152. }
  153. // Set the expiry time for the timer relative to now.
  154. std::size_t expires_after(implementation_type& impl,
  155. const duration_type& expiry_time, asio::error_code& ec)
  156. {
  157. return expires_at(impl,
  158. Time_Traits::add(Time_Traits::now(), expiry_time), ec);
  159. }
  160. // Perform a blocking wait on the timer.
  161. void wait(implementation_type& impl, asio::error_code& ec)
  162. {
  163. time_type now = Time_Traits::now();
  164. ec = asio::error_code();
  165. while (Time_Traits::less_than(now, impl.expiry) && !ec)
  166. {
  167. this->do_wait(Time_Traits::to_posix_duration(
  168. Time_Traits::subtract(impl.expiry, now)), ec);
  169. now = Time_Traits::now();
  170. }
  171. }
  172. // Start an asynchronous wait on the timer.
  173. template <typename Handler>
  174. void async_wait(implementation_type& impl, Handler& handler)
  175. {
  176. // Allocate and construct an operation to wrap the handler.
  177. typedef wait_handler<Handler> op;
  178. typename op::ptr p = { asio::detail::addressof(handler),
  179. op::ptr::allocate(handler), 0 };
  180. p.p = new (p.v) op(handler);
  181. impl.might_have_pending_waits = true;
  182. ASIO_HANDLER_CREATION((scheduler_.context(),
  183. *p.p, "deadline_timer", &impl, 0, "async_wait"));
  184. scheduler_.schedule_timer(timer_queue_, impl.expiry, impl.timer_data, p.p);
  185. p.v = p.p = 0;
  186. }
  187. private:
  188. // Helper function to wait given a duration type. The duration type should
  189. // either be of type boost::posix_time::time_duration, or implement the
  190. // required subset of its interface.
  191. template <typename Duration>
  192. void do_wait(const Duration& timeout, asio::error_code& ec)
  193. {
  194. #if defined(ASIO_WINDOWS_RUNTIME)
  195. std::this_thread::sleep_for(
  196. std::chrono::seconds(timeout.total_seconds())
  197. + std::chrono::microseconds(timeout.total_microseconds()));
  198. ec = asio::error_code();
  199. #else // defined(ASIO_WINDOWS_RUNTIME)
  200. ::timeval tv;
  201. tv.tv_sec = timeout.total_seconds();
  202. tv.tv_usec = timeout.total_microseconds() % 1000000;
  203. socket_ops::select(0, 0, 0, 0, &tv, ec);
  204. #endif // defined(ASIO_WINDOWS_RUNTIME)
  205. }
  206. // The queue of timers.
  207. timer_queue<Time_Traits> timer_queue_;
  208. // The object that schedules and executes timers. Usually a reactor.
  209. timer_scheduler& scheduler_;
  210. };
  211. } // namespace detail
  212. } // namespace asio
  213. #include "asio/detail/pop_options.hpp"
  214. #endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP