Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-12 08:08:01

0001 //
0002 // detail/reactive_socket_service_base.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 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, false, &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,
0247         false, false, false, &io_ex, 0);
0248     p.v = p.p = 0;
0249   }
0250 
0251   // Send the given data to the peer.
0252   template <typename ConstBufferSequence>
0253   size_t send(base_implementation_type& impl,
0254       const ConstBufferSequence& buffers,
0255       socket_base::message_flags flags, boost::system::error_code& ec)
0256   {
0257     typedef buffer_sequence_adapter<boost::asio::const_buffer,
0258         ConstBufferSequence> bufs_type;
0259 
0260     if (bufs_type::is_single_buffer)
0261     {
0262       return socket_ops::sync_send1(impl.socket_,
0263           impl.state_, bufs_type::first(buffers).data(),
0264           bufs_type::first(buffers).size(), flags, ec);
0265     }
0266     else
0267     {
0268       bufs_type bufs(buffers);
0269       return socket_ops::sync_send(impl.socket_, impl.state_,
0270           bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
0271     }
0272   }
0273 
0274   // Wait until data can be sent without blocking.
0275   size_t send(base_implementation_type& impl, const null_buffers&,
0276       socket_base::message_flags, boost::system::error_code& ec)
0277   {
0278     // Wait for socket to become ready.
0279     socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
0280 
0281     return 0;
0282   }
0283 
0284   // Start an asynchronous send. The data being sent must be valid for the
0285   // lifetime of the asynchronous operation.
0286   template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
0287   void async_send(base_implementation_type& impl,
0288       const ConstBufferSequence& buffers, socket_base::message_flags flags,
0289       Handler& handler, const IoExecutor& io_ex)
0290   {
0291     bool is_continuation =
0292       boost_asio_handler_cont_helpers::is_continuation(handler);
0293 
0294     associated_cancellation_slot_t<Handler> slot
0295       = boost::asio::get_associated_cancellation_slot(handler);
0296 
0297     // Allocate and construct an operation to wrap the handler.
0298     typedef reactive_socket_send_op<
0299         ConstBufferSequence, Handler, IoExecutor> op;
0300     typename op::ptr p = { boost::asio::detail::addressof(handler),
0301       op::ptr::allocate(handler), 0 };
0302     p.p = new (p.v) op(success_ec_, impl.socket_,
0303         impl.state_, buffers, flags, handler, io_ex);
0304 
0305     // Optionally register for per-operation cancellation.
0306     if (slot.is_connected())
0307     {
0308       p.p->cancellation_key_ =
0309         &slot.template emplace<reactor_op_cancellation>(
0310             &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);
0311     }
0312 
0313     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0314           &impl, impl.socket_, "async_send"));
0315 
0316     start_op(impl, reactor::write_op, p.p, is_continuation, true,
0317         ((impl.state_ & socket_ops::stream_oriented)
0318           && buffer_sequence_adapter<boost::asio::const_buffer,
0319             ConstBufferSequence>::all_empty(buffers)), true, &io_ex, 0);
0320     p.v = p.p = 0;
0321   }
0322 
0323   // Start an asynchronous wait until data can be sent without blocking.
0324   template <typename Handler, typename IoExecutor>
0325   void async_send(base_implementation_type& impl, const null_buffers&,
0326       socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
0327   {
0328     bool is_continuation =
0329       boost_asio_handler_cont_helpers::is_continuation(handler);
0330 
0331     associated_cancellation_slot_t<Handler> slot
0332       = boost::asio::get_associated_cancellation_slot(handler);
0333 
0334     // Allocate and construct an operation to wrap the handler.
0335     typedef reactive_null_buffers_op<Handler, IoExecutor> op;
0336     typename op::ptr p = { boost::asio::detail::addressof(handler),
0337       op::ptr::allocate(handler), 0 };
0338     p.p = new (p.v) op(success_ec_, handler, io_ex);
0339 
0340     // Optionally register for per-operation cancellation.
0341     if (slot.is_connected())
0342     {
0343       p.p->cancellation_key_ =
0344         &slot.template emplace<reactor_op_cancellation>(
0345             &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);
0346     }
0347 
0348     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0349           &impl, impl.socket_, "async_send(null_buffers)"));
0350 
0351     start_op(impl, reactor::write_op, p.p,
0352         is_continuation, false, false, false, &io_ex, 0);
0353     p.v = p.p = 0;
0354   }
0355 
0356   // Receive some data from the peer. Returns the number of bytes received.
0357   template <typename MutableBufferSequence>
0358   size_t receive(base_implementation_type& impl,
0359       const MutableBufferSequence& buffers,
0360       socket_base::message_flags flags, boost::system::error_code& ec)
0361   {
0362     typedef buffer_sequence_adapter<boost::asio::mutable_buffer,
0363         MutableBufferSequence> bufs_type;
0364 
0365     if (bufs_type::is_single_buffer)
0366     {
0367       return socket_ops::sync_recv1(impl.socket_,
0368           impl.state_, bufs_type::first(buffers).data(),
0369           bufs_type::first(buffers).size(), flags, ec);
0370     }
0371     else
0372     {
0373       bufs_type bufs(buffers);
0374       return socket_ops::sync_recv(impl.socket_, impl.state_,
0375           bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
0376     }
0377   }
0378 
0379   // Wait until data can be received without blocking.
0380   size_t receive(base_implementation_type& impl, const null_buffers&,
0381       socket_base::message_flags, boost::system::error_code& ec)
0382   {
0383     // Wait for socket to become ready.
0384     socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0385 
0386     return 0;
0387   }
0388 
0389   // Start an asynchronous receive. The buffer for the data being received
0390   // must be valid for the lifetime of the asynchronous operation.
0391   template <typename MutableBufferSequence,
0392       typename Handler, typename IoExecutor>
0393   void async_receive(base_implementation_type& impl,
0394       const MutableBufferSequence& buffers, socket_base::message_flags flags,
0395       Handler& handler, const IoExecutor& io_ex)
0396   {
0397     bool is_continuation =
0398       boost_asio_handler_cont_helpers::is_continuation(handler);
0399 
0400     associated_cancellation_slot_t<Handler> slot
0401       = boost::asio::get_associated_cancellation_slot(handler);
0402 
0403     // Allocate and construct an operation to wrap the handler.
0404     typedef reactive_socket_recv_op<
0405         MutableBufferSequence, Handler, IoExecutor> op;
0406     typename op::ptr p = { boost::asio::detail::addressof(handler),
0407       op::ptr::allocate(handler), 0 };
0408     p.p = new (p.v) op(success_ec_, impl.socket_,
0409         impl.state_, buffers, flags, handler, io_ex);
0410 
0411     // Optionally register for per-operation cancellation.
0412     if (slot.is_connected())
0413     {
0414       p.p->cancellation_key_ =
0415         &slot.template emplace<reactor_op_cancellation>(
0416             &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);
0417     }
0418 
0419     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0420           &impl, impl.socket_, "async_receive"));
0421 
0422     start_op(impl,
0423         (flags & socket_base::message_out_of_band)
0424           ? reactor::except_op : reactor::read_op,
0425         p.p, is_continuation,
0426         (flags & socket_base::message_out_of_band) == 0,
0427         ((impl.state_ & socket_ops::stream_oriented)
0428           && buffer_sequence_adapter<boost::asio::mutable_buffer,
0429             MutableBufferSequence>::all_empty(buffers)), true, &io_ex, 0);
0430     p.v = p.p = 0;
0431   }
0432 
0433   // Wait until data can be received without blocking.
0434   template <typename Handler, typename IoExecutor>
0435   void async_receive(base_implementation_type& impl,
0436       const null_buffers&, socket_base::message_flags flags,
0437       Handler& handler, const IoExecutor& io_ex)
0438   {
0439     bool is_continuation =
0440       boost_asio_handler_cont_helpers::is_continuation(handler);
0441 
0442     associated_cancellation_slot_t<Handler> slot
0443       = boost::asio::get_associated_cancellation_slot(handler);
0444 
0445     // Allocate and construct an operation to wrap the handler.
0446     typedef reactive_null_buffers_op<Handler, IoExecutor> op;
0447     typename op::ptr p = { boost::asio::detail::addressof(handler),
0448       op::ptr::allocate(handler), 0 };
0449     p.p = new (p.v) op(success_ec_, handler, io_ex);
0450 
0451     // Optionally register for per-operation cancellation.
0452     if (slot.is_connected())
0453     {
0454       p.p->cancellation_key_ =
0455         &slot.template emplace<reactor_op_cancellation>(
0456             &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);
0457     }
0458 
0459     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0460           &impl, impl.socket_, "async_receive(null_buffers)"));
0461 
0462     start_op(impl,
0463         (flags & socket_base::message_out_of_band)
0464           ? reactor::except_op : reactor::read_op,
0465         p.p, is_continuation, false, false, false, &io_ex, 0);
0466     p.v = p.p = 0;
0467   }
0468 
0469   // Receive some data with associated flags. Returns the number of bytes
0470   // received.
0471   template <typename MutableBufferSequence>
0472   size_t receive_with_flags(base_implementation_type& impl,
0473       const MutableBufferSequence& buffers,
0474       socket_base::message_flags in_flags,
0475       socket_base::message_flags& out_flags, boost::system::error_code& ec)
0476   {
0477     buffer_sequence_adapter<boost::asio::mutable_buffer,
0478         MutableBufferSequence> bufs(buffers);
0479 
0480     return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
0481         bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
0482   }
0483 
0484   // Wait until data can be received without blocking.
0485   size_t receive_with_flags(base_implementation_type& impl,
0486       const null_buffers&, socket_base::message_flags,
0487       socket_base::message_flags& out_flags, boost::system::error_code& ec)
0488   {
0489     // Wait for socket to become ready.
0490     socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0491 
0492     // Clear out_flags, since we cannot give it any other sensible value when
0493     // performing a null_buffers operation.
0494     out_flags = 0;
0495 
0496     return 0;
0497   }
0498 
0499   // Start an asynchronous receive. The buffer for the data being received
0500   // must be valid for the lifetime of the asynchronous operation.
0501   template <typename MutableBufferSequence,
0502       typename Handler, typename IoExecutor>
0503   void async_receive_with_flags(base_implementation_type& impl,
0504       const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
0505       socket_base::message_flags& out_flags, Handler& handler,
0506       const IoExecutor& io_ex)
0507   {
0508     bool is_continuation =
0509       boost_asio_handler_cont_helpers::is_continuation(handler);
0510 
0511     associated_cancellation_slot_t<Handler> slot
0512       = boost::asio::get_associated_cancellation_slot(handler);
0513 
0514     // Allocate and construct an operation to wrap the handler.
0515     typedef reactive_socket_recvmsg_op<
0516         MutableBufferSequence, Handler, IoExecutor> op;
0517     typename op::ptr p = { boost::asio::detail::addressof(handler),
0518       op::ptr::allocate(handler), 0 };
0519     p.p = new (p.v) op(success_ec_, impl.socket_,
0520         buffers, in_flags, out_flags, handler, io_ex);
0521 
0522     // Optionally register for per-operation cancellation.
0523     if (slot.is_connected())
0524     {
0525       p.p->cancellation_key_ =
0526         &slot.template emplace<reactor_op_cancellation>(
0527             &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);
0528     }
0529 
0530     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0531           &impl, impl.socket_, "async_receive_with_flags"));
0532 
0533     start_op(impl,
0534         (in_flags & socket_base::message_out_of_band)
0535           ? reactor::except_op : reactor::read_op,
0536         p.p, is_continuation,
0537         (in_flags & socket_base::message_out_of_band) == 0,
0538         false, true, &io_ex, 0);
0539     p.v = p.p = 0;
0540   }
0541 
0542   // Wait until data can be received without blocking.
0543   template <typename Handler, typename IoExecutor>
0544   void async_receive_with_flags(base_implementation_type& impl,
0545       const null_buffers&, socket_base::message_flags in_flags,
0546       socket_base::message_flags& out_flags, Handler& handler,
0547       const IoExecutor& io_ex)
0548   {
0549     bool is_continuation =
0550       boost_asio_handler_cont_helpers::is_continuation(handler);
0551 
0552     associated_cancellation_slot_t<Handler> slot
0553       = boost::asio::get_associated_cancellation_slot(handler);
0554 
0555     // Allocate and construct an operation to wrap the handler.
0556     typedef reactive_null_buffers_op<Handler, IoExecutor> op;
0557     typename op::ptr p = { boost::asio::detail::addressof(handler),
0558       op::ptr::allocate(handler), 0 };
0559     p.p = new (p.v) op(success_ec_, handler, io_ex);
0560 
0561     // Optionally register for per-operation cancellation.
0562     if (slot.is_connected())
0563     {
0564       p.p->cancellation_key_ =
0565         &slot.template emplace<reactor_op_cancellation>(
0566             &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);
0567     }
0568 
0569     BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
0570           &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
0571 
0572     // Clear out_flags, since we cannot give it any other sensible value when
0573     // performing a null_buffers operation.
0574     out_flags = 0;
0575 
0576     start_op(impl,
0577         (in_flags & socket_base::message_out_of_band)
0578           ? reactor::except_op : reactor::read_op,
0579         p.p, is_continuation, false, false, false, &io_ex, 0);
0580     p.v = p.p = 0;
0581   }
0582 
0583 protected:
0584   // Open a new socket implementation.
0585   BOOST_ASIO_DECL boost::system::error_code do_open(
0586       base_implementation_type& impl, int af,
0587       int type, int protocol, boost::system::error_code& ec);
0588 
0589   // Assign a native socket to a socket implementation.
0590   BOOST_ASIO_DECL boost::system::error_code do_assign(
0591       base_implementation_type& impl, int type,
0592       const native_handle_type& native_socket, boost::system::error_code& ec);
0593 
0594   // Start the asynchronous read or write operation.
0595   BOOST_ASIO_DECL void do_start_op(base_implementation_type& impl,
0596       int op_type, reactor_op* op, bool is_continuation,
0597       bool allow_speculative, bool noop, bool needs_non_blocking,
0598       void (*on_immediate)(operation* op, bool, const void*),
0599       const void* immediate_arg);
0600 
0601   // Start the asynchronous operation for handlers that are specialised for
0602   // immediate completion.
0603   template <typename Op>
0604   void start_op(base_implementation_type& impl, int op_type, Op* op,
0605       bool is_continuation, bool allow_speculative, bool noop,
0606       bool needs_non_blocking, const void* io_ex, ...)
0607   {
0608     return do_start_op(impl, op_type, op, is_continuation, allow_speculative,
0609         noop, needs_non_blocking, &Op::do_immediate, io_ex);
0610   }
0611 
0612   // Start the asynchronous operation for handlers that are not specialised for
0613   // immediate completion.
0614   template <typename Op>
0615   void start_op(base_implementation_type& impl, int op_type,
0616       Op* op, bool is_continuation, bool allow_speculative,
0617       bool noop, bool needs_non_blocking, const void*,
0618       enable_if_t<
0619         is_same<
0620           typename associated_immediate_executor<
0621             typename Op::handler_type,
0622             typename Op::io_executor_type
0623           >::asio_associated_immediate_executor_is_unspecialised,
0624           void
0625         >::value
0626       >*)
0627   {
0628     return do_start_op(impl, op_type, op, is_continuation,
0629         allow_speculative, noop, needs_non_blocking,
0630         &reactor::call_post_immediate_completion, &reactor_);
0631   }
0632 
0633   // Start the asynchronous accept operation.
0634   BOOST_ASIO_DECL void do_start_accept_op(base_implementation_type& impl,
0635       reactor_op* op, bool is_continuation, bool peer_is_open,
0636       void (*on_immediate)(operation* op, bool, const void*),
0637       const void* immediate_arg);
0638 
0639   // Start the asynchronous accept operation for handlers that are specialised
0640   // for immediate completion.
0641   template <typename Op>
0642   void start_accept_op(base_implementation_type& impl, Op* op,
0643       bool is_continuation, bool peer_is_open, const void* io_ex, ...)
0644   {
0645     return do_start_accept_op(impl, op, is_continuation,
0646         peer_is_open, &Op::do_immediate, io_ex);
0647   }
0648 
0649   // Start the asynchronous operation for handlers that are not specialised for
0650   // immediate completion.
0651   template <typename Op>
0652   void start_accept_op(base_implementation_type& impl, Op* op,
0653       bool is_continuation, bool peer_is_open, const void*,
0654       enable_if_t<
0655         is_same<
0656           typename associated_immediate_executor<
0657             typename Op::handler_type,
0658             typename Op::io_executor_type
0659           >::asio_associated_immediate_executor_is_unspecialised,
0660           void
0661         >::value
0662       >*)
0663   {
0664     return do_start_accept_op(impl, op, is_continuation, peer_is_open,
0665         &reactor::call_post_immediate_completion, &reactor_);
0666   }
0667 
0668   // Start the asynchronous connect operation.
0669   BOOST_ASIO_DECL void do_start_connect_op(base_implementation_type& impl,
0670       reactor_op* op, bool is_continuation, const void* addr, size_t addrlen,
0671       void (*on_immediate)(operation* op, bool, const void*),
0672       const void* immediate_arg);
0673 
0674   // Start the asynchronous operation for handlers that are specialised for
0675   // immediate completion.
0676   template <typename Op>
0677   void start_connect_op(base_implementation_type& impl,
0678       Op* op, bool is_continuation, const void* addr,
0679       size_t addrlen, const void* io_ex, ...)
0680   {
0681     return do_start_connect_op(impl, op, is_continuation,
0682         addr, addrlen, &Op::do_immediate, io_ex);
0683   }
0684 
0685   // Start the asynchronous operation for handlers that are not specialised for
0686   // immediate completion.
0687   template <typename Op>
0688   void start_connect_op(base_implementation_type& impl, Op* op,
0689       bool is_continuation, const void* addr, size_t addrlen, const void*,
0690       enable_if_t<
0691         is_same<
0692           typename associated_immediate_executor<
0693             typename Op::handler_type,
0694             typename Op::io_executor_type
0695           >::asio_associated_immediate_executor_is_unspecialised,
0696           void
0697         >::value
0698       >*)
0699   {
0700     return do_start_connect_op(impl, op, is_continuation, addr,
0701         addrlen, &reactor::call_post_immediate_completion, &reactor_);
0702   }
0703 
0704   // Helper class used to implement per-operation cancellation
0705   class reactor_op_cancellation
0706   {
0707   public:
0708     reactor_op_cancellation(reactor* r,
0709         reactor::per_descriptor_data* p, socket_type d, int o)
0710       : reactor_(r),
0711         reactor_data_(p),
0712         descriptor_(d),
0713         op_type_(o)
0714     {
0715     }
0716 
0717     void operator()(cancellation_type_t type)
0718     {
0719       if (!!(type &
0720             (cancellation_type::terminal
0721               | cancellation_type::partial
0722               | cancellation_type::total)))
0723       {
0724         reactor_->cancel_ops_by_key(descriptor_,
0725             *reactor_data_, op_type_, this);
0726       }
0727     }
0728 
0729   private:
0730     reactor* reactor_;
0731     reactor::per_descriptor_data* reactor_data_;
0732     socket_type descriptor_;
0733     int op_type_;
0734   };
0735 
0736   // The selector that performs event demultiplexing for the service.
0737   reactor& reactor_;
0738 
0739   // Cached success value to avoid accessing category singleton.
0740   const boost::system::error_code success_ec_;
0741 };
0742 
0743 } // namespace detail
0744 } // namespace asio
0745 } // namespace boost
0746 
0747 #include <boost/asio/detail/pop_options.hpp>
0748 
0749 #if defined(BOOST_ASIO_HEADER_ONLY)
0750 # include <boost/asio/detail/impl/reactive_socket_service_base.ipp>
0751 #endif // defined(BOOST_ASIO_HEADER_ONLY)
0752 
0753 #endif // !defined(BOOST_ASIO_HAS_IOCP)
0754        //   && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
0755        //   && !defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0756 
0757 #endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP