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