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