Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:43

0001 //
0002 // detail/reactive_socket_service_base.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
0012 #define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if !defined(BOOST_ASIO_HAS_IOCP) \
0021   && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0022   && !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0023 
0024 #include <boost/asio/associated_cancellation_slot.hpp>
0025 #include <boost/asio/buffer.hpp>
0026 #include <boost/asio/cancellation_type.hpp>
0027 #include <boost/asio/error.hpp>
0028 #include <boost/asio/execution_context.hpp>
0029 #include <boost/asio/socket_base.hpp>
0030 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0031 #include <boost/asio/detail/memory.hpp>
0032 #include <boost/asio/detail/reactive_null_buffers_op.hpp>
0033 #include <boost/asio/detail/reactive_socket_recv_op.hpp>
0034 #include <boost/asio/detail/reactive_socket_recvmsg_op.hpp>
0035 #include <boost/asio/detail/reactive_socket_send_op.hpp>
0036 #include <boost/asio/detail/reactive_wait_op.hpp>
0037 #include <boost/asio/detail/reactor.hpp>
0038 #include <boost/asio/detail/reactor_op.hpp>
0039 #include <boost/asio/detail/socket_holder.hpp>
0040 #include <boost/asio/detail/socket_ops.hpp>
0041 #include <boost/asio/detail/socket_types.hpp>
0042 
0043 #include <boost/asio/detail/push_options.hpp>
0044 
0045 namespace boost {
0046 namespace asio {
0047 namespace detail {
0048 
0049 class reactive_socket_service_base
0050 {
0051 public:
0052   // The native type of a socket.
0053   typedef socket_type native_handle_type;
0054 
0055   // The implementation type of the socket.
0056   struct base_implementation_type
0057   {
0058     // The native socket representation.
0059     socket_type socket_;
0060 
0061     // The current state of the socket.
0062     socket_ops::state_type state_;
0063 
0064     // Per-descriptor data used by the reactor.
0065     reactor::per_descriptor_data reactor_data_;
0066   };
0067 
0068   // Constructor.
0069   BOOST_ASIO_DECL reactive_socket_service_base(execution_context& context);
0070 
0071   // Destroy all user-defined handler objects owned by the service.
0072   BOOST_ASIO_DECL void base_shutdown();
0073 
0074   // Construct a new socket implementation.
0075   BOOST_ASIO_DECL void construct(base_implementation_type& impl);
0076 
0077   // Move-construct a new socket implementation.
0078   BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
0079       base_implementation_type& other_impl) noexcept;
0080 
0081   // Move-assign from another socket implementation.
0082   BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
0083       reactive_socket_service_base& other_service,
0084       base_implementation_type& other_impl);
0085 
0086   // Destroy a socket implementation.
0087   BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
0088 
0089   // Determine whether the socket is open.
0090   bool is_open(const base_implementation_type& impl) const
0091   {
0092     return impl.socket_ != invalid_socket;
0093   }
0094 
0095   // Destroy a socket implementation.
0096   BOOST_ASIO_DECL boost::system::error_code close(
0097       base_implementation_type& impl, boost::system::error_code& ec);
0098 
0099   // Release ownership of the socket.
0100   BOOST_ASIO_DECL socket_type release(
0101       base_implementation_type& impl, boost::system::error_code& ec);
0102 
0103   // Get the native socket representation.
0104   native_handle_type native_handle(base_implementation_type& impl)
0105   {
0106     return impl.socket_;
0107   }
0108 
0109   // Cancel all operations associated with the socket.
0110   BOOST_ASIO_DECL boost::system::error_code cancel(
0111       base_implementation_type& impl, boost::system::error_code& ec);
0112 
0113   // Determine whether the socket is at the out-of-band data mark.
0114   bool at_mark(const base_implementation_type& impl,
0115       boost::system::error_code& ec) const
0116   {
0117     return socket_ops::sockatmark(impl.socket_, ec);
0118   }
0119 
0120   // Determine the number of bytes available for reading.
0121   std::size_t available(const base_implementation_type& impl,
0122       boost::system::error_code& ec) const
0123   {
0124     return socket_ops::available(impl.socket_, ec);
0125   }
0126 
0127   // Place the socket into the state where it will listen for new connections.
0128   boost::system::error_code listen(base_implementation_type& impl,
0129       int backlog, boost::system::error_code& ec)
0130   {
0131     socket_ops::listen(impl.socket_, backlog, ec);
0132     return ec;
0133   }
0134 
0135   // Perform an IO control command on the socket.
0136   template <typename IO_Control_Command>
0137   boost::system::error_code io_control(base_implementation_type& impl,
0138       IO_Control_Command& command, boost::system::error_code& ec)
0139   {
0140     socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
0141         static_cast<ioctl_arg_type*>(command.data()), ec);
0142     return ec;
0143   }
0144 
0145   // Gets the non-blocking mode of the socket.
0146   bool non_blocking(const base_implementation_type& impl) const
0147   {
0148     return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
0149   }
0150 
0151   // Sets the non-blocking mode of the socket.
0152   boost::system::error_code non_blocking(base_implementation_type& impl,
0153       bool mode, boost::system::error_code& ec)
0154   {
0155     socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
0156     return ec;
0157   }
0158 
0159   // Gets the non-blocking mode of the native socket implementation.
0160   bool native_non_blocking(const base_implementation_type& impl) const
0161   {
0162     return (impl.state_ & socket_ops::internal_non_blocking) != 0;
0163   }
0164 
0165   // Sets the non-blocking mode of the native socket implementation.
0166   boost::system::error_code native_non_blocking(base_implementation_type& impl,
0167       bool mode, boost::system::error_code& ec)
0168   {
0169     socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
0170     return ec;
0171   }
0172 
0173   // Wait for the socket to become ready to read, ready to write, or to have
0174   // pending error conditions.
0175   boost::system::error_code wait(base_implementation_type& impl,
0176       socket_base::wait_type w, boost::system::error_code& ec)
0177   {
0178     switch (w)
0179     {
0180     case socket_base::wait_read:
0181       socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0182       break;
0183     case socket_base::wait_write:
0184       socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
0185       break;
0186     case socket_base::wait_error:
0187       socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);
0188       break;
0189     default:
0190       ec = boost::asio::error::invalid_argument;
0191       break;
0192     }
0193 
0194     return ec;
0195   }
0196 
0197   // Asynchronously wait for the socket to become ready to read, ready to
0198   // write, or to have pending error conditions.
0199   template <typename Handler, typename IoExecutor>
0200   void async_wait(base_implementation_type& impl,
0201       socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)
0202   {
0203     bool is_continuation =
0204       boost_asio_handler_cont_helpers::is_continuation(handler);
0205 
0206     associated_cancellation_slot_t<Handler> slot
0207       = boost::asio::get_associated_cancellation_slot(handler);
0208 
0209     // Allocate and construct an operation to wrap the handler.
0210     typedef reactive_wait_op<Handler, IoExecutor> op;
0211     typename op::ptr p = { boost::asio::detail::addressof(handler),
0212       op::ptr::allocate(handler), 0 };
0213     p.p = new (p.v) op(success_ec_, handler, io_ex);
0214 
0215     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0216           &impl, impl.socket_, "async_wait"));
0217 
0218     int op_type;
0219     switch (w)
0220     {
0221     case socket_base::wait_read:
0222       op_type = reactor::read_op;
0223       break;
0224     case socket_base::wait_write:
0225       op_type = reactor::write_op;
0226       break;
0227     case socket_base::wait_error:
0228       op_type = reactor::except_op;
0229       break;
0230     default:
0231       p.p->ec_ = boost::asio::error::invalid_argument;
0232       start_op(impl, reactor::read_op, p.p,
0233           is_continuation, false, true, &io_ex, 0);
0234       p.v = p.p = 0;
0235       return;
0236     }
0237 
0238     // Optionally register for per-operation cancellation.
0239     if (slot.is_connected())
0240     {
0241       p.p->cancellation_key_ =
0242         &slot.template emplace<reactor_op_cancellation>(
0243             &reactor_, &impl.reactor_data_, impl.socket_, op_type);
0244     }
0245 
0246     start_op(impl, op_type, p.p, is_continuation, false, false, &io_ex, 0);
0247     p.v = p.p = 0;
0248   }
0249 
0250   // Send the given data to the peer.
0251   template <typename ConstBufferSequence>
0252   size_t send(base_implementation_type& impl,
0253       const ConstBufferSequence& buffers,
0254       socket_base::message_flags flags, boost::system::error_code& ec)
0255   {
0256     typedef buffer_sequence_adapter<boost::asio::const_buffer,
0257         ConstBufferSequence> bufs_type;
0258 
0259     if (bufs_type::is_single_buffer)
0260     {
0261       return socket_ops::sync_send1(impl.socket_,
0262           impl.state_, bufs_type::first(buffers).data(),
0263           bufs_type::first(buffers).size(), flags, ec);
0264     }
0265     else
0266     {
0267       bufs_type bufs(buffers);
0268       return socket_ops::sync_send(impl.socket_, impl.state_,
0269           bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
0270     }
0271   }
0272 
0273   // Wait until data can be sent without blocking.
0274   size_t send(base_implementation_type& impl, const null_buffers&,
0275       socket_base::message_flags, boost::system::error_code& ec)
0276   {
0277     // Wait for socket to become ready.
0278     socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
0279 
0280     return 0;
0281   }
0282 
0283   // Start an asynchronous send. The data being sent must be valid for the
0284   // lifetime of the asynchronous operation.
0285   template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
0286   void async_send(base_implementation_type& impl,
0287       const ConstBufferSequence& buffers, socket_base::message_flags flags,
0288       Handler& handler, const IoExecutor& io_ex)
0289   {
0290     bool is_continuation =
0291       boost_asio_handler_cont_helpers::is_continuation(handler);
0292 
0293     associated_cancellation_slot_t<Handler> slot
0294       = boost::asio::get_associated_cancellation_slot(handler);
0295 
0296     // Allocate and construct an operation to wrap the handler.
0297     typedef reactive_socket_send_op<
0298         ConstBufferSequence, Handler, IoExecutor> op;
0299     typename op::ptr p = { boost::asio::detail::addressof(handler),
0300       op::ptr::allocate(handler), 0 };
0301     p.p = new (p.v) op(success_ec_, impl.socket_,
0302         impl.state_, buffers, flags, handler, io_ex);
0303 
0304     // Optionally register for per-operation cancellation.
0305     if (slot.is_connected())
0306     {
0307       p.p->cancellation_key_ =
0308         &slot.template emplace<reactor_op_cancellation>(
0309             &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);
0310     }
0311 
0312     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0313           &impl, impl.socket_, "async_send"));
0314 
0315     start_op(impl, reactor::write_op, p.p, is_continuation, true,
0316         ((impl.state_ & socket_ops::stream_oriented)
0317           && buffer_sequence_adapter<boost::asio::const_buffer,
0318             ConstBufferSequence>::all_empty(buffers)), &io_ex, 0);
0319     p.v = p.p = 0;
0320   }
0321 
0322   // Start an asynchronous wait until data can be sent without blocking.
0323   template <typename Handler, typename IoExecutor>
0324   void async_send(base_implementation_type& impl, const null_buffers&,
0325       socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
0326   {
0327     bool is_continuation =
0328       boost_asio_handler_cont_helpers::is_continuation(handler);
0329 
0330     associated_cancellation_slot_t<Handler> slot
0331       = boost::asio::get_associated_cancellation_slot(handler);
0332 
0333     // Allocate and construct an operation to wrap the handler.
0334     typedef reactive_null_buffers_op<Handler, IoExecutor> op;
0335     typename op::ptr p = { boost::asio::detail::addressof(handler),
0336       op::ptr::allocate(handler), 0 };
0337     p.p = new (p.v) op(success_ec_, handler, io_ex);
0338 
0339     // Optionally register for per-operation cancellation.
0340     if (slot.is_connected())
0341     {
0342       p.p->cancellation_key_ =
0343         &slot.template emplace<reactor_op_cancellation>(
0344             &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);
0345     }
0346 
0347     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0348           &impl, impl.socket_, "async_send(null_buffers)"));
0349 
0350     start_op(impl, reactor::write_op, p.p,
0351         is_continuation, false, false, &io_ex, 0);
0352     p.v = p.p = 0;
0353   }
0354 
0355   // Receive some data from the peer. Returns the number of bytes received.
0356   template <typename MutableBufferSequence>
0357   size_t receive(base_implementation_type& impl,
0358       const MutableBufferSequence& buffers,
0359       socket_base::message_flags flags, boost::system::error_code& ec)
0360   {
0361     typedef buffer_sequence_adapter<boost::asio::mutable_buffer,
0362         MutableBufferSequence> bufs_type;
0363 
0364     if (bufs_type::is_single_buffer)
0365     {
0366       return socket_ops::sync_recv1(impl.socket_,
0367           impl.state_, bufs_type::first(buffers).data(),
0368           bufs_type::first(buffers).size(), flags, ec);
0369     }
0370     else
0371     {
0372       bufs_type bufs(buffers);
0373       return socket_ops::sync_recv(impl.socket_, impl.state_,
0374           bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
0375     }
0376   }
0377 
0378   // Wait until data can be received without blocking.
0379   size_t receive(base_implementation_type& impl, const null_buffers&,
0380       socket_base::message_flags, boost::system::error_code& ec)
0381   {
0382     // Wait for socket to become ready.
0383     socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0384 
0385     return 0;
0386   }
0387 
0388   // Start an asynchronous receive. The buffer for the data being received
0389   // must be valid for the lifetime of the asynchronous operation.
0390   template <typename MutableBufferSequence,
0391       typename Handler, typename IoExecutor>
0392   void async_receive(base_implementation_type& impl,
0393       const MutableBufferSequence& buffers, socket_base::message_flags flags,
0394       Handler& handler, const IoExecutor& io_ex)
0395   {
0396     bool is_continuation =
0397       boost_asio_handler_cont_helpers::is_continuation(handler);
0398 
0399     associated_cancellation_slot_t<Handler> slot
0400       = boost::asio::get_associated_cancellation_slot(handler);
0401 
0402     // Allocate and construct an operation to wrap the handler.
0403     typedef reactive_socket_recv_op<
0404         MutableBufferSequence, Handler, IoExecutor> op;
0405     typename op::ptr p = { boost::asio::detail::addressof(handler),
0406       op::ptr::allocate(handler), 0 };
0407     p.p = new (p.v) op(success_ec_, impl.socket_,
0408         impl.state_, buffers, flags, handler, io_ex);
0409 
0410     // Optionally register for per-operation cancellation.
0411     if (slot.is_connected())
0412     {
0413       p.p->cancellation_key_ =
0414         &slot.template emplace<reactor_op_cancellation>(
0415             &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);
0416     }
0417 
0418     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0419           &impl, impl.socket_, "async_receive"));
0420 
0421     start_op(impl,
0422         (flags & socket_base::message_out_of_band)
0423           ? reactor::except_op : reactor::read_op,
0424         p.p, is_continuation,
0425         (flags & socket_base::message_out_of_band) == 0,
0426         ((impl.state_ & socket_ops::stream_oriented)
0427           && buffer_sequence_adapter<boost::asio::mutable_buffer,
0428             MutableBufferSequence>::all_empty(buffers)), &io_ex, 0);
0429     p.v = p.p = 0;
0430   }
0431 
0432   // Wait until data can be received without blocking.
0433   template <typename Handler, typename IoExecutor>
0434   void async_receive(base_implementation_type& impl,
0435       const null_buffers&, socket_base::message_flags flags,
0436       Handler& handler, const IoExecutor& io_ex)
0437   {
0438     bool is_continuation =
0439       boost_asio_handler_cont_helpers::is_continuation(handler);
0440 
0441     associated_cancellation_slot_t<Handler> slot
0442       = boost::asio::get_associated_cancellation_slot(handler);
0443 
0444     // Allocate and construct an operation to wrap the handler.
0445     typedef reactive_null_buffers_op<Handler, IoExecutor> op;
0446     typename op::ptr p = { boost::asio::detail::addressof(handler),
0447       op::ptr::allocate(handler), 0 };
0448     p.p = new (p.v) op(success_ec_, handler, io_ex);
0449 
0450     // Optionally register for per-operation cancellation.
0451     if (slot.is_connected())
0452     {
0453       p.p->cancellation_key_ =
0454         &slot.template emplace<reactor_op_cancellation>(
0455             &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);
0456     }
0457 
0458     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0459           &impl, impl.socket_, "async_receive(null_buffers)"));
0460 
0461     start_op(impl,
0462         (flags & socket_base::message_out_of_band)
0463           ? reactor::except_op : reactor::read_op,
0464         p.p, is_continuation, false, false, &io_ex, 0);
0465     p.v = p.p = 0;
0466   }
0467 
0468   // Receive some data with associated flags. Returns the number of bytes
0469   // received.
0470   template <typename MutableBufferSequence>
0471   size_t receive_with_flags(base_implementation_type& impl,
0472       const MutableBufferSequence& buffers,
0473       socket_base::message_flags in_flags,
0474       socket_base::message_flags& out_flags, boost::system::error_code& ec)
0475   {
0476     buffer_sequence_adapter<boost::asio::mutable_buffer,
0477         MutableBufferSequence> bufs(buffers);
0478 
0479     return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
0480         bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
0481   }
0482 
0483   // Wait until data can be received without blocking.
0484   size_t receive_with_flags(base_implementation_type& impl,
0485       const null_buffers&, socket_base::message_flags,
0486       socket_base::message_flags& out_flags, boost::system::error_code& ec)
0487   {
0488     // Wait for socket to become ready.
0489     socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0490 
0491     // Clear out_flags, since we cannot give it any other sensible value when
0492     // performing a null_buffers operation.
0493     out_flags = 0;
0494 
0495     return 0;
0496   }
0497 
0498   // Start an asynchronous receive. The buffer for the data being received
0499   // must be valid for the lifetime of the asynchronous operation.
0500   template <typename MutableBufferSequence,
0501       typename Handler, typename IoExecutor>
0502   void async_receive_with_flags(base_implementation_type& impl,
0503       const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
0504       socket_base::message_flags& out_flags, Handler& handler,
0505       const IoExecutor& io_ex)
0506   {
0507     bool is_continuation =
0508       boost_asio_handler_cont_helpers::is_continuation(handler);
0509 
0510     associated_cancellation_slot_t<Handler> slot
0511       = boost::asio::get_associated_cancellation_slot(handler);
0512 
0513     // Allocate and construct an operation to wrap the handler.
0514     typedef reactive_socket_recvmsg_op<
0515         MutableBufferSequence, Handler, IoExecutor> op;
0516     typename op::ptr p = { boost::asio::detail::addressof(handler),
0517       op::ptr::allocate(handler), 0 };
0518     p.p = new (p.v) op(success_ec_, impl.socket_,
0519         buffers, in_flags, out_flags, handler, io_ex);
0520 
0521     // Optionally register for per-operation cancellation.
0522     if (slot.is_connected())
0523     {
0524       p.p->cancellation_key_ =
0525         &slot.template emplace<reactor_op_cancellation>(
0526             &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);
0527     }
0528 
0529     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0530           &impl, impl.socket_, "async_receive_with_flags"));
0531 
0532     start_op(impl,
0533         (in_flags & socket_base::message_out_of_band)
0534           ? reactor::except_op : reactor::read_op,
0535         p.p, is_continuation,
0536         (in_flags & socket_base::message_out_of_band) == 0, false, &io_ex, 0);
0537     p.v = p.p = 0;
0538   }
0539 
0540   // Wait until data can be received without blocking.
0541   template <typename Handler, typename IoExecutor>
0542   void async_receive_with_flags(base_implementation_type& impl,
0543       const null_buffers&, socket_base::message_flags in_flags,
0544       socket_base::message_flags& out_flags, Handler& handler,
0545       const IoExecutor& io_ex)
0546   {
0547     bool is_continuation =
0548       boost_asio_handler_cont_helpers::is_continuation(handler);
0549 
0550     associated_cancellation_slot_t<Handler> slot
0551       = boost::asio::get_associated_cancellation_slot(handler);
0552 
0553     // Allocate and construct an operation to wrap the handler.
0554     typedef reactive_null_buffers_op<Handler, IoExecutor> op;
0555     typename op::ptr p = { boost::asio::detail::addressof(handler),
0556       op::ptr::allocate(handler), 0 };
0557     p.p = new (p.v) op(success_ec_, handler, io_ex);
0558 
0559     // Optionally register for per-operation cancellation.
0560     if (slot.is_connected())
0561     {
0562       p.p->cancellation_key_ =
0563         &slot.template emplace<reactor_op_cancellation>(
0564             &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);
0565     }
0566 
0567     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0568           &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
0569 
0570     // Clear out_flags, since we cannot give it any other sensible value when
0571     // performing a null_buffers operation.
0572     out_flags = 0;
0573 
0574     start_op(impl,
0575         (in_flags & socket_base::message_out_of_band)
0576           ? reactor::except_op : reactor::read_op,
0577         p.p, is_continuation, false, false, &io_ex, 0);
0578     p.v = p.p = 0;
0579   }
0580 
0581 protected:
0582   // Open a new socket implementation.
0583   BOOST_ASIO_DECL boost::system::error_code do_open(
0584       base_implementation_type& impl, int af,
0585       int type, int protocol, boost::system::error_code& ec);
0586 
0587   // Assign a native socket to a socket implementation.
0588   BOOST_ASIO_DECL boost::system::error_code do_assign(
0589       base_implementation_type& impl, int type,
0590       const native_handle_type& native_socket, boost::system::error_code& ec);
0591 
0592   // Start the asynchronous read or write operation.
0593   BOOST_ASIO_DECL void do_start_op(base_implementation_type& impl, int op_type,
0594       reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop,
0595       void (*on_immediate)(operation* op, bool, const void*),
0596       const void* immediate_arg);
0597 
0598   // Start the asynchronous operation for handlers that are specialised for
0599   // immediate completion.
0600   template <typename Op>
0601   void start_op(base_implementation_type& impl, int op_type, Op* op,
0602       bool is_continuation, bool is_non_blocking, bool noop,
0603       const void* io_ex, ...)
0604   {
0605     return do_start_op(impl, op_type, op, is_continuation,
0606         is_non_blocking, noop, &Op::do_immediate, io_ex);
0607   }
0608 
0609   // Start the asynchronous operation for handlers that are not specialised for
0610   // immediate completion.
0611   template <typename Op>
0612   void start_op(base_implementation_type& impl, int op_type, Op* op,
0613       bool is_continuation, bool is_non_blocking, bool noop, const void*,
0614       enable_if_t<
0615         is_same<
0616           typename associated_immediate_executor<
0617             typename Op::handler_type,
0618             typename Op::io_executor_type
0619           >::asio_associated_immediate_executor_is_unspecialised,
0620           void
0621         >::value
0622       >*)
0623   {
0624     return do_start_op(impl, op_type, op, is_continuation, is_non_blocking,
0625         noop, &reactor::call_post_immediate_completion, &reactor_);
0626   }
0627 
0628   // Start the asynchronous accept operation.
0629   BOOST_ASIO_DECL void do_start_accept_op(base_implementation_type& impl,
0630       reactor_op* op, bool is_continuation, bool peer_is_open,
0631       void (*on_immediate)(operation* op, bool, const void*),
0632       const void* immediate_arg);
0633 
0634   // Start the asynchronous accept operation for handlers that are specialised
0635   // for immediate completion.
0636   template <typename Op>
0637   void start_accept_op(base_implementation_type& impl, Op* op,
0638       bool is_continuation, bool peer_is_open, const void* io_ex, ...)
0639   {
0640     return do_start_accept_op(impl, op, is_continuation,
0641         peer_is_open, &Op::do_immediate, io_ex);
0642   }
0643 
0644   // Start the asynchronous operation for handlers that are not specialised for
0645   // immediate completion.
0646   template <typename Op>
0647   void start_accept_op(base_implementation_type& impl, Op* op,
0648       bool is_continuation, bool peer_is_open, const void*,
0649       enable_if_t<
0650         is_same<
0651           typename associated_immediate_executor<
0652             typename Op::handler_type,
0653             typename Op::io_executor_type
0654           >::asio_associated_immediate_executor_is_unspecialised,
0655           void
0656         >::value
0657       >*)
0658   {
0659     return do_start_accept_op(impl, op, is_continuation, peer_is_open,
0660         &reactor::call_post_immediate_completion, &reactor_);
0661   }
0662 
0663   // Start the asynchronous connect operation.
0664   BOOST_ASIO_DECL void do_start_connect_op(base_implementation_type& impl,
0665       reactor_op* op, bool is_continuation, const void* addr, size_t addrlen,
0666       void (*on_immediate)(operation* op, bool, const void*),
0667       const void* immediate_arg);
0668 
0669   // Start the asynchronous operation for handlers that are specialised for
0670   // immediate completion.
0671   template <typename Op>
0672   void start_connect_op(base_implementation_type& impl,
0673       Op* op, bool is_continuation, const void* addr,
0674       size_t addrlen, const void* io_ex, ...)
0675   {
0676     return do_start_connect_op(impl, op, is_continuation,
0677         addr, addrlen, &Op::do_immediate, io_ex);
0678   }
0679 
0680   // Start the asynchronous operation for handlers that are not specialised for
0681   // immediate completion.
0682   template <typename Op>
0683   void start_connect_op(base_implementation_type& impl, Op* op,
0684       bool is_continuation, const void* addr, size_t addrlen, const void*,
0685       enable_if_t<
0686         is_same<
0687           typename associated_immediate_executor<
0688             typename Op::handler_type,
0689             typename Op::io_executor_type
0690           >::asio_associated_immediate_executor_is_unspecialised,
0691           void
0692         >::value
0693       >*)
0694   {
0695     return do_start_connect_op(impl, op, is_continuation, addr,
0696         addrlen, &reactor::call_post_immediate_completion, &reactor_);
0697   }
0698 
0699   // Helper class used to implement per-operation cancellation
0700   class reactor_op_cancellation
0701   {
0702   public:
0703     reactor_op_cancellation(reactor* r,
0704         reactor::per_descriptor_data* p, socket_type d, int o)
0705       : reactor_(r),
0706         reactor_data_(p),
0707         descriptor_(d),
0708         op_type_(o)
0709     {
0710     }
0711 
0712     void operator()(cancellation_type_t type)
0713     {
0714       if (!!(type &
0715             (cancellation_type::terminal
0716               | cancellation_type::partial
0717               | cancellation_type::total)))
0718       {
0719         reactor_->cancel_ops_by_key(descriptor_,
0720             *reactor_data_, op_type_, this);
0721       }
0722     }
0723 
0724   private:
0725     reactor* reactor_;
0726     reactor::per_descriptor_data* reactor_data_;
0727     socket_type descriptor_;
0728     int op_type_;
0729   };
0730 
0731   // The selector that performs event demultiplexing for the service.
0732   reactor& reactor_;
0733 
0734   // Cached success value to avoid accessing category singleton.
0735   const boost::system::error_code success_ec_;
0736 };
0737 
0738 } // namespace detail
0739 } // namespace asio
0740 } // namespace boost
0741 
0742 #include <boost/asio/detail/pop_options.hpp>
0743 
0744 #if defined(BOOST_ASIO_HEADER_ONLY)
0745 # include <boost/asio/detail/impl/reactive_socket_service_base.ipp>
0746 #endif // defined(BOOST_ASIO_HEADER_ONLY)
0747 
0748 #endif // !defined(BOOST_ASIO_HAS_IOCP)
0749        //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
0750        //   && !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0751 
0752 #endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP