Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / asio / windows / basic_stream_handle.hpp
1 //
2 // windows/basic_stream_handle.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
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)
9 //
10
11 #ifndef BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
12 #define BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
13
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/windows/basic_overlapped_handle.hpp>
20
21 #if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
22   || defined(GENERATING_DOCUMENTATION)
23
24 #include <boost/asio/detail/push_options.hpp>
25
26 namespace boost {
27 namespace asio {
28 namespace windows {
29
30 /// Provides stream-oriented handle functionality.
31 /**
32  * The windows::basic_stream_handle class provides asynchronous and blocking
33  * stream-oriented handle functionality.
34  *
35  * @par Thread Safety
36  * @e Distinct @e objects: Safe.@n
37  * @e Shared @e objects: Unsafe.
38  *
39  * @par Concepts:
40  * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
41  */
42 template <typename Executor = executor>
43 class basic_stream_handle
44   : public basic_overlapped_handle<Executor>
45 {
46 public:
47   /// The type of the executor associated with the object.
48   typedef Executor executor_type;
49
50   /// Rebinds the handle type to another executor.
51   template <typename Executor1>
52   struct rebind_executor
53   {
54     /// The handle type when rebound to the specified executor.
55     typedef basic_stream_handle<Executor1> other;
56   };
57
58   /// The native representation of a handle.
59 #if defined(GENERATING_DOCUMENTATION)
60   typedef implementation_defined native_handle_type;
61 #else
62   typedef boost::asio::detail::win_iocp_handle_service::native_handle_type
63     native_handle_type;
64 #endif
65
66   /// Construct a stream handle without opening it.
67   /**
68    * This constructor creates a stream handle without opening it.
69    *
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
72    * handle.
73    */
74   explicit basic_stream_handle(const executor_type& ex)
75     : basic_overlapped_handle<Executor>(ex)
76   {
77   }
78
79   /// Construct a stream handle without opening it.
80   /**
81    * This constructor creates a stream handle without opening it. The handle
82    * needs to be opened or assigned before data can be sent or received on it.
83    *
84    * @param context An execution context which provides the I/O executor that
85    * the stream handle will use, by default, to dispatch handlers for any
86    * asynchronous operations performed on the stream handle.
87    */
88   template <typename ExecutionContext>
89   explicit basic_stream_handle(ExecutionContext& context,
90       typename enable_if<
91         is_convertible<ExecutionContext&, execution_context&>::value,
92         basic_stream_handle
93       >::type* = 0)
94     : basic_overlapped_handle<Executor>(context)
95   {
96   }
97
98   /// Construct a stream handle on an existing native handle.
99   /**
100    * This constructor creates a stream handle object to hold an existing native
101    * handle.
102    *
103    * @param ex The I/O executor that the stream handle will use, by default, to
104    * dispatch handlers for any asynchronous operations performed on the stream
105    * handle.
106    *
107    * @param handle The new underlying handle implementation.
108    *
109    * @throws boost::system::system_error Thrown on failure.
110    */
111   basic_stream_handle(const executor_type& ex, const native_handle_type& handle)
112     : basic_overlapped_handle<Executor>(ex, handle)
113   {
114   }
115
116   /// Construct a stream handle on an existing native handle.
117   /**
118    * This constructor creates a stream handle object to hold an existing native
119    * handle.
120    *
121    * @param context An execution context which provides the I/O executor that
122    * the stream handle will use, by default, to dispatch handlers for any
123    * asynchronous operations performed on the stream handle.
124    *
125    * @param handle The new underlying handle implementation.
126    *
127    * @throws boost::system::system_error Thrown on failure.
128    */
129   template <typename ExecutionContext>
130   basic_stream_handle(ExecutionContext& context,
131       const native_handle_type& handle,
132       typename enable_if<
133         is_convertible<ExecutionContext&, execution_context&>::value
134       >::type* = 0)
135     : basic_overlapped_handle<Executor>(context, handle)
136   {
137   }
138
139 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
140   /// Move-construct a stream handle from another.
141   /**
142    * This constructor moves a stream handle from one object to another.
143    *
144    * @param other The other stream handle object from which the move
145    * will occur.
146    *
147    * @note Following the move, the moved-from object is in the same state as if
148    * constructed using the @c basic_stream_handle(const executor_type&)
149    * constructor.
150    */
151   basic_stream_handle(basic_stream_handle&& other)
152     : basic_overlapped_handle<Executor>(std::move(other))
153   {
154   }
155
156   /// Move-assign a stream handle from another.
157   /**
158    * This assignment operator moves a stream handle from one object to
159    * another.
160    *
161    * @param other The other stream handle object from which the move will occur.
162    *
163    * @note Following the move, the moved-from object is in the same state as if
164    * constructed using the @c basic_stream_handle(const executor_type&)
165    * constructor.
166    */
167   basic_stream_handle& operator=(basic_stream_handle&& other)
168   {
169     basic_overlapped_handle<Executor>::operator=(std::move(other));
170     return *this;
171   }
172 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
173
174   /// Write some data to the handle.
175   /**
176    * This function is used to write data to the stream handle. The function call
177    * will block until one or more bytes of the data has been written
178    * successfully, or until an error occurs.
179    *
180    * @param buffers One or more data buffers to be written to the handle.
181    *
182    * @returns The number of bytes written.
183    *
184    * @throws boost::system::system_error Thrown on failure. An error code of
185    * boost::asio::error::eof indicates that the connection was closed by the
186    * peer.
187    *
188    * @note The write_some operation may not transmit all of the data to the
189    * peer. Consider using the @ref write function if you need to ensure that
190    * all data is written before the blocking operation completes.
191    *
192    * @par Example
193    * To write a single data buffer use the @ref buffer function as follows:
194    * @code
195    * handle.write_some(boost::asio::buffer(data, size));
196    * @endcode
197    * See the @ref buffer documentation for information on writing multiple
198    * buffers in one go, and how to use it with arrays, boost::array or
199    * std::vector.
200    */
201   template <typename ConstBufferSequence>
202   std::size_t write_some(const ConstBufferSequence& buffers)
203   {
204     boost::system::error_code ec;
205     std::size_t s = this->impl_.get_service().write_some(
206         this->impl_.get_implementation(), buffers, ec);
207     boost::asio::detail::throw_error(ec, "write_some");
208     return s;
209   }
210
211   /// Write some data to the handle.
212   /**
213    * This function is used to write data to the stream handle. The function call
214    * will block until one or more bytes of the data has been written
215    * successfully, or until an error occurs.
216    *
217    * @param buffers One or more data buffers to be written to the handle.
218    *
219    * @param ec Set to indicate what error occurred, if any.
220    *
221    * @returns The number of bytes written. Returns 0 if an error occurred.
222    *
223    * @note The write_some operation may not transmit all of the data to the
224    * peer. Consider using the @ref write function if you need to ensure that
225    * all data is written before the blocking operation completes.
226    */
227   template <typename ConstBufferSequence>
228   std::size_t write_some(const ConstBufferSequence& buffers,
229       boost::system::error_code& ec)
230   {
231     return this->impl_.get_service().write_some(
232         this->impl_.get_implementation(), buffers, ec);
233   }
234
235   /// Start an asynchronous write.
236   /**
237    * This function is used to asynchronously write data to the stream handle.
238    * The function call always returns immediately.
239    *
240    * @param buffers One or more data buffers to be written to the handle.
241    * Although the buffers object may be copied as necessary, ownership of the
242    * underlying memory blocks is retained by the caller, which must guarantee
243    * that they remain valid until the handler is called.
244    *
245    * @param handler The handler to be called when the write operation completes.
246    * Copies will be made of the handler as required. The function signature of
247    * the handler must be:
248    * @code void handler(
249    *   const boost::system::error_code& error, // Result of operation.
250    *   std::size_t bytes_transferred           // Number of bytes written.
251    * ); @endcode
252    * Regardless of whether the asynchronous operation completes immediately or
253    * not, the handler will not be invoked from within this function. On
254    * immediate completion, invocation of the handler will be performed in a
255    * manner equivalent to using boost::asio::post().
256    *
257    * @note The write operation may not transmit all of the data to the peer.
258    * Consider using the @ref async_write function if you need to ensure that all
259    * data is written before the asynchronous operation completes.
260    *
261    * @par Example
262    * To write a single data buffer use the @ref buffer function as follows:
263    * @code
264    * handle.async_write_some(boost::asio::buffer(data, size), handler);
265    * @endcode
266    * See the @ref buffer documentation for information on writing multiple
267    * buffers in one go, and how to use it with arrays, boost::array or
268    * std::vector.
269    */
270   template <typename ConstBufferSequence,
271       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
272         std::size_t)) WriteHandler
273           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
274   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
275       void (boost::system::error_code, std::size_t))
276   async_write_some(const ConstBufferSequence& buffers,
277       BOOST_ASIO_MOVE_ARG(WriteHandler) handler
278         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
279   {
280     return async_initiate<WriteHandler,
281       void (boost::system::error_code, std::size_t)>(
282         initiate_async_write_some(this), handler, buffers);
283   }
284
285   /// Read some data from the handle.
286   /**
287    * This function is used to read data from the stream handle. The function
288    * call will block until one or more bytes of data has been read successfully,
289    * or until an error occurs.
290    *
291    * @param buffers One or more buffers into which the data will be read.
292    *
293    * @returns The number of bytes read.
294    *
295    * @throws boost::system::system_error Thrown on failure. An error code of
296    * boost::asio::error::eof indicates that the connection was closed by the
297    * peer.
298    *
299    * @note The read_some operation may not read all of the requested number of
300    * bytes. Consider using the @ref read function if you need to ensure that
301    * the requested amount of data is read before the blocking operation
302    * completes.
303    *
304    * @par Example
305    * To read into a single data buffer use the @ref buffer function as follows:
306    * @code
307    * handle.read_some(boost::asio::buffer(data, size));
308    * @endcode
309    * See the @ref buffer documentation for information on reading into multiple
310    * buffers in one go, and how to use it with arrays, boost::array or
311    * std::vector.
312    */
313   template <typename MutableBufferSequence>
314   std::size_t read_some(const MutableBufferSequence& buffers)
315   {
316     boost::system::error_code ec;
317     std::size_t s = this->impl_.get_service().read_some(
318         this->impl_.get_implementation(), buffers, ec);
319     boost::asio::detail::throw_error(ec, "read_some");
320     return s;
321   }
322
323   /// Read some data from the handle.
324   /**
325    * This function is used to read data from the stream handle. The function
326    * call will block until one or more bytes of data has been read successfully,
327    * or until an error occurs.
328    *
329    * @param buffers One or more buffers into which the data will be read.
330    *
331    * @param ec Set to indicate what error occurred, if any.
332    *
333    * @returns The number of bytes read. Returns 0 if an error occurred.
334    *
335    * @note The read_some operation may not read all of the requested number of
336    * bytes. Consider using the @ref read function if you need to ensure that
337    * the requested amount of data is read before the blocking operation
338    * completes.
339    */
340   template <typename MutableBufferSequence>
341   std::size_t read_some(const MutableBufferSequence& buffers,
342       boost::system::error_code& ec)
343   {
344     return this->impl_.get_service().read_some(
345         this->impl_.get_implementation(), buffers, ec);
346   }
347
348   /// Start an asynchronous read.
349   /**
350    * This function is used to asynchronously read data from the stream handle.
351    * The function call always returns immediately.
352    *
353    * @param buffers One or more buffers into which the data will be read.
354    * Although the buffers object may be copied as necessary, ownership of the
355    * underlying memory blocks is retained by the caller, which must guarantee
356    * that they remain valid until the handler is called.
357    *
358    * @param handler The handler to be called when the read operation completes.
359    * Copies will be made of the handler as required. The function signature of
360    * the handler must be:
361    * @code void handler(
362    *   const boost::system::error_code& error, // Result of operation.
363    *   std::size_t bytes_transferred           // Number of bytes read.
364    * ); @endcode
365    * Regardless of whether the asynchronous operation completes immediately or
366    * not, the handler will not be invoked from within this function. On
367    * immediate completion, invocation of the handler will be performed in a
368    * manner equivalent to using boost::asio::post().
369    *
370    * @note The read operation may not read all of the requested number of bytes.
371    * Consider using the @ref async_read function if you need to ensure that the
372    * requested amount of data is read before the asynchronous operation
373    * completes.
374    *
375    * @par Example
376    * To read into a single data buffer use the @ref buffer function as follows:
377    * @code
378    * handle.async_read_some(boost::asio::buffer(data, size), handler);
379    * @endcode
380    * See the @ref buffer documentation for information on reading into multiple
381    * buffers in one go, and how to use it with arrays, boost::array or
382    * std::vector.
383    */
384   template <typename MutableBufferSequence,
385       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
386         std::size_t)) ReadHandler
387           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
388   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
389       void (boost::system::error_code, std::size_t))
390   async_read_some(const MutableBufferSequence& buffers,
391       BOOST_ASIO_MOVE_ARG(ReadHandler) handler
392         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
393   {
394     return async_initiate<ReadHandler,
395       void (boost::system::error_code, std::size_t)>(
396         initiate_async_read_some(this), handler, buffers);
397   }
398
399 private:
400   class initiate_async_write_some
401   {
402   public:
403     typedef Executor executor_type;
404
405     explicit initiate_async_write_some(basic_stream_handle* self)
406       : self_(self)
407     {
408     }
409
410     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
411     {
412       return self_->get_executor();
413     }
414
415     template <typename WriteHandler, typename ConstBufferSequence>
416     void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
417         const ConstBufferSequence& buffers) const
418     {
419       // If you get an error on the following line it means that your handler
420       // does not meet the documented type requirements for a WriteHandler.
421       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
422
423       detail::non_const_lvalue<WriteHandler> handler2(handler);
424       self_->impl_.get_service().async_write_some(
425           self_->impl_.get_implementation(), buffers, handler2.value,
426           self_->impl_.get_implementation_executor());
427     }
428
429   private:
430     basic_stream_handle* self_;
431   };
432
433   class initiate_async_read_some
434   {
435   public:
436     typedef Executor executor_type;
437
438     explicit initiate_async_read_some(basic_stream_handle* self)
439       : self_(self)
440     {
441     }
442
443     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
444     {
445       return self_->get_executor();
446     }
447
448     template <typename ReadHandler, typename MutableBufferSequence>
449     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
450         const MutableBufferSequence& buffers) const
451     {
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 ReadHandler.
454       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
455
456       detail::non_const_lvalue<ReadHandler> handler2(handler);
457       self_->impl_.get_service().async_read_some(
458           self_->impl_.get_implementation(), buffers, handler2.value,
459           self_->impl_.get_implementation_executor());
460     }
461
462   private:
463     basic_stream_handle* self_;
464   };
465 };
466
467 } // namespace windows
468 } // namespace asio
469 } // namespace boost
470
471 #include <boost/asio/detail/pop_options.hpp>
472
473 #endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
474        //   || defined(GENERATING_DOCUMENTATION)
475
476 #endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP