Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //
0002 // windows/basic_stream_handle.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_WINDOWS_BASIC_STREAM_HANDLE_HPP
0012 #define BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_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 #include <boost/asio/windows/basic_overlapped_handle.hpp>
0020 
0021 #if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
0022   || defined(GENERATING_DOCUMENTATION)
0023 
0024 #include <boost/asio/detail/push_options.hpp>
0025 
0026 namespace boost {
0027 namespace asio {
0028 namespace windows {
0029 
0030 /// Provides stream-oriented handle functionality.
0031 /**
0032  * The windows::basic_stream_handle class provides asynchronous and blocking
0033  * stream-oriented handle functionality.
0034  *
0035  * @par Thread Safety
0036  * @e Distinct @e objects: Safe.@n
0037  * @e Shared @e objects: Unsafe.
0038  *
0039  * @par Concepts:
0040  * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
0041  */
0042 template <typename Executor = any_io_executor>
0043 class basic_stream_handle
0044   : public basic_overlapped_handle<Executor>
0045 {
0046 private:
0047   class initiate_async_write_some;
0048   class initiate_async_read_some;
0049 
0050 public:
0051   /// The type of the executor associated with the object.
0052   typedef Executor executor_type;
0053 
0054   /// Rebinds the handle type to another executor.
0055   template <typename Executor1>
0056   struct rebind_executor
0057   {
0058     /// The handle type when rebound to the specified executor.
0059     typedef basic_stream_handle<Executor1> other;
0060   };
0061 
0062   /// The native representation of a handle.
0063 #if defined(GENERATING_DOCUMENTATION)
0064   typedef implementation_defined native_handle_type;
0065 #else
0066   typedef boost::asio::detail::win_iocp_handle_service::native_handle_type
0067     native_handle_type;
0068 #endif
0069 
0070   /// Construct a stream handle without opening it.
0071   /**
0072    * This constructor creates a stream handle without opening it.
0073    *
0074    * @param ex The I/O executor that the stream handle will use, by default, to
0075    * dispatch handlers for any asynchronous operations performed on the stream
0076    * handle.
0077    */
0078   explicit basic_stream_handle(const executor_type& ex)
0079     : basic_overlapped_handle<Executor>(ex)
0080   {
0081   }
0082 
0083   /// Construct a stream handle without opening it.
0084   /**
0085    * This constructor creates a stream handle without opening it. The handle
0086    * needs to be opened or assigned before data can be written to or read from
0087    * it.
0088    *
0089    * @param context An execution context which provides the I/O executor that
0090    * the stream handle will use, by default, to dispatch handlers for any
0091    * asynchronous operations performed on the stream handle.
0092    */
0093   template <typename ExecutionContext>
0094   explicit basic_stream_handle(ExecutionContext& context,
0095       constraint_t<
0096         is_convertible<ExecutionContext&, execution_context&>::value,
0097         defaulted_constraint
0098       > = defaulted_constraint())
0099     : basic_overlapped_handle<Executor>(context)
0100   {
0101   }
0102 
0103   /// Construct a stream handle on an existing native handle.
0104   /**
0105    * This constructor creates a stream handle object to hold an existing native
0106    * handle.
0107    *
0108    * @param ex The I/O executor that the stream handle will use, by default, to
0109    * dispatch handlers for any asynchronous operations performed on the stream
0110    * handle.
0111    *
0112    * @param handle The new underlying handle implementation.
0113    *
0114    * @throws boost::system::system_error Thrown on failure.
0115    */
0116   basic_stream_handle(const executor_type& ex, const native_handle_type& handle)
0117     : basic_overlapped_handle<Executor>(ex, handle)
0118   {
0119   }
0120 
0121   /// Construct a stream handle on an existing native handle.
0122   /**
0123    * This constructor creates a stream handle object to hold an existing native
0124    * handle.
0125    *
0126    * @param context An execution context which provides the I/O executor that
0127    * the stream handle will use, by default, to dispatch handlers for any
0128    * asynchronous operations performed on the stream handle.
0129    *
0130    * @param handle The new underlying handle implementation.
0131    *
0132    * @throws boost::system::system_error Thrown on failure.
0133    */
0134   template <typename ExecutionContext>
0135   basic_stream_handle(ExecutionContext& context,
0136       const native_handle_type& handle,
0137       constraint_t<
0138         is_convertible<ExecutionContext&, execution_context&>::value
0139       > = 0)
0140     : basic_overlapped_handle<Executor>(context, handle)
0141   {
0142   }
0143 
0144   /// Move-construct a stream handle from another.
0145   /**
0146    * This constructor moves a stream handle from one object to another.
0147    *
0148    * @param other The other stream handle object from which the move
0149    * will occur.
0150    *
0151    * @note Following the move, the moved-from object is in the same state as if
0152    * constructed using the @c basic_stream_handle(const executor_type&)
0153    * constructor.
0154    */
0155   basic_stream_handle(basic_stream_handle&& other)
0156     : basic_overlapped_handle<Executor>(std::move(other))
0157   {
0158   }
0159 
0160   /// Move-assign a stream handle from another.
0161   /**
0162    * This assignment operator moves a stream handle from one object to
0163    * another.
0164    *
0165    * @param other The other stream handle object from which the move will occur.
0166    *
0167    * @note Following the move, the moved-from object is in the same state as if
0168    * constructed using the @c basic_stream_handle(const executor_type&)
0169    * constructor.
0170    */
0171   basic_stream_handle& operator=(basic_stream_handle&& other)
0172   {
0173     basic_overlapped_handle<Executor>::operator=(std::move(other));
0174     return *this;
0175   }
0176 
0177   /// Move-construct a stream handle from a handle of another executor type.
0178   /**
0179    * This constructor moves a stream handle from one object to another.
0180    *
0181    * @param other The other stream handle object from which the move
0182    * will occur.
0183    *
0184    * @note Following the move, the moved-from object is in the same state as if
0185    * constructed using the @c basic_stream_handle(const executor_type&)
0186    * constructor.
0187    */
0188   template<typename Executor1>
0189   basic_stream_handle(basic_stream_handle<Executor1>&& other,
0190       constraint_t<
0191         is_convertible<Executor1, Executor>::value,
0192         defaulted_constraint
0193       > = defaulted_constraint())
0194     : basic_overlapped_handle<Executor>(std::move(other))
0195   {
0196   }
0197 
0198   /// Move-assign a stream handle from a handle of another executor type.
0199   /**
0200    * This assignment operator moves a stream handle from one object to
0201    * another.
0202    *
0203    * @param other The other stream handle object from which the move will occur.
0204    *
0205    * @note Following the move, the moved-from object is in the same state as if
0206    * constructed using the @c basic_stream_handle(const executor_type&)
0207    * constructor.
0208    */
0209   template<typename Executor1>
0210   constraint_t<
0211     is_convertible<Executor1, Executor>::value,
0212     basic_stream_handle&
0213   > operator=(basic_stream_handle<Executor1>&& other)
0214   {
0215     basic_overlapped_handle<Executor>::operator=(std::move(other));
0216     return *this;
0217   }
0218 
0219   /// Write some data to the handle.
0220   /**
0221    * This function is used to write data to the stream handle. The function call
0222    * will block until one or more bytes of the data has been written
0223    * successfully, or until an error occurs.
0224    *
0225    * @param buffers One or more data buffers to be written to the handle.
0226    *
0227    * @returns The number of bytes written.
0228    *
0229    * @throws boost::system::system_error Thrown on failure. An error code of
0230    * boost::asio::error::eof indicates that the connection was closed by the
0231    * peer.
0232    *
0233    * @note The write_some operation may not transmit all of the data to the
0234    * peer. Consider using the @ref write function if you need to ensure that
0235    * all data is written before the blocking operation completes.
0236    *
0237    * @par Example
0238    * To write a single data buffer use the @ref buffer function as follows:
0239    * @code
0240    * handle.write_some(boost::asio::buffer(data, size));
0241    * @endcode
0242    * See the @ref buffer documentation for information on writing multiple
0243    * buffers in one go, and how to use it with arrays, boost::array or
0244    * std::vector.
0245    */
0246   template <typename ConstBufferSequence>
0247   std::size_t write_some(const ConstBufferSequence& buffers)
0248   {
0249     boost::system::error_code ec;
0250     std::size_t s = this->impl_.get_service().write_some(
0251         this->impl_.get_implementation(), buffers, ec);
0252     boost::asio::detail::throw_error(ec, "write_some");
0253     return s;
0254   }
0255 
0256   /// Write some data to the handle.
0257   /**
0258    * This function is used to write data to the stream handle. The function call
0259    * will block until one or more bytes of the data has been written
0260    * successfully, or until an error occurs.
0261    *
0262    * @param buffers One or more data buffers to be written to the handle.
0263    *
0264    * @param ec Set to indicate what error occurred, if any.
0265    *
0266    * @returns The number of bytes written. Returns 0 if an error occurred.
0267    *
0268    * @note The write_some operation may not transmit all of the data to the
0269    * peer. Consider using the @ref write function if you need to ensure that
0270    * all data is written before the blocking operation completes.
0271    */
0272   template <typename ConstBufferSequence>
0273   std::size_t write_some(const ConstBufferSequence& buffers,
0274       boost::system::error_code& ec)
0275   {
0276     return this->impl_.get_service().write_some(
0277         this->impl_.get_implementation(), buffers, ec);
0278   }
0279 
0280   /// Start an asynchronous write.
0281   /**
0282    * This function is used to asynchronously write data to the stream handle.
0283    * It is an initiating function for an @ref asynchronous_operation, and always
0284    * returns immediately.
0285    *
0286    * @param buffers One or more data buffers to be written to the handle.
0287    * Although the buffers object may be copied as necessary, ownership of the
0288    * underlying memory blocks is retained by the caller, which must guarantee
0289    * that they remain valid until the completion handler is called.
0290    *
0291    * @param token The @ref completion_token that will be used to produce a
0292    * completion handler, which will be called when the write completes.
0293    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0294    * @ref yield_context, or a function object with the correct completion
0295    * signature. The function signature of the completion handler must be:
0296    * @code void handler(
0297    *   const boost::system::error_code& error, // Result of operation.
0298    *   std::size_t bytes_transferred // Number of bytes written.
0299    * ); @endcode
0300    * Regardless of whether the asynchronous operation completes immediately or
0301    * not, the completion handler will not be invoked from within this function.
0302    * On immediate completion, invocation of the handler will be performed in a
0303    * manner equivalent to using boost::asio::post().
0304    *
0305    * @par Completion Signature
0306    * @code void(boost::system::error_code, std::size_t) @endcode
0307    *
0308    * @note The write operation may not transmit all of the data to the peer.
0309    * Consider using the @ref async_write function if you need to ensure that all
0310    * data is written before the asynchronous operation completes.
0311    *
0312    * @par Example
0313    * To write a single data buffer use the @ref buffer function as follows:
0314    * @code
0315    * handle.async_write_some(boost::asio::buffer(data, size), handler);
0316    * @endcode
0317    * See the @ref buffer documentation for information on writing multiple
0318    * buffers in one go, and how to use it with arrays, boost::array or
0319    * std::vector.
0320    *
0321    * @par Per-Operation Cancellation
0322    * This asynchronous operation supports cancellation for the following
0323    * boost::asio::cancellation_type values:
0324    *
0325    * @li @c cancellation_type::terminal
0326    *
0327    * @li @c cancellation_type::partial
0328    *
0329    * @li @c cancellation_type::total
0330    */
0331   template <typename ConstBufferSequence,
0332       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0333         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0334   auto async_write_some(const ConstBufferSequence& buffers,
0335       WriteToken&& token = default_completion_token_t<executor_type>())
0336     -> decltype(
0337       async_initiate<WriteToken,
0338         void (boost::system::error_code, std::size_t)>(
0339           declval<initiate_async_write_some>(), token, buffers))
0340   {
0341     return async_initiate<WriteToken,
0342       void (boost::system::error_code, std::size_t)>(
0343         initiate_async_write_some(this), token, buffers);
0344   }
0345 
0346   /// Read some data from the handle.
0347   /**
0348    * This function is used to read data from the stream handle. The function
0349    * call will block until one or more bytes of data has been read successfully,
0350    * or until an error occurs.
0351    *
0352    * @param buffers One or more buffers into which the data will be read.
0353    *
0354    * @returns The number of bytes read.
0355    *
0356    * @throws boost::system::system_error Thrown on failure. An error code of
0357    * boost::asio::error::eof indicates that the connection was closed by the
0358    * peer.
0359    *
0360    * @note The read_some operation may not read all of the requested number of
0361    * bytes. Consider using the @ref read function if you need to ensure that
0362    * the requested amount of data is read before the blocking operation
0363    * completes.
0364    *
0365    * @par Example
0366    * To read into a single data buffer use the @ref buffer function as follows:
0367    * @code
0368    * handle.read_some(boost::asio::buffer(data, size));
0369    * @endcode
0370    * See the @ref buffer documentation for information on reading into multiple
0371    * buffers in one go, and how to use it with arrays, boost::array or
0372    * std::vector.
0373    */
0374   template <typename MutableBufferSequence>
0375   std::size_t read_some(const MutableBufferSequence& buffers)
0376   {
0377     boost::system::error_code ec;
0378     std::size_t s = this->impl_.get_service().read_some(
0379         this->impl_.get_implementation(), buffers, ec);
0380     boost::asio::detail::throw_error(ec, "read_some");
0381     return s;
0382   }
0383 
0384   /// Read some data from the handle.
0385   /**
0386    * This function is used to read data from the stream handle. The function
0387    * call will block until one or more bytes of data has been read successfully,
0388    * or until an error occurs.
0389    *
0390    * @param buffers One or more buffers into which the data will be read.
0391    *
0392    * @param ec Set to indicate what error occurred, if any.
0393    *
0394    * @returns The number of bytes read. Returns 0 if an error occurred.
0395    *
0396    * @note The read_some operation may not read all of the requested number of
0397    * bytes. Consider using the @ref read function if you need to ensure that
0398    * the requested amount of data is read before the blocking operation
0399    * completes.
0400    */
0401   template <typename MutableBufferSequence>
0402   std::size_t read_some(const MutableBufferSequence& buffers,
0403       boost::system::error_code& ec)
0404   {
0405     return this->impl_.get_service().read_some(
0406         this->impl_.get_implementation(), buffers, ec);
0407   }
0408 
0409   /// Start an asynchronous read.
0410   /**
0411    * This function is used to asynchronously read data from the stream handle.
0412    * It is an initiating function for an @ref asynchronous_operation, and always
0413    * returns immediately.
0414    *
0415    * @param buffers One or more buffers into which the data will be read.
0416    * Although the buffers object may be copied as necessary, ownership of the
0417    * underlying memory blocks is retained by the caller, which must guarantee
0418    * that they remain valid until the completion handler is called.
0419    *
0420    * @param token The @ref completion_token that will be used to produce a
0421    * completion handler, which will be called when the read completes.
0422    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0423    * @ref yield_context, or a function object with the correct completion
0424    * signature. The function signature of the completion handler must be:
0425    * @code void handler(
0426    *   const boost::system::error_code& error, // Result of operation.
0427    *   std::size_t bytes_transferred // Number of bytes read.
0428    * ); @endcode
0429    * Regardless of whether the asynchronous operation completes immediately or
0430    * not, the completion handler will not be invoked from within this function.
0431    * On immediate completion, invocation of the handler will be performed in a
0432    * manner equivalent to using boost::asio::post().
0433    *
0434    * @par Completion Signature
0435    * @code void(boost::system::error_code, std::size_t) @endcode
0436    *
0437    * @note The read operation may not read all of the requested number of bytes.
0438    * Consider using the @ref async_read function if you need to ensure that the
0439    * requested amount of data is read before the asynchronous operation
0440    * completes.
0441    *
0442    * @par Example
0443    * To read into a single data buffer use the @ref buffer function as follows:
0444    * @code
0445    * handle.async_read_some(boost::asio::buffer(data, size), handler);
0446    * @endcode
0447    * See the @ref buffer documentation for information on reading into multiple
0448    * buffers in one go, and how to use it with arrays, boost::array or
0449    * std::vector.
0450    *
0451    * @par Per-Operation Cancellation
0452    * This asynchronous operation supports cancellation for the following
0453    * boost::asio::cancellation_type values:
0454    *
0455    * @li @c cancellation_type::terminal
0456    *
0457    * @li @c cancellation_type::partial
0458    *
0459    * @li @c cancellation_type::total
0460    */
0461   template <typename MutableBufferSequence,
0462       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0463         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0464   auto async_read_some(const MutableBufferSequence& buffers,
0465       ReadToken&& token = default_completion_token_t<executor_type>())
0466     -> decltype(
0467       async_initiate<ReadToken,
0468         void (boost::system::error_code, std::size_t)>(
0469           declval<initiate_async_read_some>(), token, buffers))
0470   {
0471     return async_initiate<ReadToken,
0472       void (boost::system::error_code, std::size_t)>(
0473         initiate_async_read_some(this), token, buffers);
0474   }
0475 
0476 private:
0477   class initiate_async_write_some
0478   {
0479   public:
0480     typedef Executor executor_type;
0481 
0482     explicit initiate_async_write_some(basic_stream_handle* self)
0483       : self_(self)
0484     {
0485     }
0486 
0487     const executor_type& get_executor() const noexcept
0488     {
0489       return self_->get_executor();
0490     }
0491 
0492     template <typename WriteHandler, typename ConstBufferSequence>
0493     void operator()(WriteHandler&& handler,
0494         const ConstBufferSequence& buffers) const
0495     {
0496       // If you get an error on the following line it means that your handler
0497       // does not meet the documented type requirements for a WriteHandler.
0498       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0499 
0500       detail::non_const_lvalue<WriteHandler> handler2(handler);
0501       self_->impl_.get_service().async_write_some(
0502           self_->impl_.get_implementation(), buffers,
0503           handler2.value, self_->impl_.get_executor());
0504     }
0505 
0506   private:
0507     basic_stream_handle* self_;
0508   };
0509 
0510   class initiate_async_read_some
0511   {
0512   public:
0513     typedef Executor executor_type;
0514 
0515     explicit initiate_async_read_some(basic_stream_handle* self)
0516       : self_(self)
0517     {
0518     }
0519 
0520     const executor_type& get_executor() const noexcept
0521     {
0522       return self_->get_executor();
0523     }
0524 
0525     template <typename ReadHandler, typename MutableBufferSequence>
0526     void operator()(ReadHandler&& handler,
0527         const MutableBufferSequence& buffers) const
0528     {
0529       // If you get an error on the following line it means that your handler
0530       // does not meet the documented type requirements for a ReadHandler.
0531       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0532 
0533       detail::non_const_lvalue<ReadHandler> handler2(handler);
0534       self_->impl_.get_service().async_read_some(
0535           self_->impl_.get_implementation(), buffers,
0536           handler2.value, self_->impl_.get_executor());
0537     }
0538 
0539   private:
0540     basic_stream_handle* self_;
0541   };
0542 };
0543 
0544 } // namespace windows
0545 } // namespace asio
0546 } // namespace boost
0547 
0548 #include <boost/asio/detail/pop_options.hpp>
0549 
0550 #endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
0551        //   || defined(GENERATING_DOCUMENTATION)
0552 
0553 #endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP