1//
2// detail/impl/reactive_descriptor_service.ipp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 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_REACTIVE_DESCRIPTOR_SERVICE_IPP
12#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_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
20#if !defined(BOOST_ASIO_WINDOWS) \
21 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
22 && !defined(__CYGWIN__)
23
24#include <boost/asio/error.hpp>
25#include <boost/asio/detail/reactive_descriptor_service.hpp>
26
27#include <boost/asio/detail/push_options.hpp>
28
29namespace boost {
30namespace asio {
31namespace detail {
32
33reactive_descriptor_service::reactive_descriptor_service(
34 boost::asio::io_service& io_service)
35 : reactor_(boost::asio::use_service<reactor>(ios&: io_service))
36{
37 reactor_.init_task();
38}
39
40void reactive_descriptor_service::shutdown_service()
41{
42}
43
44void reactive_descriptor_service::construct(
45 reactive_descriptor_service::implementation_type& impl)
46{
47 impl.descriptor_ = -1;
48 impl.state_ = 0;
49}
50
51void reactive_descriptor_service::move_construct(
52 reactive_descriptor_service::implementation_type& impl,
53 reactive_descriptor_service::implementation_type& other_impl)
54{
55 impl.descriptor_ = other_impl.descriptor_;
56 other_impl.descriptor_ = -1;
57
58 impl.state_ = other_impl.state_;
59 other_impl.state_ = 0;
60
61 reactor_.move_descriptor(impl.descriptor_,
62 target_descriptor_data&: impl.reactor_data_, source_descriptor_data&: other_impl.reactor_data_);
63}
64
65void reactive_descriptor_service::move_assign(
66 reactive_descriptor_service::implementation_type& impl,
67 reactive_descriptor_service& other_service,
68 reactive_descriptor_service::implementation_type& other_impl)
69{
70 destroy(impl);
71
72 impl.descriptor_ = other_impl.descriptor_;
73 other_impl.descriptor_ = -1;
74
75 impl.state_ = other_impl.state_;
76 other_impl.state_ = 0;
77
78 other_service.reactor_.move_descriptor(impl.descriptor_,
79 target_descriptor_data&: impl.reactor_data_, source_descriptor_data&: other_impl.reactor_data_);
80}
81
82void reactive_descriptor_service::destroy(
83 reactive_descriptor_service::implementation_type& impl)
84{
85 if (is_open(impl))
86 {
87 BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "close"));
88
89 reactor_.deregister_descriptor(descriptor: impl.descriptor_, descriptor_data&: impl.reactor_data_,
90 closing: (impl.state_ & descriptor_ops::possible_dup) == 0);
91 }
92
93 boost::system::error_code ignored_ec;
94 descriptor_ops::close(d: impl.descriptor_, state&: impl.state_, ec&: ignored_ec);
95}
96
97boost::system::error_code reactive_descriptor_service::assign(
98 reactive_descriptor_service::implementation_type& impl,
99 const native_handle_type& native_descriptor, boost::system::error_code& ec)
100{
101 if (is_open(impl))
102 {
103 ec = boost::asio::error::already_open;
104 return ec;
105 }
106
107 if (int err = reactor_.register_descriptor(
108 descriptor: native_descriptor, descriptor_data&: impl.reactor_data_))
109 {
110 ec = boost::system::error_code(err,
111 boost::asio::error::get_system_category());
112 return ec;
113 }
114
115 impl.descriptor_ = native_descriptor;
116 impl.state_ = descriptor_ops::possible_dup;
117 ec = boost::system::error_code();
118 return ec;
119}
120
121boost::system::error_code reactive_descriptor_service::close(
122 reactive_descriptor_service::implementation_type& impl,
123 boost::system::error_code& ec)
124{
125 if (is_open(impl))
126 {
127 BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "close"));
128
129 reactor_.deregister_descriptor(descriptor: impl.descriptor_, descriptor_data&: impl.reactor_data_,
130 closing: (impl.state_ & descriptor_ops::possible_dup) == 0);
131 }
132
133 descriptor_ops::close(d: impl.descriptor_, state&: impl.state_, ec);
134
135 // The descriptor is closed by the OS even if close() returns an error.
136 //
137 // (Actually, POSIX says the state of the descriptor is unspecified. On
138 // Linux the descriptor is apparently closed anyway; e.g. see
139 // http://lkml.org/lkml/2005/9/10/129
140 // We'll just have to assume that other OSes follow the same behaviour.)
141 construct(impl);
142
143 return ec;
144}
145
146reactive_descriptor_service::native_handle_type
147reactive_descriptor_service::release(
148 reactive_descriptor_service::implementation_type& impl)
149{
150 native_handle_type descriptor = impl.descriptor_;
151
152 if (is_open(impl))
153 {
154 BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "release"));
155
156 reactor_.deregister_descriptor(descriptor: impl.descriptor_, descriptor_data&: impl.reactor_data_, closing: false);
157 construct(impl);
158 }
159
160 return descriptor;
161}
162
163boost::system::error_code reactive_descriptor_service::cancel(
164 reactive_descriptor_service::implementation_type& impl,
165 boost::system::error_code& ec)
166{
167 if (!is_open(impl))
168 {
169 ec = boost::asio::error::bad_descriptor;
170 return ec;
171 }
172
173 BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "cancel"));
174
175 reactor_.cancel_ops(impl.descriptor_, descriptor_data&: impl.reactor_data_);
176 ec = boost::system::error_code();
177 return ec;
178}
179
180void reactive_descriptor_service::start_op(
181 reactive_descriptor_service::implementation_type& impl,
182 int op_type, reactor_op* op, bool is_continuation,
183 bool is_non_blocking, bool noop)
184{
185 if (!noop)
186 {
187 if ((impl.state_ & descriptor_ops::non_blocking) ||
188 descriptor_ops::set_internal_non_blocking(
189 d: impl.descriptor_, state&: impl.state_, value: true, ec&: op->ec_))
190 {
191 reactor_.start_op(op_type, descriptor: impl.descriptor_,
192 descriptor_data&: impl.reactor_data_, op, is_continuation, allow_speculative: is_non_blocking);
193 return;
194 }
195 }
196
197 reactor_.post_immediate_completion(op, is_continuation);
198}
199
200} // namespace detail
201} // namespace asio
202} // namespace boost
203
204#include <boost/asio/detail/pop_options.hpp>
205
206#endif // !defined(BOOST_ASIO_WINDOWS)
207 // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
208 // && !defined(__CYGWIN__)
209
210#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
211

source code of boost/boost/asio/detail/impl/reactive_descriptor_service.ipp