Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:05

0001 //
0002 // basic_socket.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_BASIC_SOCKET_HPP
0012 #define BOOST_ASIO_BASIC_SOCKET_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <utility>
0019 #include <boost/asio/any_io_executor.hpp>
0020 #include <boost/asio/detail/config.hpp>
0021 #include <boost/asio/async_result.hpp>
0022 #include <boost/asio/detail/handler_type_requirements.hpp>
0023 #include <boost/asio/detail/io_object_impl.hpp>
0024 #include <boost/asio/detail/non_const_lvalue.hpp>
0025 #include <boost/asio/detail/throw_error.hpp>
0026 #include <boost/asio/detail/type_traits.hpp>
0027 #include <boost/asio/error.hpp>
0028 #include <boost/asio/execution_context.hpp>
0029 #include <boost/asio/post.hpp>
0030 #include <boost/asio/socket_base.hpp>
0031 
0032 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0033 # include <boost/asio/detail/null_socket_service.hpp>
0034 #elif defined(BOOST_ASIO_HAS_IOCP)
0035 # include <boost/asio/detail/win_iocp_socket_service.hpp>
0036 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0037 # include <boost/asio/detail/io_uring_socket_service.hpp>
0038 #else
0039 # include <boost/asio/detail/reactive_socket_service.hpp>
0040 #endif
0041 
0042 #include <boost/asio/detail/push_options.hpp>
0043 
0044 namespace boost {
0045 namespace asio {
0046 
0047 #if !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL)
0048 #define BOOST_ASIO_BASIC_SOCKET_FWD_DECL
0049 
0050 // Forward declaration with defaulted arguments.
0051 template <typename Protocol, typename Executor = any_io_executor>
0052 class basic_socket;
0053 
0054 #endif // !defined(BOOST_ASIO_BASIC_SOCKET_FWD_DECL)
0055 
0056 /// Provides socket functionality.
0057 /**
0058  * The basic_socket class template provides functionality that is common to both
0059  * stream-oriented and datagram-oriented sockets.
0060  *
0061  * @par Thread Safety
0062  * @e Distinct @e objects: Safe.@n
0063  * @e Shared @e objects: Unsafe.
0064  */
0065 template <typename Protocol, typename Executor>
0066 class basic_socket
0067   : public socket_base
0068 {
0069 private:
0070   class initiate_async_connect;
0071   class initiate_async_wait;
0072 
0073 public:
0074   /// The type of the executor associated with the object.
0075   typedef Executor executor_type;
0076 
0077   /// Rebinds the socket type to another executor.
0078   template <typename Executor1>
0079   struct rebind_executor
0080   {
0081     /// The socket type when rebound to the specified executor.
0082     typedef basic_socket<Protocol, Executor1> other;
0083   };
0084 
0085   /// The native representation of a socket.
0086 #if defined(GENERATING_DOCUMENTATION)
0087   typedef implementation_defined native_handle_type;
0088 #elif defined(BOOST_ASIO_WINDOWS_RUNTIME)
0089   typedef typename detail::null_socket_service<
0090     Protocol>::native_handle_type native_handle_type;
0091 #elif defined(BOOST_ASIO_HAS_IOCP)
0092   typedef typename detail::win_iocp_socket_service<
0093     Protocol>::native_handle_type native_handle_type;
0094 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0095   typedef typename detail::io_uring_socket_service<
0096     Protocol>::native_handle_type native_handle_type;
0097 #else
0098   typedef typename detail::reactive_socket_service<
0099     Protocol>::native_handle_type native_handle_type;
0100 #endif
0101 
0102   /// The protocol type.
0103   typedef Protocol protocol_type;
0104 
0105   /// The endpoint type.
0106   typedef typename Protocol::endpoint endpoint_type;
0107 
0108 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0109   /// A basic_socket is always the lowest layer.
0110   typedef basic_socket<Protocol, Executor> lowest_layer_type;
0111 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0112 
0113   /// Construct a basic_socket without opening it.
0114   /**
0115    * This constructor creates a socket without opening it.
0116    *
0117    * @param ex The I/O executor that the socket will use, by default, to
0118    * dispatch handlers for any asynchronous operations performed on the socket.
0119    */
0120   explicit basic_socket(const executor_type& ex)
0121     : impl_(0, ex)
0122   {
0123   }
0124 
0125   /// Construct a basic_socket without opening it.
0126   /**
0127    * This constructor creates a socket without opening it.
0128    *
0129    * @param context An execution context which provides the I/O executor that
0130    * the socket will use, by default, to dispatch handlers for any asynchronous
0131    * operations performed on the socket.
0132    */
0133   template <typename ExecutionContext>
0134   explicit basic_socket(ExecutionContext& context,
0135       constraint_t<
0136         is_convertible<ExecutionContext&, execution_context&>::value
0137       > = 0)
0138     : impl_(0, 0, context)
0139   {
0140   }
0141 
0142   /// Construct and open a basic_socket.
0143   /**
0144    * This constructor creates and opens a socket.
0145    *
0146    * @param ex The I/O executor that the socket will use, by default, to
0147    * dispatch handlers for any asynchronous operations performed on the socket.
0148    *
0149    * @param protocol An object specifying protocol parameters to be used.
0150    *
0151    * @throws boost::system::system_error Thrown on failure.
0152    */
0153   basic_socket(const executor_type& ex, const protocol_type& protocol)
0154     : impl_(0, ex)
0155   {
0156     boost::system::error_code ec;
0157     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
0158     boost::asio::detail::throw_error(ec, "open");
0159   }
0160 
0161   /// Construct and open a basic_socket.
0162   /**
0163    * This constructor creates and opens a socket.
0164    *
0165    * @param context An execution context which provides the I/O executor that
0166    * the socket will use, by default, to dispatch handlers for any asynchronous
0167    * operations performed on the socket.
0168    *
0169    * @param protocol An object specifying protocol parameters to be used.
0170    *
0171    * @throws boost::system::system_error Thrown on failure.
0172    */
0173   template <typename ExecutionContext>
0174   basic_socket(ExecutionContext& context, const protocol_type& protocol,
0175       constraint_t<
0176         is_convertible<ExecutionContext&, execution_context&>::value,
0177         defaulted_constraint
0178       > = defaulted_constraint())
0179     : impl_(0, 0, context)
0180   {
0181     boost::system::error_code ec;
0182     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
0183     boost::asio::detail::throw_error(ec, "open");
0184   }
0185 
0186   /// Construct a basic_socket, opening it and binding it to the given local
0187   /// endpoint.
0188   /**
0189    * This constructor creates a socket and automatically opens it bound to the
0190    * specified endpoint on the local machine. The protocol used is the protocol
0191    * associated with the given endpoint.
0192    *
0193    * @param ex The I/O executor that the socket will use, by default, to
0194    * dispatch handlers for any asynchronous operations performed on the socket.
0195    *
0196    * @param endpoint An endpoint on the local machine to which the socket will
0197    * be bound.
0198    *
0199    * @throws boost::system::system_error Thrown on failure.
0200    */
0201   basic_socket(const executor_type& ex, const endpoint_type& endpoint)
0202     : impl_(0, ex)
0203   {
0204     boost::system::error_code ec;
0205     const protocol_type protocol = endpoint.protocol();
0206     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
0207     boost::asio::detail::throw_error(ec, "open");
0208     impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
0209     boost::asio::detail::throw_error(ec, "bind");
0210   }
0211 
0212   /// Construct a basic_socket, opening it and binding it to the given local
0213   /// endpoint.
0214   /**
0215    * This constructor creates a socket and automatically opens it bound to the
0216    * specified endpoint on the local machine. The protocol used is the protocol
0217    * associated with the given endpoint.
0218    *
0219    * @param context An execution context which provides the I/O executor that
0220    * the socket will use, by default, to dispatch handlers for any asynchronous
0221    * operations performed on the socket.
0222    *
0223    * @param endpoint An endpoint on the local machine to which the socket will
0224    * be bound.
0225    *
0226    * @throws boost::system::system_error Thrown on failure.
0227    */
0228   template <typename ExecutionContext>
0229   basic_socket(ExecutionContext& context, const endpoint_type& endpoint,
0230       constraint_t<
0231         is_convertible<ExecutionContext&, execution_context&>::value
0232       > = 0)
0233     : impl_(0, 0, context)
0234   {
0235     boost::system::error_code ec;
0236     const protocol_type protocol = endpoint.protocol();
0237     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
0238     boost::asio::detail::throw_error(ec, "open");
0239     impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
0240     boost::asio::detail::throw_error(ec, "bind");
0241   }
0242 
0243   /// Construct a basic_socket on an existing native socket.
0244   /**
0245    * This constructor creates a socket object to hold an existing native socket.
0246    *
0247    * @param ex The I/O executor that the socket will use, by default, to
0248    * dispatch handlers for any asynchronous operations performed on the socket.
0249    *
0250    * @param protocol An object specifying protocol parameters to be used.
0251    *
0252    * @param native_socket A native socket.
0253    *
0254    * @throws boost::system::system_error Thrown on failure.
0255    */
0256   basic_socket(const executor_type& ex, const protocol_type& protocol,
0257       const native_handle_type& native_socket)
0258     : impl_(0, ex)
0259   {
0260     boost::system::error_code ec;
0261     impl_.get_service().assign(impl_.get_implementation(),
0262         protocol, native_socket, ec);
0263     boost::asio::detail::throw_error(ec, "assign");
0264   }
0265 
0266   /// Construct a basic_socket on an existing native socket.
0267   /**
0268    * This constructor creates a socket object to hold an existing native socket.
0269    *
0270    * @param context An execution context which provides the I/O executor that
0271    * the socket will use, by default, to dispatch handlers for any asynchronous
0272    * operations performed on the socket.
0273    *
0274    * @param protocol An object specifying protocol parameters to be used.
0275    *
0276    * @param native_socket A native socket.
0277    *
0278    * @throws boost::system::system_error Thrown on failure.
0279    */
0280   template <typename ExecutionContext>
0281   basic_socket(ExecutionContext& context, const protocol_type& protocol,
0282       const native_handle_type& native_socket,
0283       constraint_t<
0284         is_convertible<ExecutionContext&, execution_context&>::value
0285       > = 0)
0286     : impl_(0, 0, context)
0287   {
0288     boost::system::error_code ec;
0289     impl_.get_service().assign(impl_.get_implementation(),
0290         protocol, native_socket, ec);
0291     boost::asio::detail::throw_error(ec, "assign");
0292   }
0293 
0294   /// Move-construct a basic_socket from another.
0295   /**
0296    * This constructor moves a socket from one object to another.
0297    *
0298    * @param other The other basic_socket object from which the move will
0299    * occur.
0300    *
0301    * @note Following the move, the moved-from object is in the same state as if
0302    * constructed using the @c basic_socket(const executor_type&) constructor.
0303    */
0304   basic_socket(basic_socket&& other) noexcept
0305     : impl_(std::move(other.impl_))
0306   {
0307   }
0308 
0309   /// Move-assign a basic_socket from another.
0310   /**
0311    * This assignment operator moves a socket from one object to another.
0312    *
0313    * @param other The other basic_socket object from which the move will
0314    * occur.
0315    *
0316    * @note Following the move, the moved-from object is in the same state as if
0317    * constructed using the @c basic_socket(const executor_type&) constructor.
0318    */
0319   basic_socket& operator=(basic_socket&& other)
0320   {
0321     impl_ = std::move(other.impl_);
0322     return *this;
0323   }
0324 
0325   // All sockets have access to each other's implementations.
0326   template <typename Protocol1, typename Executor1>
0327   friend class basic_socket;
0328 
0329   /// Move-construct a basic_socket from a socket of another protocol type.
0330   /**
0331    * This constructor moves a socket from one object to another.
0332    *
0333    * @param other The other basic_socket object from which the move will
0334    * occur.
0335    *
0336    * @note Following the move, the moved-from object is in the same state as if
0337    * constructed using the @c basic_socket(const executor_type&) constructor.
0338    */
0339   template <typename Protocol1, typename Executor1>
0340   basic_socket(basic_socket<Protocol1, Executor1>&& other,
0341       constraint_t<
0342         is_convertible<Protocol1, Protocol>::value
0343           && is_convertible<Executor1, Executor>::value
0344       > = 0)
0345     : impl_(std::move(other.impl_))
0346   {
0347   }
0348 
0349   /// Move-assign a basic_socket from a socket of another protocol type.
0350   /**
0351    * This assignment operator moves a socket from one object to another.
0352    *
0353    * @param other The other basic_socket object from which the move will
0354    * occur.
0355    *
0356    * @note Following the move, the moved-from object is in the same state as if
0357    * constructed using the @c basic_socket(const executor_type&) constructor.
0358    */
0359   template <typename Protocol1, typename Executor1>
0360   constraint_t<
0361     is_convertible<Protocol1, Protocol>::value
0362       && is_convertible<Executor1, Executor>::value,
0363     basic_socket&
0364   > operator=(basic_socket<Protocol1, Executor1>&& other)
0365   {
0366     basic_socket tmp(std::move(other));
0367     impl_ = std::move(tmp.impl_);
0368     return *this;
0369   }
0370 
0371   /// Get the executor associated with the object.
0372   const executor_type& get_executor() noexcept
0373   {
0374     return impl_.get_executor();
0375   }
0376 
0377 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0378   /// Get a reference to the lowest layer.
0379   /**
0380    * This function returns a reference to the lowest layer in a stack of
0381    * layers. Since a basic_socket cannot contain any further layers, it simply
0382    * returns a reference to itself.
0383    *
0384    * @return A reference to the lowest layer in the stack of layers. Ownership
0385    * is not transferred to the caller.
0386    */
0387   lowest_layer_type& lowest_layer()
0388   {
0389     return *this;
0390   }
0391 
0392   /// Get a const reference to the lowest layer.
0393   /**
0394    * This function returns a const reference to the lowest layer in a stack of
0395    * layers. Since a basic_socket cannot contain any further layers, it simply
0396    * returns a reference to itself.
0397    *
0398    * @return A const reference to the lowest layer in the stack of layers.
0399    * Ownership is not transferred to the caller.
0400    */
0401   const lowest_layer_type& lowest_layer() const
0402   {
0403     return *this;
0404   }
0405 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0406 
0407   /// Open the socket using the specified protocol.
0408   /**
0409    * This function opens the socket so that it will use the specified protocol.
0410    *
0411    * @param protocol An object specifying protocol parameters to be used.
0412    *
0413    * @throws boost::system::system_error Thrown on failure.
0414    *
0415    * @par Example
0416    * @code
0417    * boost::asio::ip::tcp::socket socket(my_context);
0418    * socket.open(boost::asio::ip::tcp::v4());
0419    * @endcode
0420    */
0421   void open(const protocol_type& protocol = protocol_type())
0422   {
0423     boost::system::error_code ec;
0424     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
0425     boost::asio::detail::throw_error(ec, "open");
0426   }
0427 
0428   /// Open the socket using the specified protocol.
0429   /**
0430    * This function opens the socket so that it will use the specified protocol.
0431    *
0432    * @param protocol An object specifying which protocol is to be used.
0433    *
0434    * @param ec Set to indicate what error occurred, if any.
0435    *
0436    * @par Example
0437    * @code
0438    * boost::asio::ip::tcp::socket socket(my_context);
0439    * boost::system::error_code ec;
0440    * socket.open(boost::asio::ip::tcp::v4(), ec);
0441    * if (ec)
0442    * {
0443    *   // An error occurred.
0444    * }
0445    * @endcode
0446    */
0447   BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
0448       boost::system::error_code& ec)
0449   {
0450     impl_.get_service().open(impl_.get_implementation(), protocol, ec);
0451     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0452   }
0453 
0454   /// Assign an existing native socket to the socket.
0455   /*
0456    * This function opens the socket to hold an existing native socket.
0457    *
0458    * @param protocol An object specifying which protocol is to be used.
0459    *
0460    * @param native_socket A native socket.
0461    *
0462    * @throws boost::system::system_error Thrown on failure.
0463    */
0464   void assign(const protocol_type& protocol,
0465       const native_handle_type& native_socket)
0466   {
0467     boost::system::error_code ec;
0468     impl_.get_service().assign(impl_.get_implementation(),
0469         protocol, native_socket, ec);
0470     boost::asio::detail::throw_error(ec, "assign");
0471   }
0472 
0473   /// Assign an existing native socket to the socket.
0474   /*
0475    * This function opens the socket to hold an existing native socket.
0476    *
0477    * @param protocol An object specifying which protocol is to be used.
0478    *
0479    * @param native_socket A native socket.
0480    *
0481    * @param ec Set to indicate what error occurred, if any.
0482    */
0483   BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
0484       const native_handle_type& native_socket, boost::system::error_code& ec)
0485   {
0486     impl_.get_service().assign(impl_.get_implementation(),
0487         protocol, native_socket, ec);
0488     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0489   }
0490 
0491   /// Determine whether the socket is open.
0492   bool is_open() const
0493   {
0494     return impl_.get_service().is_open(impl_.get_implementation());
0495   }
0496 
0497   /// Close the socket.
0498   /**
0499    * This function is used to close the socket. Any asynchronous send, receive
0500    * or connect operations will be cancelled immediately, and will complete
0501    * with the boost::asio::error::operation_aborted error.
0502    *
0503    * @throws boost::system::system_error Thrown on failure. Note that, even if
0504    * the function indicates an error, the underlying descriptor is closed.
0505    *
0506    * @note For portable behaviour with respect to graceful closure of a
0507    * connected socket, call shutdown() before closing the socket.
0508    */
0509   void close()
0510   {
0511     boost::system::error_code ec;
0512     impl_.get_service().close(impl_.get_implementation(), ec);
0513     boost::asio::detail::throw_error(ec, "close");
0514   }
0515 
0516   /// Close the socket.
0517   /**
0518    * This function is used to close the socket. Any asynchronous send, receive
0519    * or connect operations will be cancelled immediately, and will complete
0520    * with the boost::asio::error::operation_aborted error.
0521    *
0522    * @param ec Set to indicate what error occurred, if any. Note that, even if
0523    * the function indicates an error, the underlying descriptor is closed.
0524    *
0525    * @par Example
0526    * @code
0527    * boost::asio::ip::tcp::socket socket(my_context);
0528    * ...
0529    * boost::system::error_code ec;
0530    * socket.close(ec);
0531    * if (ec)
0532    * {
0533    *   // An error occurred.
0534    * }
0535    * @endcode
0536    *
0537    * @note For portable behaviour with respect to graceful closure of a
0538    * connected socket, call shutdown() before closing the socket.
0539    */
0540   BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
0541   {
0542     impl_.get_service().close(impl_.get_implementation(), ec);
0543     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0544   }
0545 
0546   /// Release ownership of the underlying native socket.
0547   /**
0548    * This function causes all outstanding asynchronous connect, send and receive
0549    * operations to finish immediately, and the handlers for cancelled operations
0550    * will be passed the boost::asio::error::operation_aborted error. Ownership
0551    * of the native socket is then transferred to the caller.
0552    *
0553    * @throws boost::system::system_error Thrown on failure.
0554    *
0555    * @note This function is unsupported on Windows versions prior to Windows
0556    * 8.1, and will fail with boost::asio::error::operation_not_supported on
0557    * these platforms.
0558    */
0559 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
0560   && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
0561   __declspec(deprecated("This function always fails with "
0562         "operation_not_supported when used on Windows versions "
0563         "prior to Windows 8.1."))
0564 #endif
0565   native_handle_type release()
0566   {
0567     boost::system::error_code ec;
0568     native_handle_type s = impl_.get_service().release(
0569         impl_.get_implementation(), ec);
0570     boost::asio::detail::throw_error(ec, "release");
0571     return s;
0572   }
0573 
0574   /// Release ownership of the underlying native socket.
0575   /**
0576    * This function causes all outstanding asynchronous connect, send and receive
0577    * operations to finish immediately, and the handlers for cancelled operations
0578    * will be passed the boost::asio::error::operation_aborted error. Ownership
0579    * of the native socket is then transferred to the caller.
0580    *
0581    * @param ec Set to indicate what error occurred, if any.
0582    *
0583    * @note This function is unsupported on Windows versions prior to Windows
0584    * 8.1, and will fail with boost::asio::error::operation_not_supported on
0585    * these platforms.
0586    */
0587 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
0588   && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
0589   __declspec(deprecated("This function always fails with "
0590         "operation_not_supported when used on Windows versions "
0591         "prior to Windows 8.1."))
0592 #endif
0593   native_handle_type release(boost::system::error_code& ec)
0594   {
0595     return impl_.get_service().release(impl_.get_implementation(), ec);
0596   }
0597 
0598   /// Get the native socket representation.
0599   /**
0600    * This function may be used to obtain the underlying representation of the
0601    * socket. This is intended to allow access to native socket functionality
0602    * that is not otherwise provided.
0603    */
0604   native_handle_type native_handle()
0605   {
0606     return impl_.get_service().native_handle(impl_.get_implementation());
0607   }
0608 
0609   /// Cancel all asynchronous operations associated with the socket.
0610   /**
0611    * This function causes all outstanding asynchronous connect, send and receive
0612    * operations to finish immediately, and the handlers for cancelled operations
0613    * will be passed the boost::asio::error::operation_aborted error.
0614    *
0615    * @throws boost::system::system_error Thrown on failure.
0616    *
0617    * @note Calls to cancel() will always fail with
0618    * boost::asio::error::operation_not_supported when run on Windows XP, Windows
0619    * Server 2003, and earlier versions of Windows, unless
0620    * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
0621    * two issues that should be considered before enabling its use:
0622    *
0623    * @li It will only cancel asynchronous operations that were initiated in the
0624    * current thread.
0625    *
0626    * @li It can appear to complete without error, but the request to cancel the
0627    * unfinished operations may be silently ignored by the operating system.
0628    * Whether it works or not seems to depend on the drivers that are installed.
0629    *
0630    * For portable cancellation, consider using one of the following
0631    * alternatives:
0632    *
0633    * @li Disable asio's I/O completion port backend by defining
0634    * BOOST_ASIO_DISABLE_IOCP.
0635    *
0636    * @li Use the close() function to simultaneously cancel the outstanding
0637    * operations and close the socket.
0638    *
0639    * When running on Windows Vista, Windows Server 2008, and later, the
0640    * CancelIoEx function is always used. This function does not have the
0641    * problems described above.
0642    */
0643 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
0644   && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
0645   && !defined(BOOST_ASIO_ENABLE_CANCELIO)
0646   __declspec(deprecated("By default, this function always fails with "
0647         "operation_not_supported when used on Windows XP, Windows Server 2003, "
0648         "or earlier. Consult documentation for details."))
0649 #endif
0650   void cancel()
0651   {
0652     boost::system::error_code ec;
0653     impl_.get_service().cancel(impl_.get_implementation(), ec);
0654     boost::asio::detail::throw_error(ec, "cancel");
0655   }
0656 
0657   /// Cancel all asynchronous operations associated with the socket.
0658   /**
0659    * This function causes all outstanding asynchronous connect, send and receive
0660    * operations to finish immediately, and the handlers for cancelled operations
0661    * will be passed the boost::asio::error::operation_aborted error.
0662    *
0663    * @param ec Set to indicate what error occurred, if any.
0664    *
0665    * @note Calls to cancel() will always fail with
0666    * boost::asio::error::operation_not_supported when run on Windows XP, Windows
0667    * Server 2003, and earlier versions of Windows, unless
0668    * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
0669    * two issues that should be considered before enabling its use:
0670    *
0671    * @li It will only cancel asynchronous operations that were initiated in the
0672    * current thread.
0673    *
0674    * @li It can appear to complete without error, but the request to cancel the
0675    * unfinished operations may be silently ignored by the operating system.
0676    * Whether it works or not seems to depend on the drivers that are installed.
0677    *
0678    * For portable cancellation, consider using one of the following
0679    * alternatives:
0680    *
0681    * @li Disable asio's I/O completion port backend by defining
0682    * BOOST_ASIO_DISABLE_IOCP.
0683    *
0684    * @li Use the close() function to simultaneously cancel the outstanding
0685    * operations and close the socket.
0686    *
0687    * When running on Windows Vista, Windows Server 2008, and later, the
0688    * CancelIoEx function is always used. This function does not have the
0689    * problems described above.
0690    */
0691 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
0692   && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
0693   && !defined(BOOST_ASIO_ENABLE_CANCELIO)
0694   __declspec(deprecated("By default, this function always fails with "
0695         "operation_not_supported when used on Windows XP, Windows Server 2003, "
0696         "or earlier. Consult documentation for details."))
0697 #endif
0698   BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
0699   {
0700     impl_.get_service().cancel(impl_.get_implementation(), ec);
0701     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0702   }
0703 
0704   /// Determine whether the socket is at the out-of-band data mark.
0705   /**
0706    * This function is used to check whether the socket input is currently
0707    * positioned at the out-of-band data mark.
0708    *
0709    * @return A bool indicating whether the socket is at the out-of-band data
0710    * mark.
0711    *
0712    * @throws boost::system::system_error Thrown on failure.
0713    */
0714   bool at_mark() const
0715   {
0716     boost::system::error_code ec;
0717     bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec);
0718     boost::asio::detail::throw_error(ec, "at_mark");
0719     return b;
0720   }
0721 
0722   /// Determine whether the socket is at the out-of-band data mark.
0723   /**
0724    * This function is used to check whether the socket input is currently
0725    * positioned at the out-of-band data mark.
0726    *
0727    * @param ec Set to indicate what error occurred, if any.
0728    *
0729    * @return A bool indicating whether the socket is at the out-of-band data
0730    * mark.
0731    */
0732   bool at_mark(boost::system::error_code& ec) const
0733   {
0734     return impl_.get_service().at_mark(impl_.get_implementation(), ec);
0735   }
0736 
0737   /// Determine the number of bytes available for reading.
0738   /**
0739    * This function is used to determine the number of bytes that may be read
0740    * without blocking.
0741    *
0742    * @return The number of bytes that may be read without blocking, or 0 if an
0743    * error occurs.
0744    *
0745    * @throws boost::system::system_error Thrown on failure.
0746    */
0747   std::size_t available() const
0748   {
0749     boost::system::error_code ec;
0750     std::size_t s = impl_.get_service().available(
0751         impl_.get_implementation(), ec);
0752     boost::asio::detail::throw_error(ec, "available");
0753     return s;
0754   }
0755 
0756   /// Determine the number of bytes available for reading.
0757   /**
0758    * This function is used to determine the number of bytes that may be read
0759    * without blocking.
0760    *
0761    * @param ec Set to indicate what error occurred, if any.
0762    *
0763    * @return The number of bytes that may be read without blocking, or 0 if an
0764    * error occurs.
0765    */
0766   std::size_t available(boost::system::error_code& ec) const
0767   {
0768     return impl_.get_service().available(impl_.get_implementation(), ec);
0769   }
0770 
0771   /// Bind the socket to the given local endpoint.
0772   /**
0773    * This function binds the socket to the specified endpoint on the local
0774    * machine.
0775    *
0776    * @param endpoint An endpoint on the local machine to which the socket will
0777    * be bound.
0778    *
0779    * @throws boost::system::system_error Thrown on failure.
0780    *
0781    * @par Example
0782    * @code
0783    * boost::asio::ip::tcp::socket socket(my_context);
0784    * socket.open(boost::asio::ip::tcp::v4());
0785    * socket.bind(boost::asio::ip::tcp::endpoint(
0786    *       boost::asio::ip::tcp::v4(), 12345));
0787    * @endcode
0788    */
0789   void bind(const endpoint_type& endpoint)
0790   {
0791     boost::system::error_code ec;
0792     impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
0793     boost::asio::detail::throw_error(ec, "bind");
0794   }
0795 
0796   /// Bind the socket to the given local endpoint.
0797   /**
0798    * This function binds the socket to the specified endpoint on the local
0799    * machine.
0800    *
0801    * @param endpoint An endpoint on the local machine to which the socket will
0802    * be bound.
0803    *
0804    * @param ec Set to indicate what error occurred, if any.
0805    *
0806    * @par Example
0807    * @code
0808    * boost::asio::ip::tcp::socket socket(my_context);
0809    * socket.open(boost::asio::ip::tcp::v4());
0810    * boost::system::error_code ec;
0811    * socket.bind(boost::asio::ip::tcp::endpoint(
0812    *       boost::asio::ip::tcp::v4(), 12345), ec);
0813    * if (ec)
0814    * {
0815    *   // An error occurred.
0816    * }
0817    * @endcode
0818    */
0819   BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
0820       boost::system::error_code& ec)
0821   {
0822     impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
0823     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0824   }
0825 
0826   /// Connect the socket to the specified endpoint.
0827   /**
0828    * This function is used to connect a socket to the specified remote endpoint.
0829    * The function call will block until the connection is successfully made or
0830    * an error occurs.
0831    *
0832    * The socket is automatically opened if it is not already open. If the
0833    * connect fails, and the socket was automatically opened, the socket is
0834    * not returned to the closed state.
0835    *
0836    * @param peer_endpoint The remote endpoint to which the socket will be
0837    * connected.
0838    *
0839    * @throws boost::system::system_error Thrown on failure.
0840    *
0841    * @par Example
0842    * @code
0843    * boost::asio::ip::tcp::socket socket(my_context);
0844    * boost::asio::ip::tcp::endpoint endpoint(
0845    *     boost::asio::ip::address::from_string("1.2.3.4"), 12345);
0846    * socket.connect(endpoint);
0847    * @endcode
0848    */
0849   void connect(const endpoint_type& peer_endpoint)
0850   {
0851     boost::system::error_code ec;
0852     if (!is_open())
0853     {
0854       impl_.get_service().open(impl_.get_implementation(),
0855           peer_endpoint.protocol(), ec);
0856       boost::asio::detail::throw_error(ec, "connect");
0857     }
0858     impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);
0859     boost::asio::detail::throw_error(ec, "connect");
0860   }
0861 
0862   /// Connect the socket to the specified endpoint.
0863   /**
0864    * This function is used to connect a socket to the specified remote endpoint.
0865    * The function call will block until the connection is successfully made or
0866    * an error occurs.
0867    *
0868    * The socket is automatically opened if it is not already open. If the
0869    * connect fails, and the socket was automatically opened, the socket is
0870    * not returned to the closed state.
0871    *
0872    * @param peer_endpoint The remote endpoint to which the socket will be
0873    * connected.
0874    *
0875    * @param ec Set to indicate what error occurred, if any.
0876    *
0877    * @par Example
0878    * @code
0879    * boost::asio::ip::tcp::socket socket(my_context);
0880    * boost::asio::ip::tcp::endpoint endpoint(
0881    *     boost::asio::ip::address::from_string("1.2.3.4"), 12345);
0882    * boost::system::error_code ec;
0883    * socket.connect(endpoint, ec);
0884    * if (ec)
0885    * {
0886    *   // An error occurred.
0887    * }
0888    * @endcode
0889    */
0890   BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint,
0891       boost::system::error_code& ec)
0892   {
0893     if (!is_open())
0894     {
0895       impl_.get_service().open(impl_.get_implementation(),
0896             peer_endpoint.protocol(), ec);
0897       if (ec)
0898       {
0899         BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0900       }
0901     }
0902 
0903     impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);
0904     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
0905   }
0906 
0907   /// Start an asynchronous connect.
0908   /**
0909    * This function is used to asynchronously connect a socket to the specified
0910    * remote endpoint. It is an initiating function for an @ref
0911    * asynchronous_operation, and always returns immediately.
0912    *
0913    * The socket is automatically opened if it is not already open. If the
0914    * connect fails, and the socket was automatically opened, the socket is
0915    * not returned to the closed state.
0916    *
0917    * @param peer_endpoint The remote endpoint to which the socket will be
0918    * connected. Copies will be made of the endpoint object as required.
0919    *
0920    * @param token The @ref completion_token that will be used to produce a
0921    * completion handler, which will be called when the connect completes.
0922    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0923    * @ref yield_context, or a function object with the correct completion
0924    * signature. The function signature of the completion handler must be:
0925    * @code void handler(
0926    *   const boost::system::error_code& error // Result of operation.
0927    * ); @endcode
0928    * Regardless of whether the asynchronous operation completes immediately or
0929    * not, the completion handler will not be invoked from within this function.
0930    * On immediate completion, invocation of the handler will be performed in a
0931    * manner equivalent to using boost::asio::post().
0932    *
0933    * @par Completion Signature
0934    * @code void(boost::system::error_code) @endcode
0935    *
0936    * @par Example
0937    * @code
0938    * void connect_handler(const boost::system::error_code& error)
0939    * {
0940    *   if (!error)
0941    *   {
0942    *     // Connect succeeded.
0943    *   }
0944    * }
0945    *
0946    * ...
0947    *
0948    * boost::asio::ip::tcp::socket socket(my_context);
0949    * boost::asio::ip::tcp::endpoint endpoint(
0950    *     boost::asio::ip::address::from_string("1.2.3.4"), 12345);
0951    * socket.async_connect(endpoint, connect_handler);
0952    * @endcode
0953    *
0954    * @par Per-Operation Cancellation
0955    * On POSIX or Windows operating systems, this asynchronous operation supports
0956    * cancellation for the following boost::asio::cancellation_type values:
0957    *
0958    * @li @c cancellation_type::terminal
0959    *
0960    * @li @c cancellation_type::partial
0961    *
0962    * @li @c cancellation_type::total
0963    */
0964   template <
0965       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
0966         ConnectToken = default_completion_token_t<executor_type>>
0967   auto async_connect(const endpoint_type& peer_endpoint,
0968       ConnectToken&& token = default_completion_token_t<executor_type>())
0969     -> decltype(
0970       async_initiate<ConnectToken, void (boost::system::error_code)>(
0971         declval<initiate_async_connect>(), token,
0972         peer_endpoint, declval<boost::system::error_code&>()))
0973   {
0974     boost::system::error_code open_ec;
0975     if (!is_open())
0976     {
0977       const protocol_type protocol = peer_endpoint.protocol();
0978       impl_.get_service().open(impl_.get_implementation(), protocol, open_ec);
0979     }
0980 
0981     return async_initiate<ConnectToken, void (boost::system::error_code)>(
0982         initiate_async_connect(this), token, peer_endpoint, open_ec);
0983   }
0984 
0985   /// Set an option on the socket.
0986   /**
0987    * This function is used to set an option on the socket.
0988    *
0989    * @param option The new option value to be set on the socket.
0990    *
0991    * @throws boost::system::system_error Thrown on failure.
0992    *
0993    * @sa SettableSocketOption @n
0994    * boost::asio::socket_base::broadcast @n
0995    * boost::asio::socket_base::do_not_route @n
0996    * boost::asio::socket_base::keep_alive @n
0997    * boost::asio::socket_base::linger @n
0998    * boost::asio::socket_base::receive_buffer_size @n
0999    * boost::asio::socket_base::receive_low_watermark @n
1000    * boost::asio::socket_base::reuse_address @n
1001    * boost::asio::socket_base::send_buffer_size @n
1002    * boost::asio::socket_base::send_low_watermark @n
1003    * boost::asio::ip::multicast::join_group @n
1004    * boost::asio::ip::multicast::leave_group @n
1005    * boost::asio::ip::multicast::enable_loopback @n
1006    * boost::asio::ip::multicast::outbound_interface @n
1007    * boost::asio::ip::multicast::hops @n
1008    * boost::asio::ip::tcp::no_delay
1009    *
1010    * @par Example
1011    * Setting the IPPROTO_TCP/TCP_NODELAY option:
1012    * @code
1013    * boost::asio::ip::tcp::socket socket(my_context);
1014    * ...
1015    * boost::asio::ip::tcp::no_delay option(true);
1016    * socket.set_option(option);
1017    * @endcode
1018    */
1019   template <typename SettableSocketOption>
1020   void set_option(const SettableSocketOption& option)
1021   {
1022     boost::system::error_code ec;
1023     impl_.get_service().set_option(impl_.get_implementation(), option, ec);
1024     boost::asio::detail::throw_error(ec, "set_option");
1025   }
1026 
1027   /// Set an option on the socket.
1028   /**
1029    * This function is used to set an option on the socket.
1030    *
1031    * @param option The new option value to be set on the socket.
1032    *
1033    * @param ec Set to indicate what error occurred, if any.
1034    *
1035    * @sa SettableSocketOption @n
1036    * boost::asio::socket_base::broadcast @n
1037    * boost::asio::socket_base::do_not_route @n
1038    * boost::asio::socket_base::keep_alive @n
1039    * boost::asio::socket_base::linger @n
1040    * boost::asio::socket_base::receive_buffer_size @n
1041    * boost::asio::socket_base::receive_low_watermark @n
1042    * boost::asio::socket_base::reuse_address @n
1043    * boost::asio::socket_base::send_buffer_size @n
1044    * boost::asio::socket_base::send_low_watermark @n
1045    * boost::asio::ip::multicast::join_group @n
1046    * boost::asio::ip::multicast::leave_group @n
1047    * boost::asio::ip::multicast::enable_loopback @n
1048    * boost::asio::ip::multicast::outbound_interface @n
1049    * boost::asio::ip::multicast::hops @n
1050    * boost::asio::ip::tcp::no_delay
1051    *
1052    * @par Example
1053    * Setting the IPPROTO_TCP/TCP_NODELAY option:
1054    * @code
1055    * boost::asio::ip::tcp::socket socket(my_context);
1056    * ...
1057    * boost::asio::ip::tcp::no_delay option(true);
1058    * boost::system::error_code ec;
1059    * socket.set_option(option, ec);
1060    * if (ec)
1061    * {
1062    *   // An error occurred.
1063    * }
1064    * @endcode
1065    */
1066   template <typename SettableSocketOption>
1067   BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
1068       boost::system::error_code& ec)
1069   {
1070     impl_.get_service().set_option(impl_.get_implementation(), option, ec);
1071     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1072   }
1073 
1074   /// Get an option from the socket.
1075   /**
1076    * This function is used to get the current value of an option on the socket.
1077    *
1078    * @param option The option value to be obtained from the socket.
1079    *
1080    * @throws boost::system::system_error Thrown on failure.
1081    *
1082    * @sa GettableSocketOption @n
1083    * boost::asio::socket_base::broadcast @n
1084    * boost::asio::socket_base::do_not_route @n
1085    * boost::asio::socket_base::keep_alive @n
1086    * boost::asio::socket_base::linger @n
1087    * boost::asio::socket_base::receive_buffer_size @n
1088    * boost::asio::socket_base::receive_low_watermark @n
1089    * boost::asio::socket_base::reuse_address @n
1090    * boost::asio::socket_base::send_buffer_size @n
1091    * boost::asio::socket_base::send_low_watermark @n
1092    * boost::asio::ip::multicast::join_group @n
1093    * boost::asio::ip::multicast::leave_group @n
1094    * boost::asio::ip::multicast::enable_loopback @n
1095    * boost::asio::ip::multicast::outbound_interface @n
1096    * boost::asio::ip::multicast::hops @n
1097    * boost::asio::ip::tcp::no_delay
1098    *
1099    * @par Example
1100    * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
1101    * @code
1102    * boost::asio::ip::tcp::socket socket(my_context);
1103    * ...
1104    * boost::asio::ip::tcp::socket::keep_alive option;
1105    * socket.get_option(option);
1106    * bool is_set = option.value();
1107    * @endcode
1108    */
1109   template <typename GettableSocketOption>
1110   void get_option(GettableSocketOption& option) const
1111   {
1112     boost::system::error_code ec;
1113     impl_.get_service().get_option(impl_.get_implementation(), option, ec);
1114     boost::asio::detail::throw_error(ec, "get_option");
1115   }
1116 
1117   /// Get an option from the socket.
1118   /**
1119    * This function is used to get the current value of an option on the socket.
1120    *
1121    * @param option The option value to be obtained from the socket.
1122    *
1123    * @param ec Set to indicate what error occurred, if any.
1124    *
1125    * @sa GettableSocketOption @n
1126    * boost::asio::socket_base::broadcast @n
1127    * boost::asio::socket_base::do_not_route @n
1128    * boost::asio::socket_base::keep_alive @n
1129    * boost::asio::socket_base::linger @n
1130    * boost::asio::socket_base::receive_buffer_size @n
1131    * boost::asio::socket_base::receive_low_watermark @n
1132    * boost::asio::socket_base::reuse_address @n
1133    * boost::asio::socket_base::send_buffer_size @n
1134    * boost::asio::socket_base::send_low_watermark @n
1135    * boost::asio::ip::multicast::join_group @n
1136    * boost::asio::ip::multicast::leave_group @n
1137    * boost::asio::ip::multicast::enable_loopback @n
1138    * boost::asio::ip::multicast::outbound_interface @n
1139    * boost::asio::ip::multicast::hops @n
1140    * boost::asio::ip::tcp::no_delay
1141    *
1142    * @par Example
1143    * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
1144    * @code
1145    * boost::asio::ip::tcp::socket socket(my_context);
1146    * ...
1147    * boost::asio::ip::tcp::socket::keep_alive option;
1148    * boost::system::error_code ec;
1149    * socket.get_option(option, ec);
1150    * if (ec)
1151    * {
1152    *   // An error occurred.
1153    * }
1154    * bool is_set = option.value();
1155    * @endcode
1156    */
1157   template <typename GettableSocketOption>
1158   BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
1159       boost::system::error_code& ec) const
1160   {
1161     impl_.get_service().get_option(impl_.get_implementation(), option, ec);
1162     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1163   }
1164 
1165   /// Perform an IO control command on the socket.
1166   /**
1167    * This function is used to execute an IO control command on the socket.
1168    *
1169    * @param command The IO control command to be performed on the socket.
1170    *
1171    * @throws boost::system::system_error Thrown on failure.
1172    *
1173    * @sa IoControlCommand @n
1174    * boost::asio::socket_base::bytes_readable @n
1175    * boost::asio::socket_base::non_blocking_io
1176    *
1177    * @par Example
1178    * Getting the number of bytes ready to read:
1179    * @code
1180    * boost::asio::ip::tcp::socket socket(my_context);
1181    * ...
1182    * boost::asio::ip::tcp::socket::bytes_readable command;
1183    * socket.io_control(command);
1184    * std::size_t bytes_readable = command.get();
1185    * @endcode
1186    */
1187   template <typename IoControlCommand>
1188   void io_control(IoControlCommand& command)
1189   {
1190     boost::system::error_code ec;
1191     impl_.get_service().io_control(impl_.get_implementation(), command, ec);
1192     boost::asio::detail::throw_error(ec, "io_control");
1193   }
1194 
1195   /// Perform an IO control command on the socket.
1196   /**
1197    * This function is used to execute an IO control command on the socket.
1198    *
1199    * @param command The IO control command to be performed on the socket.
1200    *
1201    * @param ec Set to indicate what error occurred, if any.
1202    *
1203    * @sa IoControlCommand @n
1204    * boost::asio::socket_base::bytes_readable @n
1205    * boost::asio::socket_base::non_blocking_io
1206    *
1207    * @par Example
1208    * Getting the number of bytes ready to read:
1209    * @code
1210    * boost::asio::ip::tcp::socket socket(my_context);
1211    * ...
1212    * boost::asio::ip::tcp::socket::bytes_readable command;
1213    * boost::system::error_code ec;
1214    * socket.io_control(command, ec);
1215    * if (ec)
1216    * {
1217    *   // An error occurred.
1218    * }
1219    * std::size_t bytes_readable = command.get();
1220    * @endcode
1221    */
1222   template <typename IoControlCommand>
1223   BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
1224       boost::system::error_code& ec)
1225   {
1226     impl_.get_service().io_control(impl_.get_implementation(), command, ec);
1227     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1228   }
1229 
1230   /// Gets the non-blocking mode of the socket.
1231   /**
1232    * @returns @c true if the socket's synchronous operations will fail with
1233    * boost::asio::error::would_block if they are unable to perform the requested
1234    * operation immediately. If @c false, synchronous operations will block
1235    * until complete.
1236    *
1237    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1238    * operations. Asynchronous operations will never fail with the error
1239    * boost::asio::error::would_block.
1240    */
1241   bool non_blocking() const
1242   {
1243     return impl_.get_service().non_blocking(impl_.get_implementation());
1244   }
1245 
1246   /// Sets the non-blocking mode of the socket.
1247   /**
1248    * @param mode If @c true, the socket's synchronous operations will fail with
1249    * boost::asio::error::would_block if they are unable to perform the requested
1250    * operation immediately. If @c false, synchronous operations will block
1251    * until complete.
1252    *
1253    * @throws boost::system::system_error Thrown on failure.
1254    *
1255    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1256    * operations. Asynchronous operations will never fail with the error
1257    * boost::asio::error::would_block.
1258    */
1259   void non_blocking(bool mode)
1260   {
1261     boost::system::error_code ec;
1262     impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
1263     boost::asio::detail::throw_error(ec, "non_blocking");
1264   }
1265 
1266   /// Sets the non-blocking mode of the socket.
1267   /**
1268    * @param mode If @c true, the socket's synchronous operations will fail with
1269    * boost::asio::error::would_block if they are unable to perform the requested
1270    * operation immediately. If @c false, synchronous operations will block
1271    * until complete.
1272    *
1273    * @param ec Set to indicate what error occurred, if any.
1274    *
1275    * @note The non-blocking mode has no effect on the behaviour of asynchronous
1276    * operations. Asynchronous operations will never fail with the error
1277    * boost::asio::error::would_block.
1278    */
1279   BOOST_ASIO_SYNC_OP_VOID non_blocking(
1280       bool mode, boost::system::error_code& ec)
1281   {
1282     impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
1283     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1284   }
1285 
1286   /// Gets the non-blocking mode of the native socket implementation.
1287   /**
1288    * This function is used to retrieve the non-blocking mode of the underlying
1289    * native socket. This mode has no effect on the behaviour of the socket
1290    * object's synchronous operations.
1291    *
1292    * @returns @c true if the underlying socket is in non-blocking mode and
1293    * direct system calls may fail with boost::asio::error::would_block (or the
1294    * equivalent system error).
1295    *
1296    * @note The current non-blocking mode is cached by the socket object.
1297    * Consequently, the return value may be incorrect if the non-blocking mode
1298    * was set directly on the native socket.
1299    *
1300    * @par Example
1301    * This function is intended to allow the encapsulation of arbitrary
1302    * non-blocking system calls as asynchronous operations, in a way that is
1303    * transparent to the user of the socket object. The following example
1304    * illustrates how Linux's @c sendfile system call might be encapsulated:
1305    * @code template <typename Handler>
1306    * struct sendfile_op
1307    * {
1308    *   tcp::socket& sock_;
1309    *   int fd_;
1310    *   Handler handler_;
1311    *   off_t offset_;
1312    *   std::size_t total_bytes_transferred_;
1313    *
1314    *   // Function call operator meeting WriteHandler requirements.
1315    *   // Used as the handler for the async_write_some operation.
1316    *   void operator()(boost::system::error_code ec, std::size_t)
1317    *   {
1318    *     // Put the underlying socket into non-blocking mode.
1319    *     if (!ec)
1320    *       if (!sock_.native_non_blocking())
1321    *         sock_.native_non_blocking(true, ec);
1322    *
1323    *     if (!ec)
1324    *     {
1325    *       for (;;)
1326    *       {
1327    *         // Try the system call.
1328    *         errno = 0;
1329    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1330    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1331    *             boost::asio::error::get_system_category());
1332    *         total_bytes_transferred_ += ec ? 0 : n;
1333    *
1334    *         // Retry operation immediately if interrupted by signal.
1335    *         if (ec == boost::asio::error::interrupted)
1336    *           continue;
1337    *
1338    *         // Check if we need to run the operation again.
1339    *         if (ec == boost::asio::error::would_block
1340    *             || ec == boost::asio::error::try_again)
1341    *         {
1342    *           // We have to wait for the socket to become ready again.
1343    *           sock_.async_wait(tcp::socket::wait_write, *this);
1344    *           return;
1345    *         }
1346    *
1347    *         if (ec || n == 0)
1348    *         {
1349    *           // An error occurred, or we have reached the end of the file.
1350    *           // Either way we must exit the loop so we can call the handler.
1351    *           break;
1352    *         }
1353    *
1354    *         // Loop around to try calling sendfile again.
1355    *       }
1356    *     }
1357    *
1358    *     // Pass result back to user's handler.
1359    *     handler_(ec, total_bytes_transferred_);
1360    *   }
1361    * };
1362    *
1363    * template <typename Handler>
1364    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1365    * {
1366    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1367    *   sock.async_wait(tcp::socket::wait_write, op);
1368    * } @endcode
1369    */
1370   bool native_non_blocking() const
1371   {
1372     return impl_.get_service().native_non_blocking(impl_.get_implementation());
1373   }
1374 
1375   /// Sets the non-blocking mode of the native socket implementation.
1376   /**
1377    * This function is used to modify the non-blocking mode of the underlying
1378    * native socket. It has no effect on the behaviour of the socket object's
1379    * synchronous operations.
1380    *
1381    * @param mode If @c true, the underlying socket is put into non-blocking
1382    * mode and direct system calls may fail with boost::asio::error::would_block
1383    * (or the equivalent system error).
1384    *
1385    * @throws boost::system::system_error Thrown on failure. If the @c mode is
1386    * @c false, but the current value of @c non_blocking() is @c true, this
1387    * function fails with boost::asio::error::invalid_argument, as the
1388    * combination does not make sense.
1389    *
1390    * @par Example
1391    * This function is intended to allow the encapsulation of arbitrary
1392    * non-blocking system calls as asynchronous operations, in a way that is
1393    * transparent to the user of the socket object. The following example
1394    * illustrates how Linux's @c sendfile system call might be encapsulated:
1395    * @code template <typename Handler>
1396    * struct sendfile_op
1397    * {
1398    *   tcp::socket& sock_;
1399    *   int fd_;
1400    *   Handler handler_;
1401    *   off_t offset_;
1402    *   std::size_t total_bytes_transferred_;
1403    *
1404    *   // Function call operator meeting WriteHandler requirements.
1405    *   // Used as the handler for the async_write_some operation.
1406    *   void operator()(boost::system::error_code ec, std::size_t)
1407    *   {
1408    *     // Put the underlying socket into non-blocking mode.
1409    *     if (!ec)
1410    *       if (!sock_.native_non_blocking())
1411    *         sock_.native_non_blocking(true, ec);
1412    *
1413    *     if (!ec)
1414    *     {
1415    *       for (;;)
1416    *       {
1417    *         // Try the system call.
1418    *         errno = 0;
1419    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1420    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1421    *             boost::asio::error::get_system_category());
1422    *         total_bytes_transferred_ += ec ? 0 : n;
1423    *
1424    *         // Retry operation immediately if interrupted by signal.
1425    *         if (ec == boost::asio::error::interrupted)
1426    *           continue;
1427    *
1428    *         // Check if we need to run the operation again.
1429    *         if (ec == boost::asio::error::would_block
1430    *             || ec == boost::asio::error::try_again)
1431    *         {
1432    *           // We have to wait for the socket to become ready again.
1433    *           sock_.async_wait(tcp::socket::wait_write, *this);
1434    *           return;
1435    *         }
1436    *
1437    *         if (ec || n == 0)
1438    *         {
1439    *           // An error occurred, or we have reached the end of the file.
1440    *           // Either way we must exit the loop so we can call the handler.
1441    *           break;
1442    *         }
1443    *
1444    *         // Loop around to try calling sendfile again.
1445    *       }
1446    *     }
1447    *
1448    *     // Pass result back to user's handler.
1449    *     handler_(ec, total_bytes_transferred_);
1450    *   }
1451    * };
1452    *
1453    * template <typename Handler>
1454    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1455    * {
1456    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1457    *   sock.async_wait(tcp::socket::wait_write, op);
1458    * } @endcode
1459    */
1460   void native_non_blocking(bool mode)
1461   {
1462     boost::system::error_code ec;
1463     impl_.get_service().native_non_blocking(
1464         impl_.get_implementation(), mode, ec);
1465     boost::asio::detail::throw_error(ec, "native_non_blocking");
1466   }
1467 
1468   /// Sets the non-blocking mode of the native socket implementation.
1469   /**
1470    * This function is used to modify the non-blocking mode of the underlying
1471    * native socket. It has no effect on the behaviour of the socket object's
1472    * synchronous operations.
1473    *
1474    * @param mode If @c true, the underlying socket is put into non-blocking
1475    * mode and direct system calls may fail with boost::asio::error::would_block
1476    * (or the equivalent system error).
1477    *
1478    * @param ec Set to indicate what error occurred, if any. If the @c mode is
1479    * @c false, but the current value of @c non_blocking() is @c true, this
1480    * function fails with boost::asio::error::invalid_argument, as the
1481    * combination does not make sense.
1482    *
1483    * @par Example
1484    * This function is intended to allow the encapsulation of arbitrary
1485    * non-blocking system calls as asynchronous operations, in a way that is
1486    * transparent to the user of the socket object. The following example
1487    * illustrates how Linux's @c sendfile system call might be encapsulated:
1488    * @code template <typename Handler>
1489    * struct sendfile_op
1490    * {
1491    *   tcp::socket& sock_;
1492    *   int fd_;
1493    *   Handler handler_;
1494    *   off_t offset_;
1495    *   std::size_t total_bytes_transferred_;
1496    *
1497    *   // Function call operator meeting WriteHandler requirements.
1498    *   // Used as the handler for the async_write_some operation.
1499    *   void operator()(boost::system::error_code ec, std::size_t)
1500    *   {
1501    *     // Put the underlying socket into non-blocking mode.
1502    *     if (!ec)
1503    *       if (!sock_.native_non_blocking())
1504    *         sock_.native_non_blocking(true, ec);
1505    *
1506    *     if (!ec)
1507    *     {
1508    *       for (;;)
1509    *       {
1510    *         // Try the system call.
1511    *         errno = 0;
1512    *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
1513    *         ec = boost::system::error_code(n < 0 ? errno : 0,
1514    *             boost::asio::error::get_system_category());
1515    *         total_bytes_transferred_ += ec ? 0 : n;
1516    *
1517    *         // Retry operation immediately if interrupted by signal.
1518    *         if (ec == boost::asio::error::interrupted)
1519    *           continue;
1520    *
1521    *         // Check if we need to run the operation again.
1522    *         if (ec == boost::asio::error::would_block
1523    *             || ec == boost::asio::error::try_again)
1524    *         {
1525    *           // We have to wait for the socket to become ready again.
1526    *           sock_.async_wait(tcp::socket::wait_write, *this);
1527    *           return;
1528    *         }
1529    *
1530    *         if (ec || n == 0)
1531    *         {
1532    *           // An error occurred, or we have reached the end of the file.
1533    *           // Either way we must exit the loop so we can call the handler.
1534    *           break;
1535    *         }
1536    *
1537    *         // Loop around to try calling sendfile again.
1538    *       }
1539    *     }
1540    *
1541    *     // Pass result back to user's handler.
1542    *     handler_(ec, total_bytes_transferred_);
1543    *   }
1544    * };
1545    *
1546    * template <typename Handler>
1547    * void async_sendfile(tcp::socket& sock, int fd, Handler h)
1548    * {
1549    *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
1550    *   sock.async_wait(tcp::socket::wait_write, op);
1551    * } @endcode
1552    */
1553   BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
1554       bool mode, boost::system::error_code& ec)
1555   {
1556     impl_.get_service().native_non_blocking(
1557         impl_.get_implementation(), mode, ec);
1558     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1559   }
1560 
1561   /// Get the local endpoint of the socket.
1562   /**
1563    * This function is used to obtain the locally bound endpoint of the socket.
1564    *
1565    * @returns An object that represents the local endpoint of the socket.
1566    *
1567    * @throws boost::system::system_error Thrown on failure.
1568    *
1569    * @par Example
1570    * @code
1571    * boost::asio::ip::tcp::socket socket(my_context);
1572    * ...
1573    * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
1574    * @endcode
1575    */
1576   endpoint_type local_endpoint() const
1577   {
1578     boost::system::error_code ec;
1579     endpoint_type ep = impl_.get_service().local_endpoint(
1580         impl_.get_implementation(), ec);
1581     boost::asio::detail::throw_error(ec, "local_endpoint");
1582     return ep;
1583   }
1584 
1585   /// Get the local endpoint of the socket.
1586   /**
1587    * This function is used to obtain the locally bound endpoint of the socket.
1588    *
1589    * @param ec Set to indicate what error occurred, if any.
1590    *
1591    * @returns An object that represents the local endpoint of the socket.
1592    * Returns a default-constructed endpoint object if an error occurred.
1593    *
1594    * @par Example
1595    * @code
1596    * boost::asio::ip::tcp::socket socket(my_context);
1597    * ...
1598    * boost::system::error_code ec;
1599    * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
1600    * if (ec)
1601    * {
1602    *   // An error occurred.
1603    * }
1604    * @endcode
1605    */
1606   endpoint_type local_endpoint(boost::system::error_code& ec) const
1607   {
1608     return impl_.get_service().local_endpoint(impl_.get_implementation(), ec);
1609   }
1610 
1611   /// Get the remote endpoint of the socket.
1612   /**
1613    * This function is used to obtain the remote endpoint of the socket.
1614    *
1615    * @returns An object that represents the remote endpoint of the socket.
1616    *
1617    * @throws boost::system::system_error Thrown on failure.
1618    *
1619    * @par Example
1620    * @code
1621    * boost::asio::ip::tcp::socket socket(my_context);
1622    * ...
1623    * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
1624    * @endcode
1625    */
1626   endpoint_type remote_endpoint() const
1627   {
1628     boost::system::error_code ec;
1629     endpoint_type ep = impl_.get_service().remote_endpoint(
1630         impl_.get_implementation(), ec);
1631     boost::asio::detail::throw_error(ec, "remote_endpoint");
1632     return ep;
1633   }
1634 
1635   /// Get the remote endpoint of the socket.
1636   /**
1637    * This function is used to obtain the remote endpoint of the socket.
1638    *
1639    * @param ec Set to indicate what error occurred, if any.
1640    *
1641    * @returns An object that represents the remote endpoint of the socket.
1642    * Returns a default-constructed endpoint object if an error occurred.
1643    *
1644    * @par Example
1645    * @code
1646    * boost::asio::ip::tcp::socket socket(my_context);
1647    * ...
1648    * boost::system::error_code ec;
1649    * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
1650    * if (ec)
1651    * {
1652    *   // An error occurred.
1653    * }
1654    * @endcode
1655    */
1656   endpoint_type remote_endpoint(boost::system::error_code& ec) const
1657   {
1658     return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec);
1659   }
1660 
1661   /// Disable sends or receives on the socket.
1662   /**
1663    * This function is used to disable send operations, receive operations, or
1664    * both.
1665    *
1666    * @param what Determines what types of operation will no longer be allowed.
1667    *
1668    * @throws boost::system::system_error Thrown on failure.
1669    *
1670    * @par Example
1671    * Shutting down the send side of the socket:
1672    * @code
1673    * boost::asio::ip::tcp::socket socket(my_context);
1674    * ...
1675    * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
1676    * @endcode
1677    */
1678   void shutdown(shutdown_type what)
1679   {
1680     boost::system::error_code ec;
1681     impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
1682     boost::asio::detail::throw_error(ec, "shutdown");
1683   }
1684 
1685   /// Disable sends or receives on the socket.
1686   /**
1687    * This function is used to disable send operations, receive operations, or
1688    * both.
1689    *
1690    * @param what Determines what types of operation will no longer be allowed.
1691    *
1692    * @param ec Set to indicate what error occurred, if any.
1693    *
1694    * @par Example
1695    * Shutting down the send side of the socket:
1696    * @code
1697    * boost::asio::ip::tcp::socket socket(my_context);
1698    * ...
1699    * boost::system::error_code ec;
1700    * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
1701    * if (ec)
1702    * {
1703    *   // An error occurred.
1704    * }
1705    * @endcode
1706    */
1707   BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what,
1708       boost::system::error_code& ec)
1709   {
1710     impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
1711     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1712   }
1713 
1714   /// Wait for the socket to become ready to read, ready to write, or to have
1715   /// pending error conditions.
1716   /**
1717    * This function is used to perform a blocking wait for a socket to enter
1718    * a ready to read, write or error condition state.
1719    *
1720    * @param w Specifies the desired socket state.
1721    *
1722    * @par Example
1723    * Waiting for a socket to become readable.
1724    * @code
1725    * boost::asio::ip::tcp::socket socket(my_context);
1726    * ...
1727    * socket.wait(boost::asio::ip::tcp::socket::wait_read);
1728    * @endcode
1729    */
1730   void wait(wait_type w)
1731   {
1732     boost::system::error_code ec;
1733     impl_.get_service().wait(impl_.get_implementation(), w, ec);
1734     boost::asio::detail::throw_error(ec, "wait");
1735   }
1736 
1737   /// Wait for the socket to become ready to read, ready to write, or to have
1738   /// pending error conditions.
1739   /**
1740    * This function is used to perform a blocking wait for a socket to enter
1741    * a ready to read, write or error condition state.
1742    *
1743    * @param w Specifies the desired socket state.
1744    *
1745    * @param ec Set to indicate what error occurred, if any.
1746    *
1747    * @par Example
1748    * Waiting for a socket to become readable.
1749    * @code
1750    * boost::asio::ip::tcp::socket socket(my_context);
1751    * ...
1752    * boost::system::error_code ec;
1753    * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec);
1754    * @endcode
1755    */
1756   BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
1757   {
1758     impl_.get_service().wait(impl_.get_implementation(), w, ec);
1759     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
1760   }
1761 
1762   /// Asynchronously wait for the socket to become ready to read, ready to
1763   /// write, or to have pending error conditions.
1764   /**
1765    * This function is used to perform an asynchronous wait for a socket to enter
1766    * a ready to read, write or error condition state. It is an initiating
1767    * function for an @ref asynchronous_operation, and always returns
1768    * immediately.
1769    *
1770    * @param w Specifies the desired socket state.
1771    *
1772    * @param token The @ref completion_token that will be used to produce a
1773    * completion handler, which will be called when the wait completes. Potential
1774    * completion tokens include @ref use_future, @ref use_awaitable, @ref
1775    * yield_context, or a function object with the correct completion signature.
1776    * The function signature of the completion handler must be:
1777    * @code void handler(
1778    *   const boost::system::error_code& error // Result of operation.
1779    * ); @endcode
1780    * Regardless of whether the asynchronous operation completes immediately or
1781    * not, the completion handler will not be invoked from within this function.
1782    * On immediate completion, invocation of the handler will be performed in a
1783    * manner equivalent to using boost::asio::post().
1784    *
1785    * @par Completion Signature
1786    * @code void(boost::system::error_code) @endcode
1787    *
1788    * @par Example
1789    * @code
1790    * void wait_handler(const boost::system::error_code& error)
1791    * {
1792    *   if (!error)
1793    *   {
1794    *     // Wait succeeded.
1795    *   }
1796    * }
1797    *
1798    * ...
1799    *
1800    * boost::asio::ip::tcp::socket socket(my_context);
1801    * ...
1802    * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
1803    * @endcode
1804    *
1805    * @par Per-Operation Cancellation
1806    * On POSIX or Windows operating systems, this asynchronous operation supports
1807    * cancellation for the following boost::asio::cancellation_type values:
1808    *
1809    * @li @c cancellation_type::terminal
1810    *
1811    * @li @c cancellation_type::partial
1812    *
1813    * @li @c cancellation_type::total
1814    */
1815   template <
1816       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
1817         WaitToken = default_completion_token_t<executor_type>>
1818   auto async_wait(wait_type w,
1819       WaitToken&& token = default_completion_token_t<executor_type>())
1820     -> decltype(
1821       async_initiate<WaitToken, void (boost::system::error_code)>(
1822           declval<initiate_async_wait>(), token, w))
1823   {
1824     return async_initiate<WaitToken, void (boost::system::error_code)>(
1825         initiate_async_wait(this), token, w);
1826   }
1827 
1828 protected:
1829   /// Protected destructor to prevent deletion through this type.
1830   /**
1831    * This function destroys the socket, cancelling any outstanding asynchronous
1832    * operations associated with the socket as if by calling @c cancel.
1833    */
1834   ~basic_socket()
1835   {
1836   }
1837 
1838 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
1839   detail::io_object_impl<
1840     detail::null_socket_service<Protocol>, Executor> impl_;
1841 #elif defined(BOOST_ASIO_HAS_IOCP)
1842   detail::io_object_impl<
1843     detail::win_iocp_socket_service<Protocol>, Executor> impl_;
1844 #elif defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
1845   detail::io_object_impl<
1846     detail::io_uring_socket_service<Protocol>, Executor> impl_;
1847 #else
1848   detail::io_object_impl<
1849     detail::reactive_socket_service<Protocol>, Executor> impl_;
1850 #endif
1851 
1852 private:
1853   // Disallow copying and assignment.
1854   basic_socket(const basic_socket&) = delete;
1855   basic_socket& operator=(const basic_socket&) = delete;
1856 
1857   class initiate_async_connect
1858   {
1859   public:
1860     typedef Executor executor_type;
1861 
1862     explicit initiate_async_connect(basic_socket* self)
1863       : self_(self)
1864     {
1865     }
1866 
1867     const executor_type& get_executor() const noexcept
1868     {
1869       return self_->get_executor();
1870     }
1871 
1872     template <typename ConnectHandler>
1873     void operator()(ConnectHandler&& handler,
1874         const endpoint_type& peer_endpoint,
1875         const boost::system::error_code& open_ec) const
1876     {
1877       // If you get an error on the following line it means that your handler
1878       // does not meet the documented type requirements for a ConnectHandler.
1879       BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
1880 
1881       if (open_ec)
1882       {
1883           boost::asio::post(self_->impl_.get_executor(),
1884               boost::asio::detail::bind_handler(
1885                 static_cast<ConnectHandler&&>(handler), open_ec));
1886       }
1887       else
1888       {
1889         detail::non_const_lvalue<ConnectHandler> handler2(handler);
1890         self_->impl_.get_service().async_connect(
1891             self_->impl_.get_implementation(), peer_endpoint,
1892             handler2.value, self_->impl_.get_executor());
1893       }
1894     }
1895 
1896   private:
1897     basic_socket* self_;
1898   };
1899 
1900   class initiate_async_wait
1901   {
1902   public:
1903     typedef Executor executor_type;
1904 
1905     explicit initiate_async_wait(basic_socket* self)
1906       : self_(self)
1907     {
1908     }
1909 
1910     const executor_type& get_executor() const noexcept
1911     {
1912       return self_->get_executor();
1913     }
1914 
1915     template <typename WaitHandler>
1916     void operator()(WaitHandler&& handler, wait_type w) const
1917     {
1918       // If you get an error on the following line it means that your handler
1919       // does not meet the documented type requirements for a WaitHandler.
1920       BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
1921 
1922       detail::non_const_lvalue<WaitHandler> handler2(handler);
1923       self_->impl_.get_service().async_wait(
1924           self_->impl_.get_implementation(), w,
1925           handler2.value, self_->impl_.get_executor());
1926     }
1927 
1928   private:
1929     basic_socket* self_;
1930   };
1931 };
1932 
1933 } // namespace asio
1934 } // namespace boost
1935 
1936 #include <boost/asio/detail/pop_options.hpp>
1937 
1938 #endif // BOOST_ASIO_BASIC_SOCKET_HPP