io_context.hpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. //
  2. // impl/io_context.hpp
  3. // ~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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 BOOST_ASIO_IMPL_IO_CONTEXT_HPP
  11. #define BOOST_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 <boost/asio/detail/completion_handler.hpp>
  16. #include <boost/asio/detail/executor_op.hpp>
  17. #include <boost/asio/detail/fenced_block.hpp>
  18. #include <boost/asio/detail/handler_type_requirements.hpp>
  19. #include <boost/asio/detail/recycling_allocator.hpp>
  20. #include <boost/asio/detail/service_registry.hpp>
  21. #include <boost/asio/detail/throw_error.hpp>
  22. #include <boost/asio/detail/type_traits.hpp>
  23. #include <boost/asio/detail/push_options.hpp>
  24. namespace boost {
  25. namespace asio {
  26. template <typename Service>
  27. inline Service& use_service(io_context& ioc)
  28. {
  29. // Check that Service meets the necessary type requirements.
  30. (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
  31. (void)static_cast<const execution_context::id*>(&Service::id);
  32. return ioc.service_registry_->template use_service<Service>(ioc);
  33. }
  34. template <>
  35. inline detail::io_context_impl& use_service<detail::io_context_impl>(
  36. io_context& ioc)
  37. {
  38. return ioc.impl_;
  39. }
  40. } // namespace asio
  41. } // namespace boost
  42. #include <boost/asio/detail/pop_options.hpp>
  43. #if defined(BOOST_ASIO_HAS_IOCP)
  44. # include <boost/asio/detail/win_iocp_io_context.hpp>
  45. #else
  46. # include <boost/asio/detail/scheduler.hpp>
  47. #endif
  48. #include <boost/asio/detail/push_options.hpp>
  49. namespace boost {
  50. namespace asio {
  51. inline io_context::executor_type
  52. io_context::get_executor() BOOST_ASIO_NOEXCEPT
  53. {
  54. return executor_type(*this);
  55. }
  56. #if defined(BOOST_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. boost::system::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. boost::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(BOOST_ASIO_HAS_CHRONO)
  101. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  102. inline void io_context::reset()
  103. {
  104. restart();
  105. }
  106. template <typename LegacyCompletionHandler>
  107. BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
  108. io_context::dispatch(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
  109. {
  110. // If you get an error on the following line it means that your handler does
  111. // not meet the documented type requirements for a LegacyCompletionHandler.
  112. BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
  113. LegacyCompletionHandler, handler) type_check;
  114. async_completion<LegacyCompletionHandler, void ()> init(handler);
  115. if (impl_.can_dispatch())
  116. {
  117. detail::fenced_block b(detail::fenced_block::full);
  118. boost_asio_handler_invoke_helpers::invoke(
  119. init.completion_handler, init.completion_handler);
  120. }
  121. else
  122. {
  123. // Allocate and construct an operation to wrap the handler.
  124. typedef detail::completion_handler<
  125. typename handler_type<LegacyCompletionHandler, void ()>::type> op;
  126. typename op::ptr p = { detail::addressof(init.completion_handler),
  127. op::ptr::allocate(init.completion_handler), 0 };
  128. p.p = new (p.v) op(init.completion_handler);
  129. BOOST_ASIO_HANDLER_CREATION((*this, *p.p,
  130. "io_context", this, 0, "dispatch"));
  131. impl_.do_dispatch(p.p);
  132. p.v = p.p = 0;
  133. }
  134. return init.result.get();
  135. }
  136. template <typename LegacyCompletionHandler>
  137. BOOST_ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
  138. io_context::post(BOOST_ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
  139. {
  140. // If you get an error on the following line it means that your handler does
  141. // not meet the documented type requirements for a LegacyCompletionHandler.
  142. BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
  143. LegacyCompletionHandler, handler) type_check;
  144. async_completion<LegacyCompletionHandler, void ()> init(handler);
  145. bool is_continuation =
  146. boost_asio_handler_cont_helpers::is_continuation(init.completion_handler);
  147. // Allocate and construct an operation to wrap the handler.
  148. typedef detail::completion_handler<
  149. typename handler_type<LegacyCompletionHandler, void ()>::type> op;
  150. typename op::ptr p = { detail::addressof(init.completion_handler),
  151. op::ptr::allocate(init.completion_handler), 0 };
  152. p.p = new (p.v) op(init.completion_handler);
  153. BOOST_ASIO_HANDLER_CREATION((*this, *p.p,
  154. "io_context", this, 0, "post"));
  155. impl_.post_immediate_completion(p.p, is_continuation);
  156. p.v = p.p = 0;
  157. return init.result.get();
  158. }
  159. template <typename Handler>
  160. #if defined(GENERATING_DOCUMENTATION)
  161. unspecified
  162. #else
  163. inline detail::wrapped_handler<io_context&, Handler>
  164. #endif
  165. io_context::wrap(Handler handler)
  166. {
  167. return detail::wrapped_handler<io_context&, Handler>(*this, handler);
  168. }
  169. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  170. inline io_context&
  171. io_context::executor_type::context() const BOOST_ASIO_NOEXCEPT
  172. {
  173. return io_context_;
  174. }
  175. inline void
  176. io_context::executor_type::on_work_started() const BOOST_ASIO_NOEXCEPT
  177. {
  178. io_context_.impl_.work_started();
  179. }
  180. inline void
  181. io_context::executor_type::on_work_finished() const BOOST_ASIO_NOEXCEPT
  182. {
  183. io_context_.impl_.work_finished();
  184. }
  185. template <typename Function, typename Allocator>
  186. void io_context::executor_type::dispatch(
  187. BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  188. {
  189. typedef typename decay<Function>::type function_type;
  190. // Invoke immediately if we are already inside the thread pool.
  191. if (io_context_.impl_.can_dispatch())
  192. {
  193. // Make a local, non-const copy of the function.
  194. function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
  195. detail::fenced_block b(detail::fenced_block::full);
  196. boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
  197. return;
  198. }
  199. // Allocate and construct an operation to wrap the function.
  200. typedef detail::executor_op<function_type, Allocator, detail::operation> op;
  201. typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
  202. p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
  203. BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
  204. "io_context", &this->context(), 0, "post"));
  205. io_context_.impl_.post_immediate_completion(p.p, false);
  206. p.v = p.p = 0;
  207. }
  208. template <typename Function, typename Allocator>
  209. void io_context::executor_type::post(
  210. BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  211. {
  212. typedef typename decay<Function>::type function_type;
  213. // Allocate and construct an operation to wrap the function.
  214. typedef detail::executor_op<function_type, Allocator, detail::operation> op;
  215. typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
  216. p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
  217. BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
  218. "io_context", &this->context(), 0, "post"));
  219. io_context_.impl_.post_immediate_completion(p.p, false);
  220. p.v = p.p = 0;
  221. }
  222. template <typename Function, typename Allocator>
  223. void io_context::executor_type::defer(
  224. BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
  225. {
  226. typedef typename decay<Function>::type function_type;
  227. // Allocate and construct an operation to wrap the function.
  228. typedef detail::executor_op<function_type, Allocator, detail::operation> op;
  229. typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
  230. p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
  231. BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
  232. "io_context", &this->context(), 0, "defer"));
  233. io_context_.impl_.post_immediate_completion(p.p, true);
  234. p.v = p.p = 0;
  235. }
  236. inline bool
  237. io_context::executor_type::running_in_this_thread() const BOOST_ASIO_NOEXCEPT
  238. {
  239. return io_context_.impl_.can_dispatch();
  240. }
  241. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  242. inline io_context::work::work(boost::asio::io_context& io_context)
  243. : io_context_impl_(io_context.impl_)
  244. {
  245. io_context_impl_.work_started();
  246. }
  247. inline io_context::work::work(const work& other)
  248. : io_context_impl_(other.io_context_impl_)
  249. {
  250. io_context_impl_.work_started();
  251. }
  252. inline io_context::work::~work()
  253. {
  254. io_context_impl_.work_finished();
  255. }
  256. inline boost::asio::io_context& io_context::work::get_io_context()
  257. {
  258. return static_cast<boost::asio::io_context&>(io_context_impl_.context());
  259. }
  260. inline boost::asio::io_context& io_context::work::get_io_service()
  261. {
  262. return static_cast<boost::asio::io_context&>(io_context_impl_.context());
  263. }
  264. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  265. inline boost::asio::io_context& io_context::service::get_io_context()
  266. {
  267. return static_cast<boost::asio::io_context&>(context());
  268. }
  269. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  270. inline boost::asio::io_context& io_context::service::get_io_service()
  271. {
  272. return static_cast<boost::asio::io_context&>(context());
  273. }
  274. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  275. } // namespace asio
  276. } // namespace boost
  277. #include <boost/asio/detail/pop_options.hpp>
  278. #endif // BOOST_ASIO_IMPL_IO_CONTEXT_HPP