resolver_service_base.ipp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. //
  2. // detail/impl/resolver_service_base.ipp
  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_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
  11. #define BOOST_ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/resolver_service_base.hpp>
  17. #include <boost/asio/detail/push_options.hpp>
  18. namespace boost {
  19. namespace asio {
  20. namespace detail {
  21. class resolver_service_base::work_io_context_runner
  22. {
  23. public:
  24. work_io_context_runner(boost::asio::io_context& io_context)
  25. : io_context_(io_context) {}
  26. void operator()() { io_context_.run(); }
  27. private:
  28. boost::asio::io_context& io_context_;
  29. };
  30. resolver_service_base::resolver_service_base(
  31. boost::asio::io_context& io_context)
  32. : io_context_impl_(boost::asio::use_service<io_context_impl>(io_context)),
  33. work_io_context_(new boost::asio::io_context(-1)),
  34. work_io_context_impl_(boost::asio::use_service<
  35. io_context_impl>(*work_io_context_)),
  36. work_(boost::asio::make_work_guard(*work_io_context_)),
  37. work_thread_(0)
  38. {
  39. }
  40. resolver_service_base::~resolver_service_base()
  41. {
  42. base_shutdown();
  43. }
  44. void resolver_service_base::base_shutdown()
  45. {
  46. work_.reset();
  47. if (work_io_context_.get())
  48. {
  49. work_io_context_->stop();
  50. if (work_thread_.get())
  51. {
  52. work_thread_->join();
  53. work_thread_.reset();
  54. }
  55. work_io_context_.reset();
  56. }
  57. }
  58. void resolver_service_base::base_notify_fork(
  59. boost::asio::io_context::fork_event fork_ev)
  60. {
  61. if (work_thread_.get())
  62. {
  63. if (fork_ev == boost::asio::io_context::fork_prepare)
  64. {
  65. work_io_context_->stop();
  66. work_thread_->join();
  67. }
  68. else
  69. {
  70. work_io_context_->restart();
  71. work_thread_.reset(new boost::asio::detail::thread(
  72. work_io_context_runner(*work_io_context_)));
  73. }
  74. }
  75. }
  76. void resolver_service_base::construct(
  77. resolver_service_base::implementation_type& impl)
  78. {
  79. impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
  80. }
  81. void resolver_service_base::destroy(
  82. resolver_service_base::implementation_type& impl)
  83. {
  84. BOOST_ASIO_HANDLER_OPERATION((io_context_impl_.context(),
  85. "resolver", &impl, 0, "cancel"));
  86. impl.reset();
  87. }
  88. void resolver_service_base::move_construct(implementation_type& impl,
  89. implementation_type& other_impl)
  90. {
  91. impl = BOOST_ASIO_MOVE_CAST(implementation_type)(other_impl);
  92. }
  93. void resolver_service_base::move_assign(implementation_type& impl,
  94. resolver_service_base&, implementation_type& other_impl)
  95. {
  96. destroy(impl);
  97. impl = BOOST_ASIO_MOVE_CAST(implementation_type)(other_impl);
  98. }
  99. void resolver_service_base::cancel(
  100. resolver_service_base::implementation_type& impl)
  101. {
  102. BOOST_ASIO_HANDLER_OPERATION((io_context_impl_.context(),
  103. "resolver", &impl, 0, "cancel"));
  104. impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
  105. }
  106. void resolver_service_base::start_resolve_op(resolve_op* op)
  107. {
  108. if (BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
  109. io_context_impl_.concurrency_hint()))
  110. {
  111. start_work_thread();
  112. io_context_impl_.work_started();
  113. work_io_context_impl_.post_immediate_completion(op, false);
  114. }
  115. else
  116. {
  117. op->ec_ = boost::asio::error::operation_not_supported;
  118. io_context_impl_.post_immediate_completion(op, false);
  119. }
  120. }
  121. void resolver_service_base::start_work_thread()
  122. {
  123. boost::asio::detail::mutex::scoped_lock lock(mutex_);
  124. if (!work_thread_.get())
  125. {
  126. work_thread_.reset(new boost::asio::detail::thread(
  127. work_io_context_runner(*work_io_context_)));
  128. }
  129. }
  130. } // namespace detail
  131. } // namespace asio
  132. } // namespace boost
  133. #include <boost/asio/detail/pop_options.hpp>
  134. #endif // BOOST_ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP