2 // windows/basic_stream_handle.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
12 #define BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/windows/basic_overlapped_handle.hpp>
21 #if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
22 || defined(GENERATING_DOCUMENTATION)
24 #include <boost/asio/detail/push_options.hpp>
30 /// Provides stream-oriented handle functionality.
32 * The windows::basic_stream_handle class provides asynchronous and blocking
33 * stream-oriented handle functionality.
36 * @e Distinct @e objects: Safe.@n
37 * @e Shared @e objects: Unsafe.
40 * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
42 template <typename Executor = any_io_executor>
43 class basic_stream_handle
44 : public basic_overlapped_handle<Executor>
47 /// The type of the executor associated with the object.
48 typedef Executor executor_type;
50 /// Rebinds the handle type to another executor.
51 template <typename Executor1>
52 struct rebind_executor
54 /// The handle type when rebound to the specified executor.
55 typedef basic_stream_handle<Executor1> other;
58 /// The native representation of a handle.
59 #if defined(GENERATING_DOCUMENTATION)
60 typedef implementation_defined native_handle_type;
62 typedef boost::asio::detail::win_iocp_handle_service::native_handle_type
66 /// Construct a stream handle without opening it.
68 * This constructor creates a stream handle without opening it.
70 * @param ex The I/O executor that the stream handle will use, by default, to
71 * dispatch handlers for any asynchronous operations performed on the stream
74 explicit basic_stream_handle(const executor_type& ex)
75 : basic_overlapped_handle<Executor>(ex)
79 /// Construct a stream handle without opening it.
81 * This constructor creates a stream handle without opening it. The handle
82 * needs to be opened or assigned before data can be written to or read from
85 * @param context An execution context which provides the I/O executor that
86 * the stream handle will use, by default, to dispatch handlers for any
87 * asynchronous operations performed on the stream handle.
89 template <typename ExecutionContext>
90 explicit basic_stream_handle(ExecutionContext& context,
92 is_convertible<ExecutionContext&, execution_context&>::value,
94 >::type = defaulted_constraint())
95 : basic_overlapped_handle<Executor>(context)
99 /// Construct a stream handle on an existing native handle.
101 * This constructor creates a stream handle object to hold an existing native
104 * @param ex The I/O executor that the stream handle will use, by default, to
105 * dispatch handlers for any asynchronous operations performed on the stream
108 * @param handle The new underlying handle implementation.
110 * @throws boost::system::system_error Thrown on failure.
112 basic_stream_handle(const executor_type& ex, const native_handle_type& handle)
113 : basic_overlapped_handle<Executor>(ex, handle)
117 /// Construct a stream handle on an existing native handle.
119 * This constructor creates a stream handle object to hold an existing native
122 * @param context An execution context which provides the I/O executor that
123 * the stream handle will use, by default, to dispatch handlers for any
124 * asynchronous operations performed on the stream handle.
126 * @param handle The new underlying handle implementation.
128 * @throws boost::system::system_error Thrown on failure.
130 template <typename ExecutionContext>
131 basic_stream_handle(ExecutionContext& context,
132 const native_handle_type& handle,
134 is_convertible<ExecutionContext&, execution_context&>::value
136 : basic_overlapped_handle<Executor>(context, handle)
140 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
141 /// Move-construct a stream handle from another.
143 * This constructor moves a stream handle from one object to another.
145 * @param other The other stream handle object from which the move
148 * @note Following the move, the moved-from object is in the same state as if
149 * constructed using the @c basic_stream_handle(const executor_type&)
152 basic_stream_handle(basic_stream_handle&& other)
153 : basic_overlapped_handle<Executor>(std::move(other))
157 /// Move-assign a stream handle from another.
159 * This assignment operator moves a stream handle from one object to
162 * @param other The other stream handle object from which the move will occur.
164 * @note Following the move, the moved-from object is in the same state as if
165 * constructed using the @c basic_stream_handle(const executor_type&)
168 basic_stream_handle& operator=(basic_stream_handle&& other)
170 basic_overlapped_handle<Executor>::operator=(std::move(other));
173 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
175 /// Write some data to the handle.
177 * This function is used to write data to the stream handle. The function call
178 * will block until one or more bytes of the data has been written
179 * successfully, or until an error occurs.
181 * @param buffers One or more data buffers to be written to the handle.
183 * @returns The number of bytes written.
185 * @throws boost::system::system_error Thrown on failure. An error code of
186 * boost::asio::error::eof indicates that the connection was closed by the
189 * @note The write_some operation may not transmit all of the data to the
190 * peer. Consider using the @ref write function if you need to ensure that
191 * all data is written before the blocking operation completes.
194 * To write a single data buffer use the @ref buffer function as follows:
196 * handle.write_some(boost::asio::buffer(data, size));
198 * See the @ref buffer documentation for information on writing multiple
199 * buffers in one go, and how to use it with arrays, boost::array or
202 template <typename ConstBufferSequence>
203 std::size_t write_some(const ConstBufferSequence& buffers)
205 boost::system::error_code ec;
206 std::size_t s = this->impl_.get_service().write_some(
207 this->impl_.get_implementation(), buffers, ec);
208 boost::asio::detail::throw_error(ec, "write_some");
212 /// Write some data to the handle.
214 * This function is used to write data to the stream handle. The function call
215 * will block until one or more bytes of the data has been written
216 * successfully, or until an error occurs.
218 * @param buffers One or more data buffers to be written to the handle.
220 * @param ec Set to indicate what error occurred, if any.
222 * @returns The number of bytes written. Returns 0 if an error occurred.
224 * @note The write_some operation may not transmit all of the data to the
225 * peer. Consider using the @ref write function if you need to ensure that
226 * all data is written before the blocking operation completes.
228 template <typename ConstBufferSequence>
229 std::size_t write_some(const ConstBufferSequence& buffers,
230 boost::system::error_code& ec)
232 return this->impl_.get_service().write_some(
233 this->impl_.get_implementation(), buffers, ec);
236 /// Start an asynchronous write.
238 * This function is used to asynchronously write data to the stream handle.
239 * It is an initiating function for an @ref asynchronous_operation, and always
240 * returns immediately.
242 * @param buffers One or more data buffers to be written to the handle.
243 * Although the buffers object may be copied as necessary, ownership of the
244 * underlying memory blocks is retained by the caller, which must guarantee
245 * that they remain valid until the completion handler is called.
247 * @param token The @ref completion_token that will be used to produce a
248 * completion handler, which will be called when the write completes.
249 * Potential completion tokens include @ref use_future, @ref use_awaitable,
250 * @ref yield_context, or a function object with the correct completion
251 * signature. The function signature of the completion handler must be:
252 * @code void handler(
253 * const boost::system::error_code& error, // Result of operation.
254 * std::size_t bytes_transferred // Number of bytes written.
256 * Regardless of whether the asynchronous operation completes immediately or
257 * not, the completion handler will not be invoked from within this function.
258 * On immediate completion, invocation of the handler will be performed in a
259 * manner equivalent to using boost::asio::post().
261 * @par Completion Signature
262 * @code void(boost::system::error_code, std::size_t) @endcode
264 * @note The write operation may not transmit all of the data to the peer.
265 * Consider using the @ref async_write function if you need to ensure that all
266 * data is written before the asynchronous operation completes.
269 * To write a single data buffer use the @ref buffer function as follows:
271 * handle.async_write_some(boost::asio::buffer(data, size), handler);
273 * See the @ref buffer documentation for information on writing multiple
274 * buffers in one go, and how to use it with arrays, boost::array or
277 * @par Per-Operation Cancellation
278 * This asynchronous operation supports cancellation for the following
279 * boost::asio::cancellation_type values:
281 * @li @c cancellation_type::terminal
283 * @li @c cancellation_type::partial
285 * @li @c cancellation_type::total
287 template <typename ConstBufferSequence,
288 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
289 std::size_t)) WriteToken
290 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
291 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteToken,
292 void (boost::system::error_code, std::size_t))
293 async_write_some(const ConstBufferSequence& buffers,
294 BOOST_ASIO_MOVE_ARG(WriteToken) token
295 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
297 return async_initiate<WriteToken,
298 void (boost::system::error_code, std::size_t)>(
299 initiate_async_write_some(this), token, buffers);
302 /// Read some data from the handle.
304 * This function is used to read data from the stream handle. The function
305 * call will block until one or more bytes of data has been read successfully,
306 * or until an error occurs.
308 * @param buffers One or more buffers into which the data will be read.
310 * @returns The number of bytes read.
312 * @throws boost::system::system_error Thrown on failure. An error code of
313 * boost::asio::error::eof indicates that the connection was closed by the
316 * @note The read_some operation may not read all of the requested number of
317 * bytes. Consider using the @ref read function if you need to ensure that
318 * the requested amount of data is read before the blocking operation
322 * To read into a single data buffer use the @ref buffer function as follows:
324 * handle.read_some(boost::asio::buffer(data, size));
326 * See the @ref buffer documentation for information on reading into multiple
327 * buffers in one go, and how to use it with arrays, boost::array or
330 template <typename MutableBufferSequence>
331 std::size_t read_some(const MutableBufferSequence& buffers)
333 boost::system::error_code ec;
334 std::size_t s = this->impl_.get_service().read_some(
335 this->impl_.get_implementation(), buffers, ec);
336 boost::asio::detail::throw_error(ec, "read_some");
340 /// Read some data from the handle.
342 * This function is used to read data from the stream handle. The function
343 * call will block until one or more bytes of data has been read successfully,
344 * or until an error occurs.
346 * @param buffers One or more buffers into which the data will be read.
348 * @param ec Set to indicate what error occurred, if any.
350 * @returns The number of bytes read. Returns 0 if an error occurred.
352 * @note The read_some operation may not read all of the requested number of
353 * bytes. Consider using the @ref read function if you need to ensure that
354 * the requested amount of data is read before the blocking operation
357 template <typename MutableBufferSequence>
358 std::size_t read_some(const MutableBufferSequence& buffers,
359 boost::system::error_code& ec)
361 return this->impl_.get_service().read_some(
362 this->impl_.get_implementation(), buffers, ec);
365 /// Start an asynchronous read.
367 * This function is used to asynchronously read data from the stream handle.
368 * It is an initiating function for an @ref asynchronous_operation, and always
369 * returns immediately.
371 * @param buffers One or more buffers into which the data will be read.
372 * Although the buffers object may be copied as necessary, ownership of the
373 * underlying memory blocks is retained by the caller, which must guarantee
374 * that they remain valid until the completion handler is called.
376 * @param token The @ref completion_token that will be used to produce a
377 * completion handler, which will be called when the read completes.
378 * Potential completion tokens include @ref use_future, @ref use_awaitable,
379 * @ref yield_context, or a function object with the correct completion
380 * signature. The function signature of the completion handler must be:
381 * @code void handler(
382 * const boost::system::error_code& error, // Result of operation.
383 * std::size_t bytes_transferred // Number of bytes read.
385 * Regardless of whether the asynchronous operation completes immediately or
386 * not, the completion handler will not be invoked from within this function.
387 * On immediate completion, invocation of the handler will be performed in a
388 * manner equivalent to using boost::asio::post().
390 * @par Completion Signature
391 * @code void(boost::system::error_code, std::size_t) @endcode
393 * @note The read operation may not read all of the requested number of bytes.
394 * Consider using the @ref async_read function if you need to ensure that the
395 * requested amount of data is read before the asynchronous operation
399 * To read into a single data buffer use the @ref buffer function as follows:
401 * handle.async_read_some(boost::asio::buffer(data, size), handler);
403 * See the @ref buffer documentation for information on reading into multiple
404 * buffers in one go, and how to use it with arrays, boost::array or
407 * @par Per-Operation Cancellation
408 * This asynchronous operation supports cancellation for the following
409 * boost::asio::cancellation_type values:
411 * @li @c cancellation_type::terminal
413 * @li @c cancellation_type::partial
415 * @li @c cancellation_type::total
417 template <typename MutableBufferSequence,
418 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
419 std::size_t)) ReadToken
420 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
421 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
422 void (boost::system::error_code, std::size_t))
423 async_read_some(const MutableBufferSequence& buffers,
424 BOOST_ASIO_MOVE_ARG(ReadToken) token
425 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
427 return async_initiate<ReadToken,
428 void (boost::system::error_code, std::size_t)>(
429 initiate_async_read_some(this), token, buffers);
433 class initiate_async_write_some
436 typedef Executor executor_type;
438 explicit initiate_async_write_some(basic_stream_handle* self)
443 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
445 return self_->get_executor();
448 template <typename WriteHandler, typename ConstBufferSequence>
449 void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
450 const ConstBufferSequence& buffers) const
452 // If you get an error on the following line it means that your handler
453 // does not meet the documented type requirements for a WriteHandler.
454 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
456 detail::non_const_lvalue<WriteHandler> handler2(handler);
457 self_->impl_.get_service().async_write_some(
458 self_->impl_.get_implementation(), buffers,
459 handler2.value, self_->impl_.get_executor());
463 basic_stream_handle* self_;
466 class initiate_async_read_some
469 typedef Executor executor_type;
471 explicit initiate_async_read_some(basic_stream_handle* self)
476 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
478 return self_->get_executor();
481 template <typename ReadHandler, typename MutableBufferSequence>
482 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
483 const MutableBufferSequence& buffers) const
485 // If you get an error on the following line it means that your handler
486 // does not meet the documented type requirements for a ReadHandler.
487 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
489 detail::non_const_lvalue<ReadHandler> handler2(handler);
490 self_->impl_.get_service().async_read_some(
491 self_->impl_.get_implementation(), buffers,
492 handler2.value, self_->impl_.get_executor());
496 basic_stream_handle* self_;
500 } // namespace windows
504 #include <boost/asio/detail/pop_options.hpp>
506 #endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
507 // || defined(GENERATING_DOCUMENTATION)
509 #endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP