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