Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / asio / basic_serial_port.hpp
1 //
2 // basic_serial_port.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 //
11
12 #ifndef BOOST_ASIO_BASIC_SERIAL_PORT_HPP
13 #define BOOST_ASIO_BASIC_SERIAL_PORT_HPP
14
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 # pragma once
17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18
19 #include <boost/asio/detail/config.hpp>
20
21 #if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
22   || defined(GENERATING_DOCUMENTATION)
23
24 #include <string>
25 #include <boost/asio/async_result.hpp>
26 #include <boost/asio/detail/handler_type_requirements.hpp>
27 #include <boost/asio/detail/io_object_impl.hpp>
28 #include <boost/asio/detail/non_const_lvalue.hpp>
29 #include <boost/asio/detail/throw_error.hpp>
30 #include <boost/asio/detail/type_traits.hpp>
31 #include <boost/asio/error.hpp>
32 #include <boost/asio/execution_context.hpp>
33 #include <boost/asio/executor.hpp>
34 #include <boost/asio/serial_port_base.hpp>
35 #if defined(BOOST_ASIO_HAS_IOCP)
36 # include <boost/asio/detail/win_iocp_serial_port_service.hpp>
37 #else
38 # include <boost/asio/detail/reactive_serial_port_service.hpp>
39 #endif
40
41 #if defined(BOOST_ASIO_HAS_MOVE)
42 # include <utility>
43 #endif // defined(BOOST_ASIO_HAS_MOVE)
44
45 #include <boost/asio/detail/push_options.hpp>
46
47 namespace boost {
48 namespace asio {
49
50 /// Provides serial port functionality.
51 /**
52  * The basic_serial_port class provides a wrapper over serial port
53  * functionality.
54  *
55  * @par Thread Safety
56  * @e Distinct @e objects: Safe.@n
57  * @e Shared @e objects: Unsafe.
58  */
59 template <typename Executor = executor>
60 class basic_serial_port
61   : public serial_port_base
62 {
63 public:
64   /// The type of the executor associated with the object.
65   typedef Executor executor_type;
66
67   /// Rebinds the serial port type to another executor.
68   template <typename Executor1>
69   struct rebind_executor
70   {
71     /// The serial port type when rebound to the specified executor.
72     typedef basic_serial_port<Executor1> other;
73   };
74
75   /// The native representation of a serial port.
76 #if defined(GENERATING_DOCUMENTATION)
77   typedef implementation_defined native_handle_type;
78 #elif defined(BOOST_ASIO_HAS_IOCP)
79   typedef detail::win_iocp_serial_port_service::native_handle_type
80     native_handle_type;
81 #else
82   typedef detail::reactive_serial_port_service::native_handle_type
83     native_handle_type;
84 #endif
85
86   /// A basic_basic_serial_port is always the lowest layer.
87   typedef basic_serial_port lowest_layer_type;
88
89   /// Construct a basic_serial_port without opening it.
90   /**
91    * This constructor creates a serial port without opening it.
92    *
93    * @param ex The I/O executor that the serial port will use, by default, to
94    * dispatch handlers for any asynchronous operations performed on the
95    * serial port.
96    */
97   explicit basic_serial_port(const executor_type& ex)
98     : impl_(ex)
99   {
100   }
101
102   /// Construct a basic_serial_port without opening it.
103   /**
104    * This constructor creates a serial port without opening it.
105    *
106    * @param context An execution context which provides the I/O executor that
107    * the serial port will use, by default, to dispatch handlers for any
108    * asynchronous operations performed on the serial port.
109    */
110   template <typename ExecutionContext>
111   explicit basic_serial_port(ExecutionContext& context,
112       typename enable_if<
113         is_convertible<ExecutionContext&, execution_context&>::value,
114         basic_serial_port
115       >::type* = 0)
116     : impl_(context)
117   {
118   }
119
120   /// Construct and open a basic_serial_port.
121   /**
122    * This constructor creates and opens a serial port for the specified device
123    * name.
124    *
125    * @param ex The I/O executor that the serial port will use, by default, to
126    * dispatch handlers for any asynchronous operations performed on the
127    * serial port.
128    *
129    * @param device The platform-specific device name for this serial
130    * port.
131    */
132   basic_serial_port(const executor_type& ex, const char* device)
133     : impl_(ex)
134   {
135     boost::system::error_code ec;
136     impl_.get_service().open(impl_.get_implementation(), device, ec);
137     boost::asio::detail::throw_error(ec, "open");
138   }
139
140   /// Construct and open a basic_serial_port.
141   /**
142    * This constructor creates and opens a serial port for the specified device
143    * name.
144    *
145    * @param context An execution context which provides the I/O executor that
146    * the serial port will use, by default, to dispatch handlers for any
147    * asynchronous operations performed on the serial port.
148    *
149    * @param device The platform-specific device name for this serial
150    * port.
151    */
152   template <typename ExecutionContext>
153   basic_serial_port(ExecutionContext& context, const char* device,
154       typename enable_if<
155         is_convertible<ExecutionContext&, execution_context&>::value
156       >::type* = 0)
157     : impl_(context)
158   {
159     boost::system::error_code ec;
160     impl_.get_service().open(impl_.get_implementation(), device, ec);
161     boost::asio::detail::throw_error(ec, "open");
162   }
163
164   /// Construct and open a basic_serial_port.
165   /**
166    * This constructor creates and opens a serial port for the specified device
167    * name.
168    *
169    * @param ex The I/O executor that the serial port will use, by default, to
170    * dispatch handlers for any asynchronous operations performed on the
171    * serial port.
172    *
173    * @param device The platform-specific device name for this serial
174    * port.
175    */
176   basic_serial_port(const executor_type& ex, const std::string& device)
177     : impl_(ex)
178   {
179     boost::system::error_code ec;
180     impl_.get_service().open(impl_.get_implementation(), device, ec);
181     boost::asio::detail::throw_error(ec, "open");
182   }
183
184   /// Construct and open a basic_serial_port.
185   /**
186    * This constructor creates and opens a serial port for the specified device
187    * name.
188    *
189    * @param context An execution context which provides the I/O executor that
190    * the serial port will use, by default, to dispatch handlers for any
191    * asynchronous operations performed on the serial port.
192    *
193    * @param device The platform-specific device name for this serial
194    * port.
195    */
196   template <typename ExecutionContext>
197   basic_serial_port(ExecutionContext& context, const std::string& device,
198       typename enable_if<
199         is_convertible<ExecutionContext&, execution_context&>::value
200       >::type* = 0)
201     : impl_(context)
202   {
203     boost::system::error_code ec;
204     impl_.get_service().open(impl_.get_implementation(), device, ec);
205     boost::asio::detail::throw_error(ec, "open");
206   }
207
208   /// Construct a basic_serial_port on an existing native serial port.
209   /**
210    * This constructor creates a serial port object to hold an existing native
211    * serial port.
212    *
213    * @param ex The I/O executor that the serial port will use, by default, to
214    * dispatch handlers for any asynchronous operations performed on the
215    * serial port.
216    *
217    * @param native_serial_port A native serial port.
218    *
219    * @throws boost::system::system_error Thrown on failure.
220    */
221   basic_serial_port(const executor_type& ex,
222       const native_handle_type& native_serial_port)
223     : impl_(ex)
224   {
225     boost::system::error_code ec;
226     impl_.get_service().assign(impl_.get_implementation(),
227         native_serial_port, ec);
228     boost::asio::detail::throw_error(ec, "assign");
229   }
230
231   /// Construct a basic_serial_port on an existing native serial port.
232   /**
233    * This constructor creates a serial port object to hold an existing native
234    * serial port.
235    *
236    * @param context An execution context which provides the I/O executor that
237    * the serial port will use, by default, to dispatch handlers for any
238    * asynchronous operations performed on the serial port.
239    *
240    * @param native_serial_port A native serial port.
241    *
242    * @throws boost::system::system_error Thrown on failure.
243    */
244   template <typename ExecutionContext>
245   basic_serial_port(ExecutionContext& context,
246       const native_handle_type& native_serial_port,
247       typename enable_if<
248         is_convertible<ExecutionContext&, execution_context&>::value
249       >::type* = 0)
250     : impl_(context)
251   {
252     boost::system::error_code ec;
253     impl_.get_service().assign(impl_.get_implementation(),
254         native_serial_port, ec);
255     boost::asio::detail::throw_error(ec, "assign");
256   }
257
258 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
259   /// Move-construct a basic_serial_port from another.
260   /**
261    * This constructor moves a serial port from one object to another.
262    *
263    * @param other The other basic_serial_port object from which the move will
264    * occur.
265    *
266    * @note Following the move, the moved-from object is in the same state as if
267    * constructed using the @c basic_serial_port(const executor_type&)
268    * constructor.
269    */
270   basic_serial_port(basic_serial_port&& other)
271     : impl_(std::move(other.impl_))
272   {
273   }
274
275   /// Move-assign a basic_serial_port from another.
276   /**
277    * This assignment operator moves a serial port from one object to another.
278    *
279    * @param other The other basic_serial_port object from which the move will
280    * occur.
281    *
282    * @note Following the move, the moved-from object is in the same state as if
283    * constructed using the @c basic_serial_port(const executor_type&)
284    * constructor.
285    */
286   basic_serial_port& operator=(basic_serial_port&& other)
287   {
288     impl_ = std::move(other.impl_);
289     return *this;
290   }
291 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
292
293   /// Destroys the serial port.
294   /**
295    * This function destroys the serial port, cancelling any outstanding
296    * asynchronous wait operations associated with the serial port as if by
297    * calling @c cancel.
298    */
299   ~basic_serial_port()
300   {
301   }
302
303   /// Get the executor associated with the object.
304   executor_type get_executor() BOOST_ASIO_NOEXCEPT
305   {
306     return impl_.get_executor();
307   }
308
309   /// Get a reference to the lowest layer.
310   /**
311    * This function returns a reference to the lowest layer in a stack of
312    * layers. Since a basic_serial_port cannot contain any further layers, it
313    * simply returns a reference to itself.
314    *
315    * @return A reference to the lowest layer in the stack of layers. Ownership
316    * is not transferred to the caller.
317    */
318   lowest_layer_type& lowest_layer()
319   {
320     return *this;
321   }
322
323   /// Get a const reference to the lowest layer.
324   /**
325    * This function returns a const reference to the lowest layer in a stack of
326    * layers. Since a basic_serial_port cannot contain any further layers, it
327    * simply returns a reference to itself.
328    *
329    * @return A const reference to the lowest layer in the stack of layers.
330    * Ownership is not transferred to the caller.
331    */
332   const lowest_layer_type& lowest_layer() const
333   {
334     return *this;
335   }
336
337   /// Open the serial port using the specified device name.
338   /**
339    * This function opens the serial port for the specified device name.
340    *
341    * @param device The platform-specific device name.
342    *
343    * @throws boost::system::system_error Thrown on failure.
344    */
345   void open(const std::string& device)
346   {
347     boost::system::error_code ec;
348     impl_.get_service().open(impl_.get_implementation(), device, ec);
349     boost::asio::detail::throw_error(ec, "open");
350   }
351
352   /// Open the serial port using the specified device name.
353   /**
354    * This function opens the serial port using the given platform-specific
355    * device name.
356    *
357    * @param device The platform-specific device name.
358    *
359    * @param ec Set the indicate what error occurred, if any.
360    */
361   BOOST_ASIO_SYNC_OP_VOID open(const std::string& device,
362       boost::system::error_code& ec)
363   {
364     impl_.get_service().open(impl_.get_implementation(), device, ec);
365     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
366   }
367
368   /// Assign an existing native serial port to the serial port.
369   /*
370    * This function opens the serial port to hold an existing native serial port.
371    *
372    * @param native_serial_port A native serial port.
373    *
374    * @throws boost::system::system_error Thrown on failure.
375    */
376   void assign(const native_handle_type& native_serial_port)
377   {
378     boost::system::error_code ec;
379     impl_.get_service().assign(impl_.get_implementation(),
380         native_serial_port, ec);
381     boost::asio::detail::throw_error(ec, "assign");
382   }
383
384   /// Assign an existing native serial port to the serial port.
385   /*
386    * This function opens the serial port to hold an existing native serial port.
387    *
388    * @param native_serial_port A native serial port.
389    *
390    * @param ec Set to indicate what error occurred, if any.
391    */
392   BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port,
393       boost::system::error_code& ec)
394   {
395     impl_.get_service().assign(impl_.get_implementation(),
396         native_serial_port, ec);
397     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
398   }
399
400   /// Determine whether the serial port is open.
401   bool is_open() const
402   {
403     return impl_.get_service().is_open(impl_.get_implementation());
404   }
405
406   /// Close the serial port.
407   /**
408    * This function is used to close the serial port. Any asynchronous read or
409    * write operations will be cancelled immediately, and will complete with the
410    * boost::asio::error::operation_aborted error.
411    *
412    * @throws boost::system::system_error Thrown on failure.
413    */
414   void close()
415   {
416     boost::system::error_code ec;
417     impl_.get_service().close(impl_.get_implementation(), ec);
418     boost::asio::detail::throw_error(ec, "close");
419   }
420
421   /// Close the serial port.
422   /**
423    * This function is used to close the serial port. Any asynchronous read or
424    * write operations will be cancelled immediately, and will complete with the
425    * boost::asio::error::operation_aborted error.
426    *
427    * @param ec Set to indicate what error occurred, if any.
428    */
429   BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
430   {
431     impl_.get_service().close(impl_.get_implementation(), ec);
432     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
433   }
434
435   /// Get the native serial port representation.
436   /**
437    * This function may be used to obtain the underlying representation of the
438    * serial port. This is intended to allow access to native serial port
439    * functionality that is not otherwise provided.
440    */
441   native_handle_type native_handle()
442   {
443     return impl_.get_service().native_handle(impl_.get_implementation());
444   }
445
446   /// Cancel all asynchronous operations associated with the serial port.
447   /**
448    * This function causes all outstanding asynchronous read or write operations
449    * to finish immediately, and the handlers for cancelled operations will be
450    * passed the boost::asio::error::operation_aborted error.
451    *
452    * @throws boost::system::system_error Thrown on failure.
453    */
454   void cancel()
455   {
456     boost::system::error_code ec;
457     impl_.get_service().cancel(impl_.get_implementation(), ec);
458     boost::asio::detail::throw_error(ec, "cancel");
459   }
460
461   /// Cancel all asynchronous operations associated with the serial port.
462   /**
463    * This function causes all outstanding asynchronous read or write operations
464    * to finish immediately, and the handlers for cancelled operations will be
465    * passed the boost::asio::error::operation_aborted error.
466    *
467    * @param ec Set to indicate what error occurred, if any.
468    */
469   BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
470   {
471     impl_.get_service().cancel(impl_.get_implementation(), ec);
472     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
473   }
474
475   /// Send a break sequence to the serial port.
476   /**
477    * This function causes a break sequence of platform-specific duration to be
478    * sent out the serial port.
479    *
480    * @throws boost::system::system_error Thrown on failure.
481    */
482   void send_break()
483   {
484     boost::system::error_code ec;
485     impl_.get_service().send_break(impl_.get_implementation(), ec);
486     boost::asio::detail::throw_error(ec, "send_break");
487   }
488
489   /// Send a break sequence to the serial port.
490   /**
491    * This function causes a break sequence of platform-specific duration to be
492    * sent out the serial port.
493    *
494    * @param ec Set to indicate what error occurred, if any.
495    */
496   BOOST_ASIO_SYNC_OP_VOID send_break(boost::system::error_code& ec)
497   {
498     impl_.get_service().send_break(impl_.get_implementation(), ec);
499     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
500   }
501
502   /// Set an option on the serial port.
503   /**
504    * This function is used to set an option on the serial port.
505    *
506    * @param option The option value to be set on the serial port.
507    *
508    * @throws boost::system::system_error Thrown on failure.
509    *
510    * @sa SettableSerialPortOption @n
511    * boost::asio::serial_port_base::baud_rate @n
512    * boost::asio::serial_port_base::flow_control @n
513    * boost::asio::serial_port_base::parity @n
514    * boost::asio::serial_port_base::stop_bits @n
515    * boost::asio::serial_port_base::character_size
516    */
517   template <typename SettableSerialPortOption>
518   void set_option(const SettableSerialPortOption& option)
519   {
520     boost::system::error_code ec;
521     impl_.get_service().set_option(impl_.get_implementation(), option, ec);
522     boost::asio::detail::throw_error(ec, "set_option");
523   }
524
525   /// Set an option on the serial port.
526   /**
527    * This function is used to set an option on the serial port.
528    *
529    * @param option The option value to be set on the serial port.
530    *
531    * @param ec Set to indicate what error occurred, if any.
532    *
533    * @sa SettableSerialPortOption @n
534    * boost::asio::serial_port_base::baud_rate @n
535    * boost::asio::serial_port_base::flow_control @n
536    * boost::asio::serial_port_base::parity @n
537    * boost::asio::serial_port_base::stop_bits @n
538    * boost::asio::serial_port_base::character_size
539    */
540   template <typename SettableSerialPortOption>
541   BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option,
542       boost::system::error_code& ec)
543   {
544     impl_.get_service().set_option(impl_.get_implementation(), option, ec);
545     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
546   }
547
548   /// Get an option from the serial port.
549   /**
550    * This function is used to get the current value of an option on the serial
551    * port.
552    *
553    * @param option The option value to be obtained from the serial port.
554    *
555    * @throws boost::system::system_error Thrown on failure.
556    *
557    * @sa GettableSerialPortOption @n
558    * boost::asio::serial_port_base::baud_rate @n
559    * boost::asio::serial_port_base::flow_control @n
560    * boost::asio::serial_port_base::parity @n
561    * boost::asio::serial_port_base::stop_bits @n
562    * boost::asio::serial_port_base::character_size
563    */
564   template <typename GettableSerialPortOption>
565   void get_option(GettableSerialPortOption& option) const
566   {
567     boost::system::error_code ec;
568     impl_.get_service().get_option(impl_.get_implementation(), option, ec);
569     boost::asio::detail::throw_error(ec, "get_option");
570   }
571
572   /// Get an option from the serial port.
573   /**
574    * This function is used to get the current value of an option on the serial
575    * port.
576    *
577    * @param option The option value to be obtained from the serial port.
578    *
579    * @param ec Set to indicate what error occurred, if any.
580    *
581    * @sa GettableSerialPortOption @n
582    * boost::asio::serial_port_base::baud_rate @n
583    * boost::asio::serial_port_base::flow_control @n
584    * boost::asio::serial_port_base::parity @n
585    * boost::asio::serial_port_base::stop_bits @n
586    * boost::asio::serial_port_base::character_size
587    */
588   template <typename GettableSerialPortOption>
589   BOOST_ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option,
590       boost::system::error_code& ec) const
591   {
592     impl_.get_service().get_option(impl_.get_implementation(), option, ec);
593     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
594   }
595
596   /// Write some data to the serial port.
597   /**
598    * This function is used to write data to the serial port. The function call
599    * will block until one or more bytes of the data has been written
600    * successfully, or until an error occurs.
601    *
602    * @param buffers One or more data buffers to be written to the serial port.
603    *
604    * @returns The number of bytes written.
605    *
606    * @throws boost::system::system_error Thrown on failure. An error code of
607    * boost::asio::error::eof indicates that the connection was closed by the
608    * peer.
609    *
610    * @note The write_some operation may not transmit all of the data to the
611    * peer. Consider using the @ref write function if you need to ensure that
612    * all data is written before the blocking operation completes.
613    *
614    * @par Example
615    * To write a single data buffer use the @ref buffer function as follows:
616    * @code
617    * basic_serial_port.write_some(boost::asio::buffer(data, size));
618    * @endcode
619    * See the @ref buffer documentation for information on writing multiple
620    * buffers in one go, and how to use it with arrays, boost::array or
621    * std::vector.
622    */
623   template <typename ConstBufferSequence>
624   std::size_t write_some(const ConstBufferSequence& buffers)
625   {
626     boost::system::error_code ec;
627     std::size_t s = impl_.get_service().write_some(
628         impl_.get_implementation(), buffers, ec);
629     boost::asio::detail::throw_error(ec, "write_some");
630     return s;
631   }
632
633   /// Write some data to the serial port.
634   /**
635    * This function is used to write data to the serial port. The function call
636    * will block until one or more bytes of the data has been written
637    * successfully, or until an error occurs.
638    *
639    * @param buffers One or more data buffers to be written to the serial port.
640    *
641    * @param ec Set to indicate what error occurred, if any.
642    *
643    * @returns The number of bytes written. Returns 0 if an error occurred.
644    *
645    * @note The write_some operation may not transmit all of the data to the
646    * peer. Consider using the @ref write function if you need to ensure that
647    * all data is written before the blocking operation completes.
648    */
649   template <typename ConstBufferSequence>
650   std::size_t write_some(const ConstBufferSequence& buffers,
651       boost::system::error_code& ec)
652   {
653     return impl_.get_service().write_some(
654         impl_.get_implementation(), buffers, ec);
655   }
656
657   /// Start an asynchronous write.
658   /**
659    * This function is used to asynchronously write data to the serial port.
660    * The function call always returns immediately.
661    *
662    * @param buffers One or more data buffers to be written to the serial port.
663    * Although the buffers object may be copied as necessary, ownership of the
664    * underlying memory blocks is retained by the caller, which must guarantee
665    * that they remain valid until the handler is called.
666    *
667    * @param handler The handler to be called when the write operation completes.
668    * Copies will be made of the handler as required. The function signature of
669    * the handler must be:
670    * @code void handler(
671    *   const boost::system::error_code& error, // Result of operation.
672    *   std::size_t bytes_transferred           // Number of bytes written.
673    * ); @endcode
674    * Regardless of whether the asynchronous operation completes immediately or
675    * not, the handler will not be invoked from within this function. On
676    * immediate completion, invocation of the handler will be performed in a
677    * manner equivalent to using boost::asio::post().
678    *
679    * @note The write operation may not transmit all of the data to the peer.
680    * Consider using the @ref async_write function if you need to ensure that all
681    * data is written before the asynchronous operation completes.
682    *
683    * @par Example
684    * To write a single data buffer use the @ref buffer function as follows:
685    * @code
686    * basic_serial_port.async_write_some(
687    *     boost::asio::buffer(data, size), handler);
688    * @endcode
689    * See the @ref buffer documentation for information on writing multiple
690    * buffers in one go, and how to use it with arrays, boost::array or
691    * std::vector.
692    */
693   template <typename ConstBufferSequence,
694       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
695         std::size_t)) WriteHandler
696           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
697   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,
698       void (boost::system::error_code, std::size_t))
699   async_write_some(const ConstBufferSequence& buffers,
700       BOOST_ASIO_MOVE_ARG(WriteHandler) handler
701         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
702   {
703     return async_initiate<WriteHandler,
704       void (boost::system::error_code, std::size_t)>(
705         initiate_async_write_some(this), handler, buffers);
706   }
707
708   /// Read some data from the serial port.
709   /**
710    * This function is used to read data from the serial port. The function
711    * call will block until one or more bytes of data has been read successfully,
712    * or until an error occurs.
713    *
714    * @param buffers One or more buffers into which the data will be read.
715    *
716    * @returns The number of bytes read.
717    *
718    * @throws boost::system::system_error Thrown on failure. An error code of
719    * boost::asio::error::eof indicates that the connection was closed by the
720    * peer.
721    *
722    * @note The read_some operation may not read all of the requested number of
723    * bytes. Consider using the @ref read function if you need to ensure that
724    * the requested amount of data is read before the blocking operation
725    * completes.
726    *
727    * @par Example
728    * To read into a single data buffer use the @ref buffer function as follows:
729    * @code
730    * basic_serial_port.read_some(boost::asio::buffer(data, size));
731    * @endcode
732    * See the @ref buffer documentation for information on reading into multiple
733    * buffers in one go, and how to use it with arrays, boost::array or
734    * std::vector.
735    */
736   template <typename MutableBufferSequence>
737   std::size_t read_some(const MutableBufferSequence& buffers)
738   {
739     boost::system::error_code ec;
740     std::size_t s = impl_.get_service().read_some(
741         impl_.get_implementation(), buffers, ec);
742     boost::asio::detail::throw_error(ec, "read_some");
743     return s;
744   }
745
746   /// Read some data from the serial port.
747   /**
748    * This function is used to read data from the serial port. The function
749    * call will block until one or more bytes of data has been read successfully,
750    * or until an error occurs.
751    *
752    * @param buffers One or more buffers into which the data will be read.
753    *
754    * @param ec Set to indicate what error occurred, if any.
755    *
756    * @returns The number of bytes read. Returns 0 if an error occurred.
757    *
758    * @note The read_some operation may not read all of the requested number of
759    * bytes. Consider using the @ref read function if you need to ensure that
760    * the requested amount of data is read before the blocking operation
761    * completes.
762    */
763   template <typename MutableBufferSequence>
764   std::size_t read_some(const MutableBufferSequence& buffers,
765       boost::system::error_code& ec)
766   {
767     return impl_.get_service().read_some(
768         impl_.get_implementation(), buffers, ec);
769   }
770
771   /// Start an asynchronous read.
772   /**
773    * This function is used to asynchronously read data from the serial port.
774    * The function call always returns immediately.
775    *
776    * @param buffers One or more buffers into which the data will be read.
777    * Although the buffers object may be copied as necessary, ownership of the
778    * underlying memory blocks is retained by the caller, which must guarantee
779    * that they remain valid until the handler is called.
780    *
781    * @param handler The handler to be called when the read operation completes.
782    * Copies will be made of the handler as required. The function signature of
783    * the handler must be:
784    * @code void handler(
785    *   const boost::system::error_code& error, // Result of operation.
786    *   std::size_t bytes_transferred           // Number of bytes read.
787    * ); @endcode
788    * Regardless of whether the asynchronous operation completes immediately or
789    * not, the handler will not be invoked from within this function. On
790    * immediate completion, invocation of the handler will be performed in a
791    * manner equivalent to using boost::asio::post().
792    *
793    * @note The read operation may not read all of the requested number of bytes.
794    * Consider using the @ref async_read function if you need to ensure that the
795    * requested amount of data is read before the asynchronous operation
796    * completes.
797    *
798    * @par Example
799    * To read into a single data buffer use the @ref buffer function as follows:
800    * @code
801    * basic_serial_port.async_read_some(
802    *     boost::asio::buffer(data, size), handler);
803    * @endcode
804    * See the @ref buffer documentation for information on reading into multiple
805    * buffers in one go, and how to use it with arrays, boost::array or
806    * std::vector.
807    */
808   template <typename MutableBufferSequence,
809       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
810         std::size_t)) ReadHandler
811           BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
812   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,
813       void (boost::system::error_code, std::size_t))
814   async_read_some(const MutableBufferSequence& buffers,
815       BOOST_ASIO_MOVE_ARG(ReadHandler) handler
816         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
817   {
818     return async_initiate<ReadHandler,
819       void (boost::system::error_code, std::size_t)>(
820         initiate_async_read_some(this), handler, buffers);
821   }
822
823 private:
824   // Disallow copying and assignment.
825   basic_serial_port(const basic_serial_port&) BOOST_ASIO_DELETED;
826   basic_serial_port& operator=(const basic_serial_port&) BOOST_ASIO_DELETED;
827
828   class initiate_async_write_some
829   {
830   public:
831     typedef Executor executor_type;
832
833     explicit initiate_async_write_some(basic_serial_port* self)
834       : self_(self)
835     {
836     }
837
838     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
839     {
840       return self_->get_executor();
841     }
842
843     template <typename WriteHandler, typename ConstBufferSequence>
844     void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
845         const ConstBufferSequence& buffers) const
846     {
847       // If you get an error on the following line it means that your handler
848       // does not meet the documented type requirements for a WriteHandler.
849       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
850
851       detail::non_const_lvalue<WriteHandler> handler2(handler);
852       self_->impl_.get_service().async_write_some(
853           self_->impl_.get_implementation(), buffers, handler2.value,
854           self_->impl_.get_implementation_executor());
855     }
856
857   private:
858     basic_serial_port* self_;
859   };
860
861   class initiate_async_read_some
862   {
863   public:
864     typedef Executor executor_type;
865
866     explicit initiate_async_read_some(basic_serial_port* self)
867       : self_(self)
868     {
869     }
870
871     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
872     {
873       return self_->get_executor();
874     }
875
876     template <typename ReadHandler, typename MutableBufferSequence>
877     void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
878         const MutableBufferSequence& buffers) const
879     {
880       // If you get an error on the following line it means that your handler
881       // does not meet the documented type requirements for a ReadHandler.
882       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
883
884       detail::non_const_lvalue<ReadHandler> handler2(handler);
885       self_->impl_.get_service().async_read_some(
886           self_->impl_.get_implementation(), buffers, handler2.value,
887           self_->impl_.get_implementation_executor());
888     }
889
890   private:
891     basic_serial_port* self_;
892   };
893
894 #if defined(BOOST_ASIO_HAS_IOCP)
895   detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_;
896 #else
897   detail::io_object_impl<detail::reactive_serial_port_service, Executor> impl_;
898 #endif
899 };
900
901 } // namespace asio
902 } // namespace boost
903
904 #include <boost/asio/detail/pop_options.hpp>
905
906 #endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
907        //   || defined(GENERATING_DOCUMENTATION)
908
909 #endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP