resolver_service_base.ipp 3.7 KB

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