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