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.

354 lines
9.8KB

  1. //
  2. // impl/io_context.hpp
  3. // ~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 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_IMPL_IO_CONTEXT_HPP
  11. #define ASIO_IMPL_IO_CONTEXT_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/completion_handler.hpp"
  16. #include "asio/detail/executor_op.hpp"
  17. #include "asio/detail/fenced_block.hpp"
  18. #include "asio/detail/handler_type_requirements.hpp"
  19. #include "asio/detail/non_const_lvalue.hpp"
  20. #include "asio/detail/recycling_allocator.hpp"
  21. #include "asio/detail/service_registry.hpp"
  22. #include "asio/detail/throw_error.hpp"
  23. #include "asio/detail/type_traits.hpp"
  24. #include "asio/detail/push_options.hpp"
  25. #if !defined(GENERATING_DOCUMENTATION)
  26. namespace asio {
  27. template <typename Service>
  28. inline Service& use_service(io_context& ioc)
  29. {
  30. // Check that Service meets the necessary type requirements.
  31. (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
  32. (void)static_cast<const execution_context::id*>(&Service::id);
  33. return ioc.service_registry_->template use_service<Service>(ioc);
  34. }
  35. template <>
  36. inline detail::io_context_impl& use_service<detail::io_context_impl>(
  37. io_context& ioc)
  38. {
  39. return ioc.impl_;
  40. }
  41. } // namespace asio
  42. #endif // !defined(GENERATING_DOCUMENTATION)
  43. #include "asio/detail/pop_options.hpp"
  44. #if defined(ASIO_HAS_IOCP)
  45. # include "asio/detail/win_iocp_io_context.hpp"
  46. #else
  47. # include "asio/detail/scheduler.hpp"
  48. #endif
  49. #include "asio/detail/push_options.hpp"
  50. namespace asio {
  51. inline io_context::executor_type
  52. io_context::get_executor() ASIO_NOEXCEPT
  53. {
  54. return executor_type(*this);
  55. }
  56. #if defined(ASIO_HAS_CHRONO)
  57. template <typename Rep, typename Period>
  58. std::size_t io_context::run_for(
  59. const chrono::duration<Rep, Period>& rel_time)
  60. {
  61. return this->run_until(chrono::steady_clock::now() + rel_time);
  62. }
  63. template <typename Clock, typename Duration>
  64. std::size_t io_context::run_until(
  65. const chrono::time_point<Clock, Duration>& abs_time)
  66. {
  67. std::size_t n = 0;
  68. while (this->run_one_until(abs_time))
  69. if (n != (std::numeric_limits<std::size_t>::max)())
  70. ++n;
  71. return n;
  72. }
  73. template <typename Rep, typename Period>
  74. std::size_t io_context::run_one_for(
  75. const chrono::duration<Rep, Period>& rel_time)
  76. {
  77. return this->run_one_until(chrono::steady_clock::now() + rel_time);
  78. }
  79. template <typename Clock, typename Duration>
  80. std::size_t io_context::run_one_until(
  81. const chrono::time_point<Clock, Duration>& abs_time)
  82. {
  83. typename Clock::time_point now = Clock::now();
  84. while (now < abs_time)
  85. {
  86. typename Clock::duration rel_time = abs_time - now;
  87. if (rel_time > chrono::seconds(1))
  88. rel_time = chrono::seconds(1);
  89. asio::error_code ec;
  90. std::size_t s = impl_.wait_one(
  91. static_cast<long>(chrono::duration_cast<
  92. chrono::microseconds>(rel_time).count()), ec);
  93. asio::detail::throw_error(ec);
  94. if (s || impl_.stopped())
  95. return s;
  96. now = Clock::now();
  97. }
  98. return 0;
  99. }
  100. #endif // defined(ASIO_HAS_CHRONO)
  101. #if !defined(ASIO_NO_DEPRECATED)
  102. inline void io_context::reset()
  103. {
  104. restart();
  105. }
  106. struct io_context::initiate_dispatch
  107. {
  108. template <typename LegacyCompletionHandler>
  109. void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler,
  110. io_context* self) const
  111. {
  112. // If you get an error on the following line it means that your handler does
  113. // not meet the documented type requirements for a LegacyCompletionHandler.
  114. ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
  115. LegacyCompletionHandler, handler) type_check;
  116. detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler);
  117. if (self->impl_.can_dispatch())
  118. {
  119. detail::fenced_block b(detail::fenced_block::full);
  120. asio_handler_invoke_helpers::invoke(
  121. handler2.value, handler2.value);
  122. }
  123. else
  124. {
  125. // Allocate and construct an operation to wrap the handler.
  126. typedef detail::completion_handler<
  127. typename decay<LegacyCompletionHandler>::type> op;
  128. typename op::ptr p = { detail::addressof(handler2.value),
  129. op::ptr::allocate(handler2.value), 0 };
  130. p.p = new (p.v) op(handler2.value);
  131. ASIO_HANDLER_CREATION((*self, *p.p,
  132. "io_context", self, 0, "dispatch"));
  133. self->impl_.do_dispatch(p.p);
  134. p.v = p.p = 0;
  135. }
  136. }
  137. };
  138. template <typename LegacyCompletionHandler>
  139. ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
  140. io_context::dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
  141. {
  142. return async_initiate<LegacyCompletionHandler, void ()>(
  143. initiate_dispatch(), handler, this);
  144. }
  145. struct io_context::initiate_post
  146. {
  147. template <typename LegacyCompletionHandler>
  148. void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler,
  149. io_context* self) const
  150. {
  151. // If you get an error on the following line it means that your handler does
  152. // not meet the documented type requirements for a LegacyCompletionHandler.
  153. ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
  154. LegacyCompletionHandler, handler) type_check;
  155. detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler);
  156. bool is_continuation =
  157. asio_handler_cont_helpers::is_continuation(handler2.value);
  158. // Allocate and construct an operation to wrap the handler.
  159. typedef detail::completion_handler<
  160. typename decay<LegacyCompletionHandler>::type> op;
  161. typename op::ptr p = { detail::addressof(handler2.value),
  162. op::ptr::allocate(handler2.value), 0 };
  163. p.p = new (p.v) op(handler2.value);
  164. ASIO_HANDLER_CREATION((*self, *p.p,
  165. "io_context", self, 0, "post"));
  166. self->impl_.post_immediate_completion(p.p, is_continuation);
  167. p.v = p.p = 0;
  168. }
  169. };
  170. template <typename LegacyCompletionHandler>
  171. ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
  172. io_context::post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
  173. {
  174. return async_initiate<LegacyCompletionHandler, void ()>(
  175. initiate_post(), handler, this);
  176. }
  177. template <typename Handler>
  178. #if defined(GENERATING_DOCUMENTATION)
  179. unspecified
  180. #else
  181. inline detail::wrapped_handler<io_context&, Handler>
  182. #endif
  183. io_context::wrap(Handler handler)
  184. {
  185. return detail::wrapped_handler<io_context&, Handler>(*this, handler);
  186. }
  187. #endif // !defined(ASIO_NO_DEPRECATED)
  188. inline io_context&
  189. io_context::executor_type::context() const ASIO_NOEXCEPT
  190. {
  191. return io_context_;
  192. }
  193. inline void
  194. io_context::executor_type::on_work_started() const ASIO_NOEXCEPT
  195. {
  196. io_context_.impl_.work_started();
  197. }
  198. inline void
  199. io_context::executor_type::on_work_finished() const ASIO_NOEXCEPT
  200. {
  201. io_context_.impl_.work_finished();
  202. }
  203. template <typename Function, typename Allocator>
  204. void io_context::executor_type::dispatch(
  205. ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  206. {
  207. typedef typename decay<Function>::type function_type;
  208. // Invoke immediately if we are already inside the thread pool.
  209. if (io_context_.impl_.can_dispatch())
  210. {
  211. // Make a local, non-const copy of the function.
  212. function_type tmp(ASIO_MOVE_CAST(Function)(f));
  213. detail::fenced_block b(detail::fenced_block::full);
  214. asio_handler_invoke_helpers::invoke(tmp, tmp);
  215. return;
  216. }
  217. // Allocate and construct an operation to wrap the function.
  218. typedef detail::executor_op<function_type, Allocator, detail::operation> op;
  219. typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
  220. p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
  221. ASIO_HANDLER_CREATION((this->context(), *p.p,
  222. "io_context", &this->context(), 0, "dispatch"));
  223. io_context_.impl_.post_immediate_completion(p.p, false);
  224. p.v = p.p = 0;
  225. }
  226. template <typename Function, typename Allocator>
  227. void io_context::executor_type::post(
  228. ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  229. {
  230. typedef typename decay<Function>::type function_type;
  231. // Allocate and construct an operation to wrap the function.
  232. typedef detail::executor_op<function_type, Allocator, detail::operation> op;
  233. typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
  234. p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
  235. ASIO_HANDLER_CREATION((this->context(), *p.p,
  236. "io_context", &this->context(), 0, "post"));
  237. io_context_.impl_.post_immediate_completion(p.p, false);
  238. p.v = p.p = 0;
  239. }
  240. template <typename Function, typename Allocator>
  241. void io_context::executor_type::defer(
  242. ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  243. {
  244. typedef typename decay<Function>::type function_type;
  245. // Allocate and construct an operation to wrap the function.
  246. typedef detail::executor_op<function_type, Allocator, detail::operation> op;
  247. typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
  248. p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
  249. ASIO_HANDLER_CREATION((this->context(), *p.p,
  250. "io_context", &this->context(), 0, "defer"));
  251. io_context_.impl_.post_immediate_completion(p.p, true);
  252. p.v = p.p = 0;
  253. }
  254. inline bool
  255. io_context::executor_type::running_in_this_thread() const ASIO_NOEXCEPT
  256. {
  257. return io_context_.impl_.can_dispatch();
  258. }
  259. #if !defined(ASIO_NO_DEPRECATED)
  260. inline io_context::work::work(asio::io_context& io_context)
  261. : io_context_impl_(io_context.impl_)
  262. {
  263. io_context_impl_.work_started();
  264. }
  265. inline io_context::work::work(const work& other)
  266. : io_context_impl_(other.io_context_impl_)
  267. {
  268. io_context_impl_.work_started();
  269. }
  270. inline io_context::work::~work()
  271. {
  272. io_context_impl_.work_finished();
  273. }
  274. inline asio::io_context& io_context::work::get_io_context()
  275. {
  276. return static_cast<asio::io_context&>(io_context_impl_.context());
  277. }
  278. #endif // !defined(ASIO_NO_DEPRECATED)
  279. inline asio::io_context& io_context::service::get_io_context()
  280. {
  281. return static_cast<asio::io_context&>(context());
  282. }
  283. } // namespace asio
  284. #include "asio/detail/pop_options.hpp"
  285. #endif // ASIO_IMPL_IO_CONTEXT_HPP