Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / asio / basic_seq_packet_socket.hpp
1 //
2 // basic_seq_packet_socket.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_BASIC_SEQ_PACKET_SOCKET_HPP
12 #define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_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 <cstddef>
20 #include <boost/asio/basic_socket.hpp>
21 #include <boost/asio/detail/handler_type_requirements.hpp>
22 #include <boost/asio/detail/throw_error.hpp>
23 #include <boost/asio/error.hpp>
24
25 #include <boost/asio/detail/push_options.hpp>
26
27 namespace boost {
28 namespace asio {
29
30 #if !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
31 #define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL
32
33 // Forward declaration with defaulted arguments.
34 template <typename Protocol, typename Executor = executor>
35 class basic_seq_packet_socket;
36
37 #endif // !defined(BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_FWD_DECL)
38
39 /// Provides sequenced packet socket functionality.
40 /**
41  * The basic_seq_packet_socket class template provides asynchronous and blocking
42  * sequenced packet socket functionality.
43  *
44  * @par Thread Safety
45  * @e Distinct @e objects: Safe.@n
46  * @e Shared @e objects: Unsafe.
47  */
48 template <typename Protocol, typename Executor>
49 class basic_seq_packet_socket
50   : public basic_socket<Protocol, Executor>
51 {
52 public:
53   /// The type of the executor associated with the object.
54   typedef Executor executor_type;
55
56   /// Rebinds the socket type to another executor.
57   template <typename Executor1>
58   struct rebind_executor
59   {
60     /// The socket type when rebound to the specified executor.
61     typedef basic_seq_packet_socket<Protocol, Executor1> other;
62   };
63
64   /// The native representation of a socket.
65 #if defined(GENERATING_DOCUMENTATION)
66   typedef implementation_defined native_handle_type;
67 #else
68   typedef typename basic_socket<Protocol,
69     Executor>::native_handle_type native_handle_type;
70 #endif
71
72   /// The protocol type.
73   typedef Protocol protocol_type;
74
75   /// The endpoint type.
76   typedef typename Protocol::endpoint endpoint_type;
77
78   /// Construct a basic_seq_packet_socket without opening it.
79   /**
80    * This constructor creates a sequenced packet socket without opening it. The
81    * socket needs to be opened and then connected or accepted before data can
82    * be sent or received on it.
83    *
84    * @param ex The I/O executor that the socket will use, by default, to
85    * dispatch handlers for any asynchronous operations performed on the socket.
86    */
87   explicit basic_seq_packet_socket(const executor_type& ex)
88     : basic_socket<Protocol, Executor>(ex)
89   {
90   }
91
92   /// Construct a basic_seq_packet_socket without opening it.
93   /**
94    * This constructor creates a sequenced packet socket without opening it. The
95    * socket needs to be opened and then connected or accepted before data can
96    * be sent or received on it.
97    *
98    * @param context An execution context which provides the I/O executor that
99    * the socket will use, by default, to dispatch handlers for any asynchronous
100    * operations performed on the socket.
101    */
102   template <typename ExecutionContext>
103   explicit basic_seq_packet_socket(ExecutionContext& context,
104       typename enable_if<
105         is_convertible<ExecutionContext&, execution_context&>::value
106       >::type* = 0)
107     : basic_socket<Protocol, Executor>(context)
108   {
109   }
110
111   /// Construct and open a basic_seq_packet_socket.
112   /**
113    * This constructor creates and opens a sequenced_packet socket. The socket
114    * needs to be connected or accepted before data can be sent or received on
115    * it.
116    *
117    * @param ex The I/O executor that the socket will use, by default, to
118    * dispatch handlers for any asynchronous operations performed on the socket.
119    *
120    * @param protocol An object specifying protocol parameters to be used.
121    *
122    * @throws boost::system::system_error Thrown on failure.
123    */
124   basic_seq_packet_socket(const executor_type& ex,
125       const protocol_type& protocol)
126     : basic_socket<Protocol, Executor>(ex, protocol)
127   {
128   }
129
130   /// Construct and open a basic_seq_packet_socket.
131   /**
132    * This constructor creates and opens a sequenced_packet socket. The socket
133    * needs to be connected or accepted before data can be sent or received on
134    * it.
135    *
136    * @param context An execution context which provides the I/O executor that
137    * the socket will use, by default, to dispatch handlers for any asynchronous
138    * operations performed on the socket.
139    *
140    * @param protocol An object specifying protocol parameters to be used.
141    *
142    * @throws boost::system::system_error Thrown on failure.
143    */
144   template <typename ExecutionContext>
145   basic_seq_packet_socket(ExecutionContext& context,
146       const protocol_type& protocol,
147       typename enable_if<
148         is_convertible<ExecutionContext&, execution_context&>::value
149       >::type* = 0)
150     : basic_socket<Protocol, Executor>(context, protocol)
151   {
152   }
153
154   /// Construct a basic_seq_packet_socket, opening it and binding it to the
155   /// given local endpoint.
156   /**
157    * This constructor creates a sequenced packet socket and automatically opens
158    * it bound to the specified endpoint on the local machine. The protocol used
159    * is the protocol associated with the given endpoint.
160    *
161    * @param ex The I/O executor that the socket will use, by default, to
162    * dispatch handlers for any asynchronous operations performed on the socket.
163    *
164    * @param endpoint An endpoint on the local machine to which the sequenced
165    * packet socket will be bound.
166    *
167    * @throws boost::system::system_error Thrown on failure.
168    */
169   basic_seq_packet_socket(const executor_type& ex,
170       const endpoint_type& endpoint)
171     : basic_socket<Protocol, Executor>(ex, endpoint)
172   {
173   }
174
175   /// Construct a basic_seq_packet_socket, opening it and binding it to the
176   /// given local endpoint.
177   /**
178    * This constructor creates a sequenced packet socket and automatically opens
179    * it bound to the specified endpoint on the local machine. The protocol used
180    * is the protocol associated with the given endpoint.
181    *
182    * @param context An execution context which provides the I/O executor that
183    * the socket will use, by default, to dispatch handlers for any asynchronous
184    * operations performed on the socket.
185    *
186    * @param endpoint An endpoint on the local machine to which the sequenced
187    * packet socket will be bound.
188    *
189    * @throws boost::system::system_error Thrown on failure.
190    */
191   template <typename ExecutionContext>
192   basic_seq_packet_socket(ExecutionContext& context,
193       const endpoint_type& endpoint,
194       typename enable_if<
195         is_convertible<ExecutionContext&, execution_context&>::value
196       >::type* = 0)
197     : basic_socket<Protocol, Executor>(context, endpoint)
198   {
199   }
200
201   /// Construct a basic_seq_packet_socket on an existing native socket.
202   /**
203    * This constructor creates a sequenced packet socket object to hold an
204    * existing native socket.
205    *
206    * @param ex The I/O executor that the socket will use, by default, to
207    * dispatch handlers for any asynchronous operations performed on the socket.
208    *
209    * @param protocol An object specifying protocol parameters to be used.
210    *
211    * @param native_socket The new underlying socket implementation.
212    *
213    * @throws boost::system::system_error Thrown on failure.
214    */
215   basic_seq_packet_socket(const executor_type& ex,
216       const protocol_type& protocol, const native_handle_type& native_socket)
217     : basic_socket<Protocol, Executor>(ex, protocol, native_socket)
218   {
219   }
220
221   /// Construct a basic_seq_packet_socket on an existing native socket.
222   /**
223    * This constructor creates a sequenced packet socket object to hold an
224    * existing native socket.
225    *
226    * @param context An execution context which provides the I/O executor that
227    * the socket will use, by default, to dispatch handlers for any asynchronous
228    * operations performed on the socket.
229    *
230    * @param protocol An object specifying protocol parameters to be used.
231    *
232    * @param native_socket The new underlying socket implementation.
233    *
234    * @throws boost::system::system_error Thrown on failure.
235    */
236   template <typename ExecutionContext>
237   basic_seq_packet_socket(ExecutionContext& context,
238       const protocol_type& protocol, const native_handle_type& native_socket,
239       typename enable_if<
240         is_convertible<ExecutionContext&, execution_context&>::value
241       >::type* = 0)
242     : basic_socket<Protocol, Executor>(context, protocol, native_socket)
243   {
244   }
245
246 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
247   /// Move-construct a basic_seq_packet_socket from another.
248   /**
249    * This constructor moves a sequenced packet socket from one object to
250    * another.
251    *
252    * @param other The other basic_seq_packet_socket object from which the move
253    * will occur.
254    *
255    * @note Following the move, the moved-from object is in the same state as if
256    * constructed using the @c basic_seq_packet_socket(const executor_type&)
257    * constructor.
258    */
259   basic_seq_packet_socket(basic_seq_packet_socket&& other) BOOST_ASIO_NOEXCEPT
260     : basic_socket<Protocol, Executor>(std::move(other))
261   {
262   }
263
264   /// Move-assign a basic_seq_packet_socket from another.
265   /**
266    * This assignment operator moves a sequenced packet socket from one object to
267    * another.
268    *
269    * @param other The other basic_seq_packet_socket object from which the move
270    * will occur.
271    *
272    * @note Following the move, the moved-from object is in the same state as if
273    * constructed using the @c basic_seq_packet_socket(const executor_type&)
274    * constructor.
275    */
276   basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
277   {
278     basic_socket<Protocol, Executor>::operator=(std::move(other));
279     return *this;
280   }
281
282   /// Move-construct a basic_seq_packet_socket from a socket of another protocol
283   /// type.
284   /**
285    * This constructor moves a sequenced packet socket from one object to
286    * another.
287    *
288    * @param other The other basic_seq_packet_socket object from which the move
289    * will occur.
290    *
291    * @note Following the move, the moved-from object is in the same state as if
292    * constructed using the @c basic_seq_packet_socket(const executor_type&)
293    * constructor.
294    */
295   template <typename Protocol1, typename Executor1>
296   basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,
297       typename enable_if<
298         is_convertible<Protocol1, Protocol>::value
299           && is_convertible<Executor1, Executor>::value
300       >::type* = 0)
301     : basic_socket<Protocol, Executor>(std::move(other))
302   {
303   }
304
305   /// Move-assign a basic_seq_packet_socket from a socket of another protocol
306   /// type.
307   /**
308    * This assignment operator moves a sequenced packet socket from one object to
309    * another.
310    *
311    * @param other The other basic_seq_packet_socket object from which the move
312    * will occur.
313    *
314    * @note Following the move, the moved-from object is in the same state as if
315    * constructed using the @c basic_seq_packet_socket(const executor_type&)
316    * constructor.
317    */
318   template <typename Protocol1, typename Executor1>
319   typename enable_if<
320     is_convertible<Protocol1, Protocol>::value
321       && is_convertible<Executor1, Executor>::value,
322     basic_seq_packet_socket&
323   >::type operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other)
324   {
325     basic_socket<Protocol, Executor>::operator=(std::move(other));
326     return *this;
327   }
328 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
329
330   /// Destroys the socket.
331   /**
332    * This function destroys the socket, cancelling any outstanding asynchronous
333    * operations associated with the socket as if by calling @c cancel.
334    */
335   ~basic_seq_packet_socket()
336   {
337   }
338
339   /// Send some data on the socket.
340   /**
341    * This function is used to send data on the sequenced packet socket. The
342    * function call will block until the data has been sent successfully, or an
343    * until error occurs.
344    *
345    * @param buffers One or more data buffers to be sent on the socket.
346    *
347    * @param flags Flags specifying how the send call is to be made.
348    *
349    * @returns The number of bytes sent.
350    *
351    * @throws boost::system::system_error Thrown on failure.
352    *
353    * @par Example
354    * To send a single data buffer use the @ref buffer function as follows:
355    * @code
356    * socket.send(boost::asio::buffer(data, size), 0);
357    * @endcode
358    * See the @ref buffer documentation for information on sending multiple
359    * buffers in one go, and how to use it with arrays, boost::array or
360    * std::vector.
361    */
362   template <typename ConstBufferSequence>
363   std::size_t send(const ConstBufferSequence& buffers,
364       socket_base::message_flags flags)
365   {
366     boost::system::error_code ec;
367     std::size_t s = this->impl_.get_service().send(
368         this->impl_.get_implementation(), buffers, flags, ec);
369     boost::asio::detail::throw_error(ec, "send");
370     return s;
371   }
372
373   /// Send some data on the socket.
374   /**
375    * This function is used to send data on the sequenced packet socket. The
376    * function call will block the data has been sent successfully, or an until
377    * error occurs.
378    *
379    * @param buffers One or more data buffers to be sent on the socket.
380    *
381    * @param flags Flags specifying how the send call is to be made.
382    *
383    * @param ec Set to indicate what error occurred, if any.
384    *
385    * @returns The number of bytes sent. Returns 0 if an error occurred.
386    *
387    * @note The send operation may not transmit all of the data to the peer.
388    * Consider using the @ref write function if you need to ensure that all data
389    * is written before the blocking operation completes.
390    */
391   template <typename ConstBufferSequence>
392   std::size_t send(const ConstBufferSequence& buffers,
393       socket_base::message_flags flags, boost::system::error_code& ec)
394   {
395     return this->impl_.get_service().send(
396         this->impl_.get_implementation(), buffers, flags, ec);
397   }
398
399   /// Start an asynchronous send.
400   /**
401    * This function is used to asynchronously send data on the sequenced packet
402    * socket. The function call always returns immediately.
403    *
404    * @param buffers One or more data buffers to be sent on the socket. Although
405    * the buffers object may be copied as necessary, ownership of the underlying
406    * memory blocks is retained by the caller, which must guarantee that they
407    * remain valid until the handler is called.
408    *
409    * @param flags Flags specifying how the send call is to be made.
410    *
411    * @param handler The handler to be called when the send operation completes.
412    * Copies will be made of the handler as required. The function signature of
413    * the handler must be:
414    * @code void handler(
415    *   const boost::system::error_code& error, // Result of operation.
416    *   std::size_t bytes_transferred           // Number of bytes sent.
417    * ); @endcode
418    * Regardless of whether the asynchronous operation completes immediately or
419    * not, the handler will not be invoked from within this function. On
420    * immediate completion, invocation of the handler will be performed in a
421    * manner equivalent to using boost::asio::post().
422    *
423    * @par Example
424    * To send a single data buffer use the @ref buffer function as follows:
425    * @code
426    * socket.async_send(boost::asio::buffer(data, size), 0, handler);
427    * @endcode
428    * See the @ref buffer documentation for information on sending multiple
429    * buffers in one go, and how to use it with arrays, boost::array or
430    * std::vector.
431    */
432   template <typename ConstBufferSequence,
433       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
434         std::size_t)) WriteHandler
435           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
436   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
437       void (boost::system::error_code, std::size_t))
438   async_send(const ConstBufferSequence& buffers,
439       socket_base::message_flags flags,
440       BOOST_ASIO_MOVE_ARG(WriteHandler) handler
441         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
442   {
443     return async_initiate<WriteHandler,
444       void (boost::system::error_code, std::size_t)>(
445         initiate_async_send(this), handler, buffers, flags);
446   }
447
448   /// Receive some data on the socket.
449   /**
450    * This function is used to receive data on the sequenced packet socket. The
451    * function call will block until data has been received successfully, or
452    * until an error occurs.
453    *
454    * @param buffers One or more buffers into which the data will be received.
455    *
456    * @param out_flags After the receive call completes, contains flags
457    * associated with the received data. For example, if the
458    * socket_base::message_end_of_record bit is set then the received data marks
459    * the end of a record.
460    *
461    * @returns The number of bytes received.
462    *
463    * @throws boost::system::system_error Thrown on failure. An error code of
464    * boost::asio::error::eof indicates that the connection was closed by the
465    * peer.
466    *
467    * @par Example
468    * To receive into a single data buffer use the @ref buffer function as
469    * follows:
470    * @code
471    * socket.receive(boost::asio::buffer(data, size), out_flags);
472    * @endcode
473    * See the @ref buffer documentation for information on receiving into
474    * multiple buffers in one go, and how to use it with arrays, boost::array or
475    * std::vector.
476    */
477   template <typename MutableBufferSequence>
478   std::size_t receive(const MutableBufferSequence& buffers,
479       socket_base::message_flags& out_flags)
480   {
481     boost::system::error_code ec;
482     std::size_t s = this->impl_.get_service().receive_with_flags(
483         this->impl_.get_implementation(), buffers, 0, out_flags, ec);
484     boost::asio::detail::throw_error(ec, "receive");
485     return s;
486   }
487
488   /// Receive some data on the socket.
489   /**
490    * This function is used to receive data on the sequenced packet socket. The
491    * function call will block until data has been received successfully, or
492    * until an error occurs.
493    *
494    * @param buffers One or more buffers into which the data will be received.
495    *
496    * @param in_flags Flags specifying how the receive call is to be made.
497    *
498    * @param out_flags After the receive call completes, contains flags
499    * associated with the received data. For example, if the
500    * socket_base::message_end_of_record bit is set then the received data marks
501    * the end of a record.
502    *
503    * @returns The number of bytes received.
504    *
505    * @throws boost::system::system_error Thrown on failure. An error code of
506    * boost::asio::error::eof indicates that the connection was closed by the
507    * peer.
508    *
509    * @note The receive operation may not receive all of the requested number of
510    * bytes. Consider using the @ref read function if you need to ensure that the
511    * requested amount of data is read before the blocking operation completes.
512    *
513    * @par Example
514    * To receive into a single data buffer use the @ref buffer function as
515    * follows:
516    * @code
517    * socket.receive(boost::asio::buffer(data, size), 0, out_flags);
518    * @endcode
519    * See the @ref buffer documentation for information on receiving into
520    * multiple buffers in one go, and how to use it with arrays, boost::array or
521    * std::vector.
522    */
523   template <typename MutableBufferSequence>
524   std::size_t receive(const MutableBufferSequence& buffers,
525       socket_base::message_flags in_flags,
526       socket_base::message_flags& out_flags)
527   {
528     boost::system::error_code ec;
529     std::size_t s = this->impl_.get_service().receive_with_flags(
530         this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
531     boost::asio::detail::throw_error(ec, "receive");
532     return s;
533   }
534
535   /// Receive some data on a connected socket.
536   /**
537    * This function is used to receive data on the sequenced packet socket. The
538    * function call will block until data has been received successfully, or
539    * until an error occurs.
540    *
541    * @param buffers One or more buffers into which the data will be received.
542    *
543    * @param in_flags Flags specifying how the receive call is to be made.
544    *
545    * @param out_flags After the receive call completes, contains flags
546    * associated with the received data. For example, if the
547    * socket_base::message_end_of_record bit is set then the received data marks
548    * the end of a record.
549    *
550    * @param ec Set to indicate what error occurred, if any.
551    *
552    * @returns The number of bytes received. Returns 0 if an error occurred.
553    *
554    * @note The receive operation may not receive all of the requested number of
555    * bytes. Consider using the @ref read function if you need to ensure that the
556    * requested amount of data is read before the blocking operation completes.
557    */
558   template <typename MutableBufferSequence>
559   std::size_t receive(const MutableBufferSequence& buffers,
560       socket_base::message_flags in_flags,
561       socket_base::message_flags& out_flags, boost::system::error_code& ec)
562   {
563     return this->impl_.get_service().receive_with_flags(
564         this->impl_.get_implementation(), buffers, in_flags, out_flags, ec);
565   }
566
567   /// Start an asynchronous receive.
568   /**
569    * This function is used to asynchronously receive data from the sequenced
570    * packet socket. The function call always returns immediately.
571    *
572    * @param buffers One or more buffers into which the data will be received.
573    * Although the buffers object may be copied as necessary, ownership of the
574    * underlying memory blocks is retained by the caller, which must guarantee
575    * that they remain valid until the handler is called.
576    *
577    * @param out_flags Once the asynchronous operation completes, contains flags
578    * associated with the received data. For example, if the
579    * socket_base::message_end_of_record bit is set then the received data marks
580    * the end of a record. The caller must guarantee that the referenced
581    * variable remains valid until the handler is called.
582    *
583    * @param handler The handler to be called when the receive operation
584    * completes. Copies will be made of the handler as required. The function
585    * signature of the handler must be:
586    * @code void handler(
587    *   const boost::system::error_code& error, // Result of operation.
588    *   std::size_t bytes_transferred           // Number of bytes received.
589    * ); @endcode
590    * Regardless of whether the asynchronous operation completes immediately or
591    * not, the handler will not be invoked from within this function. On
592    * immediate completion, invocation of the handler will be performed in a
593    * manner equivalent to using boost::asio::post().
594    *
595    * @par Example
596    * To receive into a single data buffer use the @ref buffer function as
597    * follows:
598    * @code
599    * socket.async_receive(boost::asio::buffer(data, size), out_flags, handler);
600    * @endcode
601    * See the @ref buffer documentation for information on receiving into
602    * multiple buffers in one go, and how to use it with arrays, boost::array or
603    * std::vector.
604    */
605   template <typename MutableBufferSequence,
606       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
607         std::size_t)) ReadHandler
608           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
609   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
610       void (boost::system::error_code, std::size_t))
611   async_receive(const MutableBufferSequence& buffers,
612       socket_base::message_flags& out_flags,
613       BOOST_ASIO_MOVE_ARG(ReadHandler) handler
614         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
615   {
616     return async_initiate<ReadHandler,
617       void (boost::system::error_code, std::size_t)>(
618         initiate_async_receive_with_flags(this), handler,
619         buffers, socket_base::message_flags(0), &out_flags);
620   }
621
622   /// Start an asynchronous receive.
623   /**
624    * This function is used to asynchronously receive data from the sequenced
625    * data socket. The function call always returns immediately.
626    *
627    * @param buffers One or more buffers into which the data will be received.
628    * Although the buffers object may be copied as necessary, ownership of the
629    * underlying memory blocks is retained by the caller, which must guarantee
630    * that they remain valid until the handler is called.
631    *
632    * @param in_flags Flags specifying how the receive call is to be made.
633    *
634    * @param out_flags Once the asynchronous operation completes, contains flags
635    * associated with the received data. For example, if the
636    * socket_base::message_end_of_record bit is set then the received data marks
637    * the end of a record. The caller must guarantee that the referenced
638    * variable remains valid until the handler is called.
639    *
640    * @param handler The handler to be called when the receive operation
641    * completes. Copies will be made of the handler as required. The function
642    * signature of the handler must be:
643    * @code void handler(
644    *   const boost::system::error_code& error, // Result of operation.
645    *   std::size_t bytes_transferred           // Number of bytes received.
646    * ); @endcode
647    * Regardless of whether the asynchronous operation completes immediately or
648    * not, the handler will not be invoked from within this function. On
649    * immediate completion, invocation of the handler will be performed in a
650    * manner equivalent to using boost::asio::post().
651    *
652    * @par Example
653    * To receive into a single data buffer use the @ref buffer function as
654    * follows:
655    * @code
656    * socket.async_receive(
657    *     boost::asio::buffer(data, size),
658    *     0, out_flags, handler);
659    * @endcode
660    * See the @ref buffer documentation for information on receiving into
661    * multiple buffers in one go, and how to use it with arrays, boost::array or
662    * std::vector.
663    */
664   template <typename MutableBufferSequence,
665       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
666         std::size_t)) ReadHandler
667           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
668   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
669       void (boost::system::error_code, std::size_t))
670   async_receive(const MutableBufferSequence& buffers,
671       socket_base::message_flags in_flags,
672       socket_base::message_flags& out_flags,
673       BOOST_ASIO_MOVE_ARG(ReadHandler) handler
674         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
675   {
676     return async_initiate<ReadHandler,
677       void (boost::system::error_code, std::size_t)>(
678         initiate_async_receive_with_flags(this),
679         handler, buffers, in_flags, &out_flags);
680   }
681
682 private:
683   class initiate_async_send
684   {
685   public:
686     typedef Executor executor_type;
687
688     explicit initiate_async_send(basic_seq_packet_socket* self)
689       : self_(self)
690     {
691     }
692
693     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
694     {
695       return self_->get_executor();
696     }
697
698     template <typename WriteHandler, typename ConstBufferSequence>
699     void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
700         const ConstBufferSequence& buffers,
701         socket_base::message_flags flags) const
702     {
703       // If you get an error on the following line it means that your handler
704       // does not meet the documented type requirements for a WriteHandler.
705       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
706
707       detail::non_const_lvalue<WriteHandler> handler2(handler);
708       self_->impl_.get_service().async_send(
709           self_->impl_.get_implementation(), buffers, flags,
710           handler2.value, self_->impl_.get_implementation_executor());
711     }
712
713   private:
714     basic_seq_packet_socket* self_;
715   };
716
717   class initiate_async_receive_with_flags
718   {
719   public:
720     typedef Executor executor_type;
721
722     explicit initiate_async_receive_with_flags(basic_seq_packet_socket* self)
723       : self_(self)
724     {
725     }
726
727     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
728     {
729       return self_->get_executor();
730     }
731
732     template <typename ReadHandler, typename MutableBufferSequence>
733     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
734         const MutableBufferSequence& buffers,
735         socket_base::message_flags in_flags,
736         socket_base::message_flags* out_flags) const
737     {
738       // If you get an error on the following line it means that your handler
739       // does not meet the documented type requirements for a ReadHandler.
740       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
741
742       detail::non_const_lvalue<ReadHandler> handler2(handler);
743       self_->impl_.get_service().async_receive_with_flags(
744           self_->impl_.get_implementation(), buffers, in_flags, *out_flags,
745           handler2.value, self_->impl_.get_implementation_executor());
746     }
747
748   private:
749     basic_seq_packet_socket* self_;
750   };
751 };
752
753 } // namespace asio
754 } // namespace boost
755
756 #include <boost/asio/detail/pop_options.hpp>
757
758 #endif // BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP