diff --git a/doc/design/implementation.qbk b/doc/design/implementation.qbk index 0e76bc1a..a9422feb 100644 --- a/doc/design/implementation.qbk +++ b/doc/design/implementation.qbk @@ -29,6 +29,9 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. [heading Linux Kernel 2.6] @@ -46,6 +49,10 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. + [heading Solaris] @@ -63,6 +70,10 @@ calls `io_service::run()`, `io_service::run_one()`, `io_service::poll()` or resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. + [heading QNX Neutrino] @@ -81,6 +92,10 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. + [heading Mac OS X] @@ -98,6 +113,10 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. + [heading FreeBSD] @@ -115,6 +134,10 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. + [heading AIX] @@ -133,6 +156,10 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. + [heading HP-UX] @@ -151,6 +178,10 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. + [heading Tru64] @@ -169,6 +200,10 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* At most `min(64,IOV_MAX)` buffers may be transferred in a single operation. + [heading Windows 95, 98 and Me] @@ -186,6 +221,10 @@ Threads: resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* For sockets, at most 16 buffers may be transferred in a single operation. + [heading Windows NT, 2000, XP, 2003 and Vista] @@ -209,5 +248,12 @@ demultiplexing. This thread is created on the first call to `async_connect()`. resolution. This thread is created on the first call to either `ip::tcp::resolver::async_resolve()` or `ip::udp::resolver::async_resolve()`. +Scatter-Gather: + +* For sockets, at most 64 buffers may be transferred in a single operation. + +* For stream-oriented handles, only one buffer may be transferred in a single +operation. + [endsect] diff --git a/doc/quickref.xml b/doc/quickref.xml index fb36d6f6..453a089d 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -37,13 +37,24 @@ ip::udp::endpoint ip::udp::resolver ip::udp::socket + local::stream_protocol + local::stream_protocol::acceptor + local::stream_protocol::endpoint + local::stream_protocol::iostream + local::stream_protocol::socket + local::datagram_protocol + local::datagram_protocol::endpoint + local::datagram_protocol::socket mutable_buffer mutable_buffers_1 + posix::descriptor_base + posix::stream_descriptor socket_base ssl::context ssl::context_base ssl::stream_base streambuf + windows::stream_handle @@ -66,18 +77,25 @@ ip::basic_resolver_entry ip::basic_resolver_iterator ip::basic_resolver_query + local::basic_endpoint + posix::basic_descriptor + posix::basic_stream_descriptor ssl::basic_context ssl::stream + windows::basic_handle + windows::basic_stream_handle Services datagram_socket_service deadline_timer_service ip::resolver_service + posix::stream_descriptor_service socket_acceptor_service ssl::context_service ssl::stream_service stream_socket_service + windows::stream_handle_service Placeholders @@ -99,6 +117,7 @@ buffer has_service ip::host_name + local::connect_pair read read_until transfer_all @@ -132,9 +151,11 @@ ConvertibleToConstBuffer ConvertibleToMutableBuffer DatagramSocketService + DescriptorService Endpoint GettableSocketOption Handler + HandleService InternetProtocol IoControlCommand IoObjectService @@ -147,6 +168,8 @@ SettableSocketOption SocketAcceptorService SocketService + StreamDescriptorService + StreamHandleService StreamSocketService SyncReadStream SyncWriteStream diff --git a/doc/reference.dox b/doc/reference.dox index ab677d09..9ec7b335 100644 --- a/doc/reference.dox +++ b/doc/reference.dox @@ -76,7 +76,10 @@ INPUT = ./../../../boost/asio.hpp \ ./../../../boost/asio \ ./../../../boost/asio/impl \ ./../../../boost/asio/ip \ + ./../../../boost/asio/local \ + ./../../../boost/asio/posix \ ./../../../boost/asio/ssl \ + ./../../../boost/asio/windows \ ./noncopyable_dox.txt \ ./std_exception_dox.txt FILE_PATTERNS = diff --git a/doc/reference.qbk b/doc/reference.qbk index d1471591..049615ba 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -19,9 +19,11 @@ [include requirements/ConvertibleToConstBuffer.qbk] [include requirements/ConvertibleToMutableBuffer.qbk] [include requirements/DatagramSocketService.qbk] +[include requirements/DescriptorService.qbk] [include requirements/Endpoint.qbk] [include requirements/GettableSocketOption.qbk] [include requirements/Handler.qbk] +[include requirements/HandleService.qbk] [include requirements/InternetProtocol.qbk] [include requirements/IoControlCommand.qbk] [include requirements/IoObjectService.qbk] @@ -34,6 +36,8 @@ [include requirements/SettableSocketOption.qbk] [include requirements/SocketAcceptorService.qbk] [include requirements/SocketService.qbk] +[include requirements/StreamDescriptorService.qbk] +[include requirements/StreamHandleService.qbk] [include requirements/StreamSocketService.qbk] [include requirements/SyncReadStream.qbk] [include requirements/SyncWriteStream.qbk] @@ -550,6 +554,364 @@ Regardless of whether the asynchronous operation completes immediately or not, t +[endsect] + + +[endsect] + +[section:async_read_at async_read_at] + +Start an asynchronous operation to read a certain amount of data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessReadDevice AsyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.async_read_at.overload1 async_read_at]``( + AsyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + ReadHandler handler); + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessReadDevice AsyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename CompletionCondition, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.async_read_at.overload2 async_read_at]``( + AsyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + CompletionCondition completion_condition, + ReadHandler handler); + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessReadDevice AsyncRandomAccessReadDevice]``, + typename Allocator, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.async_read_at.overload3 async_read_at]``( + AsyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + ReadHandler handler); + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessReadDevice AsyncRandomAccessReadDevice]``, + typename Allocator, + typename CompletionCondition, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.async_read_at.overload4 async_read_at]``( + AsyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition, + ReadHandler handler); + + +[section:overload1 async_read_at (1 of 4 overloads)] + +Start an asynchronous operation to read a certain amount of data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessReadDevice AsyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_at( + AsyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + ReadHandler handler); + + +This function is used to asynchronously read a certain number of bytes of data from a random access device at the specified offset. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* An error occurred. + +This operation is implemented in terms of one or more calls to the device's async\_read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the AsyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[buffers][One or more buffers into which the data will be read. The sum of the buffer sizes indicates the maximum number of bytes to read from the device. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // Number of bytes copied into the buffers. If an error + // occurred, this will be the number of bytes successfully + // transferred prior to the error. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::async_read_at(d, 42, boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + +[heading Remarks] + +This overload is equivalent to calling: + + boost::asio::async_read_at( + d, 42, buffers, + boost::asio::transfer_all(), + handler); + + + + + + +[endsect] + + + +[section:overload2 async_read_at (2 of 4 overloads)] + +Start an asynchronous operation to read a certain amount of data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessReadDevice AsyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename CompletionCondition, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_at( + AsyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + CompletionCondition completion_condition, + ReadHandler handler); + + +This function is used to asynchronously read a certain number of bytes of data from a random access device at the specified offset. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* The completion_condition function object returns true. + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the AsyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[buffers][One or more buffers into which the data will be read. The sum of the buffer sizes indicates the maximum number of bytes to read from the device. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[completion_condition][The function object to be called to determine whether the read operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest read_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the read operation is complete. False indicates that further calls to the device's async\_read\_some\_at function are required.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // Number of bytes copied into the buffers. If an error + // occurred, this will be the number of bytes successfully + // transferred prior to the error. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::async_read_at(d, 42, + boost::asio::buffer(data, size), + boost::asio::transfer_at_least(32), + handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload3 async_read_at (3 of 4 overloads)] + +Start an asynchronous operation to read a certain amount of data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessReadDevice AsyncRandomAccessReadDevice]``, + typename Allocator, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_at( + AsyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + ReadHandler handler); + + +This function is used to asynchronously read a certain number of bytes of data from a random access device at the specified offset. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* An error occurred. + +This operation is implemented in terms of one or more calls to the device's async\_read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the AsyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[b][A basic\_streambuf object into which the data will be read. Ownership of the streambuf is retained by the caller, which must guarantee that it remains valid until the handler is called.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // Number of bytes copied into the buffers. If an error + // occurred, this will be the number of bytes successfully + // transferred prior to the error. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +This overload is equivalent to calling: + + boost::asio::async_read_at( + d, 42, b, + boost::asio::transfer_all(), + handler); + + + + + + +[endsect] + + + +[section:overload4 async_read_at (4 of 4 overloads)] + +Start an asynchronous operation to read a certain amount of data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessReadDevice AsyncRandomAccessReadDevice]``, + typename Allocator, + typename CompletionCondition, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_at( + AsyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition, + ReadHandler handler); + + +This function is used to asynchronously read a certain number of bytes of data from a random access device at the specified offset. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's async\_read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the AsyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[b][A basic\_streambuf object into which the data will be read. Ownership of the streambuf is retained by the caller, which must guarantee that it remains valid until the handler is called.]] + +[[completion_condition][The function object to be called to determine whether the read operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest read_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the read operation is complete. False indicates that further calls to the device's async\_read\_some\_at function are required.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // Number of bytes copied into the buffers. If an error + // occurred, this will be the number of bytes successfully + // transferred prior to the error. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post(). ]] + +] + + + [endsect] @@ -589,8 +951,20 @@ Start an asynchronous operation to read data into a streambuf until a delimiter const boost::regex & expr, ReadHandler handler); + template< + typename ``[link boost_asio.reference.AsyncReadStream AsyncReadStream]``, + typename Allocator, + typename ``[link boost_asio.reference.MatchCondition MatchCondition]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.async_read_until.overload4 async_read_until]``( + AsyncReadStream & s, + boost::asio::basic_streambuf< Allocator > & b, + MatchCondition match_condition, + ReadHandler handler, + typename boost::enable_if< is_match_condition< MatchCondition > >::type * = 0); -[section:overload1 async_read_until (1 of 3 overloads)] + +[section:overload1 async_read_until (1 of 4 overloads)] Start an asynchronous operation to read data into a streambuf until a delimiter is encountered. @@ -670,7 +1044,7 @@ To asynchronously read data into a streambuf until a newline is encountered: -[section:overload2 async_read_until (2 of 3 overloads)] +[section:overload2 async_read_until (2 of 4 overloads)] Start an asynchronous operation to read data into a streambuf until a delimiter is encountered. @@ -750,7 +1124,7 @@ To asynchronously read data into a streambuf until a newline is encountered: -[section:overload3 async_read_until (3 of 3 overloads)] +[section:overload3 async_read_until (3 of 4 overloads)] Start an asynchronous operation to read data into a streambuf until a regular expression is located. @@ -828,6 +1202,140 @@ To asynchronously read data into a streambuf until a CR-LF sequence is encounter +[endsect] + + + +[section:overload4 async_read_until (4 of 4 overloads)] + +Start an asynchronous operation to read data into a streambuf until a function object indicates a match. + + template< + typename ``[link boost_asio.reference.AsyncReadStream AsyncReadStream]``, + typename Allocator, + typename ``[link boost_asio.reference.MatchCondition MatchCondition]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_until( + AsyncReadStream & s, + boost::asio::basic_streambuf< Allocator > & b, + MatchCondition match_condition, + ReadHandler handler, + typename boost::enable_if< is_match_condition< MatchCondition > >::type * = 0); + + +This function is used to asynchronously read data into the specified streambuf until a user-defined match condition function object, when applied to the data contained in the streambuf, indicates a successful match. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* The match condition function object returns a std::pair where the second element evaluates to true. + +* An error occurred. + +This operation is implemented in terms of zero or more calls to the stream's async\_read\_some function. If the match condition function object already indicates a match, the operation completes immediately. + + +[heading Parameters] + + +[variablelist + +[[s][The stream from which the data is to be read. The type must support the AsyncReadStream concept.]] + +[[b][A streambuf object into which the data will be read.]] + +[[match_condition][The function object to be called to determine whether a match exists. The signature of the function object must be: +`` + pair match_condition(iterator begin, iterator end); + +`` +where iterator represents the type: +`` + buffers_iterator::const_buffers_type> + +`` +The iterator parameters begin and end define the range of bytes to be scanned to determine whether there is a match. The first member of the return value is an iterator marking one-past-the-end of the bytes that have been consumed by the match function. This iterator is used to calculate the begin parameter for any subsequent invocation of the match condition. The second member of the return value is true if a match has been found, false otherwise.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // The number of bytes in the streambuf's get + // area that have been fully consumed by the + // match function. O if an error occurred. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The default implementation of the is_match_condition type trait evaluates to true for function pointers and function objects with a result\_type typedef. It must be specialised for other user-defined function objects. + +[heading Examples] + +To asynchronously read data into a streambuf until whitespace is encountered: + + typedef boost::asio::buffers_iterator< + boost::asio::streambuf::const_buffers_type> iterator; + + std::pair + match_whitespace(iterator begin, iterator end) + { + iterator i = begin; + while (i != end) + if (std::isspace(*i++)) + return std::make_pair(i, true); + return std::make_pair(i, false); + } + ... + void handler(const boost::system::error_code& e, std::size_t size); + ... + boost::asio::streambuf b; + boost::asio::async_read_until(s, b, match_whitespace, handler); + + + + +To asynchronously read data into a streambuf until a matching character is found: + + class match_char + { + public: + explicit match_char(char c) : c_(c) {} + + template + std::pair operator()( + Iterator begin, Iterator end) const + { + Iterator i = begin; + while (i != end) + if (c_ == *i++) + return std::make_pair(i, true); + return std::make_pair(i, false); + } + + private: + char c_; + }; + + namespace asio { + template <> struct is_match_condition + : public boost::true_type {}; + } // namespace asio + ... + void handler(const boost::system::error_code& e, std::size_t size); + ... + boost::asio::streambuf b; + boost::asio::async_read_until(s, b, match_char('a'), handler); + + + + + [endsect] @@ -835,7 +1343,7 @@ To asynchronously read data into a streambuf until a CR-LF sequence is encounter [section:async_write async_write] -Start an asynchronous operation to write of all of the supplied data to a stream. +Start an asynchronous operation to write all of the supplied data to a stream. template< typename ``[link boost_asio.reference.AsyncWriteStream AsyncWriteStream]``, @@ -880,7 +1388,7 @@ Start an asynchronous operation to write of all of the supplied data to a stream [section:overload1 async_write (1 of 4 overloads)] -Start an asynchronous operation to write of all of the supplied data to a stream. +Start an asynchronous operation to write all of the supplied data to a stream. template< typename ``[link boost_asio.reference.AsyncWriteStream AsyncWriteStream]``, @@ -1030,7 +1538,7 @@ See the [section:overload3 async_write (3 of 4 overloads)] -Start an asynchronous operation to write a certain amount of data to a stream. +Start an asynchronous operation to write all of the supplied data to a stream. template< typename ``[link boost_asio.reference.AsyncWriteStream AsyncWriteStream]``, @@ -1149,6 +1657,343 @@ Regardless of whether the asynchronous operation completes immediately or not, t +[endsect] + + +[endsect] + +[section:async_write_at async_write_at] + +Start an asynchronous operation to write all of the supplied data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessWriteDevice AsyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void ``[link boost_asio.reference.async_write_at.overload1 async_write_at]``( + AsyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + WriteHandler handler); + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessWriteDevice AsyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename CompletionCondition, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void ``[link boost_asio.reference.async_write_at.overload2 async_write_at]``( + AsyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + CompletionCondition completion_condition, + WriteHandler handler); + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessWriteDevice AsyncRandomAccessWriteDevice]``, + typename Allocator, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void ``[link boost_asio.reference.async_write_at.overload3 async_write_at]``( + AsyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + WriteHandler handler); + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessWriteDevice AsyncRandomAccessWriteDevice]``, + typename Allocator, + typename CompletionCondition, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void ``[link boost_asio.reference.async_write_at.overload4 async_write_at]``( + AsyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition, + WriteHandler handler); + + +[section:overload1 async_write_at (1 of 4 overloads)] + +Start an asynchronous operation to write all of the supplied data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessWriteDevice AsyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_at( + AsyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + WriteHandler handler); + + +This function is used to asynchronously write a certain number of bytes of data to a random access device at a specified offset. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* All of the data in the supplied buffers has been written. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* An error occurred. + +This operation is implemented in terms of one or more calls to the device's async\_write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the AsyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[buffers][One or more buffers containing the data to be written. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // Number of bytes written from the buffers. If an error + // occurred, this will be less than the sum of the buffer sizes. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::async_write_at(d, 42, boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 async_write_at (2 of 4 overloads)] + +Start an asynchronous operation to write a certain amount of data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessWriteDevice AsyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename CompletionCondition, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_at( + AsyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + CompletionCondition completion_condition, + WriteHandler handler); + + +This function is used to asynchronously write a certain number of bytes of data to a random access device at a specified offset. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* All of the data in the supplied buffers has been written. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's async\_write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the AsyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[buffers][One or more buffers containing the data to be written. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[completion_condition][The function object to be called to determine whether the write operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest write_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the write operation is complete. False indicates that further calls to the device's async\_write\_some\_at function are required.]] + +[[handler][The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // Number of bytes written from the buffers. If an error + // occurred, this will be less than the sum of the buffer sizes. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::async_write_at(d, 42, + boost::asio::buffer(data, size), + boost::asio::transfer_at_least(32), + handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload3 async_write_at (3 of 4 overloads)] + +Start an asynchronous operation to write all of the supplied data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessWriteDevice AsyncRandomAccessWriteDevice]``, + typename Allocator, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_at( + AsyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + WriteHandler handler); + + +This function is used to asynchronously write a certain number of bytes of data to a random access device at a specified offset. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* All of the data in the supplied basic_streambuf has been written. + +* An error occurred. + +This operation is implemented in terms of one or more calls to the device's async\_write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the AsyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[b][A basic\_streambuf object from which data will be written. Ownership of the streambuf is retained by the caller, which must guarantee that it remains valid until the handler is called.]] + +[[handler][The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // Number of bytes written from the buffers. If an error + // occurred, this will be less than the sum of the buffer sizes. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post(). ]] + +] + + + +[endsect] + + + +[section:overload4 async_write_at (4 of 4 overloads)] + +Start an asynchronous operation to write a certain amount of data at the specified offset. + + template< + typename ``[link boost_asio.reference.AsyncRandomAccessWriteDevice AsyncRandomAccessWriteDevice]``, + typename Allocator, + typename CompletionCondition, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_at( + AsyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition, + WriteHandler handler); + + +This function is used to asynchronously write a certain number of bytes of data to a random access device at a specified offset. The function call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: + + +* All of the data in the supplied basic_streambuf has been written. + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's async\_write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the AsyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[b][A basic\_streambuf object from which data will be written. Ownership of the streambuf is retained by the caller, which must guarantee that it remains valid until the handler is called.]] + +[[completion_condition][The function object to be called to determine whether the write operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest async_write_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the write operation is complete. False indicates that further calls to the device's async\_write\_some\_at function are required.]] + +[[handler][The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + // Result of operation. + const boost::system::error_code& error, + + // Number of bytes written from the buffers. If an error + // occurred, this will be less than the sum of the buffer sizes. + std::size_t bytes_transferred + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post(). ]] + +] + + + [endsect] @@ -1495,6 +2340,22 @@ Provides datagram-oriented socket functionality. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_datagram_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_datagram_socket class template provides asynchronous and blocking datagram-oriented socket functionality. @@ -3207,6 +4068,21 @@ Getting the value of the SOL\_SOCKET/SO\_KEEPALIVE option: [endsect] +[section:implementation basic_datagram_socket::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + [section:implementation_type basic_datagram_socket::implementation_type] @@ -3862,6 +4738,17 @@ A basic_socket is always the lowest layer. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket._basic_socket [*~basic_socket]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -3888,6 +4775,22 @@ A basic_socket is always the lowest layer. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_socket class template provides functionality that is common to both stream-oriented and datagram-oriented sockets. @@ -5165,6 +6068,21 @@ The number of bytes sent. [endsect] +[section:service basic_datagram_socket::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + [section:service_type basic_datagram_socket::service_type] @@ -5539,6 +6457,22 @@ Provides waitable timer functionality. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_deadline_timer.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_deadline_timer.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_deadline_timer class template provides the ability to perform a blocking or asynchronous wait for a timer to expire. Most applications will use the boost::asio::deadline\_timer typedef. @@ -6081,6 +7015,21 @@ A reference to the io_service object that the I/O object will use to dispatch ha +[section:implementation basic_deadline_timer::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + [section:implementation_type basic_deadline_timer::implementation_type] @@ -6120,6 +7069,21 @@ A reference to the io_service object that the I/O object will use to dispatch ha +[section:service basic_deadline_timer::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + [section:service_type basic_deadline_timer::service_type] @@ -6272,6 +7236,58 @@ Base class for all I/O objects. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_io_object.basic_io_object [*basic_io_object]]] + [Construct a basic_io_object. ] + ] + + [ + [[link boost_asio.reference.basic_io_object._basic_io_object [*~basic_io_object]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_io_object.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_io_object.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + + +[section:basic_io_object basic_io_object::basic_io_object] + +Construct a basic_io_object. + + basic_io_object( + boost::asio::io_service & io_service); + + +Performs: + + service.construct(implementation); + + + + + +[endsect] + + [section:get_io_service basic_io_object::get_io_service] @@ -6293,6 +7309,18 @@ A reference to the io_service object that the I/O object will use to dispatch ha +[section:implementation basic_io_object::implementation] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + [section:implementation_type basic_io_object::implementation_type] The underlying implementation type of I/O object. @@ -6326,6 +7354,18 @@ A reference to the io_service object that the I/O object will use to dispatch ha +[section:service basic_io_object::service] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + [section:service_type basic_io_object::service_type] The type of the service that will be used to provide I/O operations. @@ -6339,6 +7379,5836 @@ The type of the service that will be used to provide I/O operations. +[section:_basic_io_object basic_io_object::~basic_io_object] + +Protected destructor to prevent deletion through this type. + + ~basic_io_object(); + + +Performs: + + service.destroy(implementation); + + + + + +[endsect] + + + +[endsect] + +[section:basic_raw_socket basic_raw_socket] + +Provides raw-oriented socket functionality. + + template< + typename ``[link boost_asio.reference.Protocol Protocol]``, + typename ``[link boost_asio.reference.RawSocketService RawSocketService]`` = raw_socket_service> + class basic_raw_socket : + public basic_socket< Protocol, RawSocketService > + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_raw_socket.broadcast [*broadcast]]] + [Socket option to permit sending of broadcast messages. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.debug [*debug]]] + [Socket option to enable socket-level debugging. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.do_not_route [*do_not_route]]] + [Socket option to prevent routing, use local interfaces only. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.enable_connection_aborted [*enable_connection_aborted]]] + [Socket option to report aborted connections on accept. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.endpoint_type [*endpoint_type]]] + [The endpoint type. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.keep_alive [*keep_alive]]] + [Socket option to send keep-alives. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.linger [*linger]]] + [Socket option to specify whether the socket lingers on close if unsent data is present. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.lowest_layer_type [*lowest_layer_type]]] + [A basic_socket is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.message_flags [*message_flags]]] + [Bitmask type for flags that can be passed to send and receive operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.native_type [*native_type]]] + [The native representation of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.protocol_type [*protocol_type]]] + [The protocol type. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.receive_buffer_size [*receive_buffer_size]]] + [Socket option for the receive buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.receive_low_watermark [*receive_low_watermark]]] + [Socket option for the receive low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.reuse_address [*reuse_address]]] + [Socket option to allow the socket to be bound to an address that is already in use. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.send_buffer_size [*send_buffer_size]]] + [Socket option for the send buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.send_low_watermark [*send_low_watermark]]] + [Socket option for the send low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.shutdown_type [*shutdown_type]]] + [Different ways a socket may be shutdown. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_raw_socket.assign [*assign]]] + [Assign an existing native socket to the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_connect [*async_connect]]] + [Start an asynchronous connect. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_receive [*async_receive]]] + [Start an asynchronous receive on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_receive_from [*async_receive_from]]] + [Start an asynchronous receive. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_send [*async_send]]] + [Start an asynchronous send on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_send_to [*async_send_to]]] + [Start an asynchronous send. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.at_mark [*at_mark]]] + [Determine whether the socket is at the out-of-band data mark. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.available [*available]]] + [Determine the number of bytes available for reading. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.basic_raw_socket [*basic_raw_socket]]] + [Construct a basic_raw_socket without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.bind [*bind]]] + [Bind the socket to the given local endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.close [*close]]] + [Close the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.connect [*connect]]] + [Connect the socket to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.get_option [*get_option]]] + [Get an option from the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.io_control [*io_control]]] + [Perform an IO control command on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.is_open [*is_open]]] + [Determine whether the socket is open. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.local_endpoint [*local_endpoint]]] + [Get the local endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.native [*native]]] + [Get the native socket representation. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.open [*open]]] + [Open the socket using the specified protocol. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.receive [*receive]]] + [Receive some data on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.receive_from [*receive_from]]] + [Receive raw data with the endpoint of the sender. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.remote_endpoint [*remote_endpoint]]] + [Get the remote endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.send [*send]]] + [Send some data on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.send_to [*send_to]]] + [Send raw data to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.set_option [*set_option]]] + [Set an option on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.shutdown [*shutdown]]] + [Disable sends or receives on the socket. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_raw_socket.max_connections [*max_connections]]] + [The maximum length of the queue of pending incoming connections. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.message_do_not_route [*message_do_not_route]]] + [Specify that the data should not be subject to routing. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.message_out_of_band [*message_out_of_band]]] + [Process out-of-band data. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.message_peek [*message_peek]]] + [Peek at incoming data without removing it from the input queue. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_raw_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_raw_socket class template provides asynchronous and blocking raw-oriented socket functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + +[section:assign basic_raw_socket::assign] + +Assign an existing native socket to the socket. + + void ``[link boost_asio.reference.basic_raw_socket.assign.overload1 assign]``( + const protocol_type & protocol, + const native_type & native_socket); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.assign.overload2 assign]``( + const protocol_type & protocol, + const native_type & native_socket, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::assign (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Assign an existing native socket to the socket. + + void assign( + const protocol_type & protocol, + const native_type & native_socket); + + + +[endsect] + + + +[section:overload2 basic_raw_socket::assign (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Assign an existing native socket to the socket. + + boost::system::error_code assign( + const protocol_type & protocol, + const native_type & native_socket, + boost::system::error_code & ec); + + + +[endsect] + + +[endsect] + + +[section:async_connect basic_raw_socket::async_connect] + + +['Inherited from basic_socket.] + +Start an asynchronous connect. + + void async_connect( + const endpoint_type & peer_endpoint, + ConnectHandler handler); + + +This function is used to asynchronously connect a socket to the specified remote endpoint. The function call always returns immediately. + +The socket is automatically opened if it is not already open. If the connect fails, and the socket was automatically opened, the socket is returned to the closed state. + + +[heading Parameters] + + +[variablelist + +[[peer_endpoint][The remote endpoint to which the socket will be connected. Copies will be made of the endpoint object as required.]] + +[[handler][The handler to be called when the connection operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error // Result of operation + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Example] + + + + void connect_handler(const boost::system::error_code& error) + { + if (!error) + { + // Connect succeeded. + } + } + + ... + + boost::asio::ip::tcp::socket socket(io_service); + boost::asio::ip::tcp::endpoint endpoint( + boost::asio::ip::address::from_string("1.2.3.4"), 12345); + socket.async_connect(endpoint, connect_handler); + + + + + + +[endsect] + + +[section:async_receive basic_raw_socket::async_receive] + +Start an asynchronous receive on a connected socket. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.basic_raw_socket.async_receive.overload1 async_receive]``( + const MutableBufferSequence & buffers, + ReadHandler handler); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.basic_raw_socket.async_receive.overload2 async_receive]``( + const MutableBufferSequence & buffers, + socket_base::message_flags flags, + ReadHandler handler); + + +[section:overload1 basic_raw_socket::async_receive (1 of 2 overloads)] + +Start an asynchronous receive on a connected socket. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_receive( + const MutableBufferSequence & buffers, + ReadHandler handler); + + +This function is used to asynchronously receive data from the raw socket. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the receive operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes received. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The async\_receive operation can only be used with a connected socket. Use the async\_receive\_from function to receive data on an unconnected raw socket. + +[heading Example] + +To receive into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + socket.async_receive(boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on receiving into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::async_receive (2 of 2 overloads)] + +Start an asynchronous receive on a connected socket. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_receive( + const MutableBufferSequence & buffers, + socket_base::message_flags flags, + ReadHandler handler); + + +This function is used to asynchronously receive data from the raw socket. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[flags][Flags specifying how the receive call is to be made.]] + +[[handler][The handler to be called when the receive operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes received. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The async\_receive operation can only be used with a connected socket. Use the async\_receive\_from function to receive data on an unconnected raw socket. + + + +[endsect] + + +[endsect] + +[section:async_receive_from basic_raw_socket::async_receive_from] + +Start an asynchronous receive. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.basic_raw_socket.async_receive_from.overload1 async_receive_from]``( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + ReadHandler handler); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void ``[link boost_asio.reference.basic_raw_socket.async_receive_from.overload2 async_receive_from]``( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + socket_base::message_flags flags, + ReadHandler handler); + + +[section:overload1 basic_raw_socket::async_receive_from (1 of 2 overloads)] + +Start an asynchronous receive. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_receive_from( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + ReadHandler handler); + + +This function is used to asynchronously receive raw data. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[sender_endpoint][An endpoint object that receives the endpoint of the remote sender of the data. Ownership of the sender\_endpoint object is retained by the caller, which must guarantee that it is valid until the handler is called.]] + +[[handler][The handler to be called when the receive operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes received. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Example] + +To receive into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + socket.async_receive_from( + boost::asio::buffer(data, size), 0, sender_endpoint, handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on receiving into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::async_receive_from (2 of 2 overloads)] + +Start an asynchronous receive. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_receive_from( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + socket_base::message_flags flags, + ReadHandler handler); + + +This function is used to asynchronously receive raw data. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[sender_endpoint][An endpoint object that receives the endpoint of the remote sender of the data. Ownership of the sender\_endpoint object is retained by the caller, which must guarantee that it is valid until the handler is called.]] + +[[flags][Flags specifying how the receive call is to be made.]] + +[[handler][The handler to be called when the receive operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes received. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post(). ]] + +] + + + +[endsect] + + +[endsect] + +[section:async_send basic_raw_socket::async_send] + +Start an asynchronous send on a connected socket. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void ``[link boost_asio.reference.basic_raw_socket.async_send.overload1 async_send]``( + const ConstBufferSequence & buffers, + WriteHandler handler); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void ``[link boost_asio.reference.basic_raw_socket.async_send.overload2 async_send]``( + const ConstBufferSequence & buffers, + socket_base::message_flags flags, + WriteHandler handler); + + +[section:overload1 basic_raw_socket::async_send (1 of 2 overloads)] + +Start an asynchronous send on a connected socket. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_send( + const ConstBufferSequence & buffers, + WriteHandler handler); + + +This function is used to send data on the raw socket. The function call will block until the data has been sent successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be sent on the socket. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the send operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes sent. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The async\_send operation can only be used with a connected socket. Use the async\_send\_to function to send data on an unconnected raw socket. + +[heading Example] + +To send a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + socket.async_send(boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on sending multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::async_send (2 of 2 overloads)] + +Start an asynchronous send on a connected socket. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_send( + const ConstBufferSequence & buffers, + socket_base::message_flags flags, + WriteHandler handler); + + +This function is used to send data on the raw socket. The function call will block until the data has been sent successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be sent on the socket. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[flags][Flags specifying how the send call is to be made.]] + +[[handler][The handler to be called when the send operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes sent. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The async\_send operation can only be used with a connected socket. Use the async\_send\_to function to send data on an unconnected raw socket. + + + +[endsect] + + +[endsect] + +[section:async_send_to basic_raw_socket::async_send_to] + +Start an asynchronous send. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void ``[link boost_asio.reference.basic_raw_socket.async_send_to.overload1 async_send_to]``( + const ConstBufferSequence & buffers, + const endpoint_type & destination, + WriteHandler handler); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void ``[link boost_asio.reference.basic_raw_socket.async_send_to.overload2 async_send_to]``( + const ConstBufferSequence & buffers, + const endpoint_type & destination, + socket_base::message_flags flags, + WriteHandler handler); + + +[section:overload1 basic_raw_socket::async_send_to (1 of 2 overloads)] + +Start an asynchronous send. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_send_to( + const ConstBufferSequence & buffers, + const endpoint_type & destination, + WriteHandler handler); + + +This function is used to asynchronously send raw data to the specified remote endpoint. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be sent to the remote endpoint. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[destination][The remote endpoint to which the data will be sent. Copies will be made of the endpoint as required.]] + +[[handler][The handler to be called when the send operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes sent. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Example] + +To send a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::ip::udp::endpoint destination( + boost::asio::ip::address::from_string("1.2.3.4"), 12345); + socket.async_send_to( + boost::asio::buffer(data, size), destination, handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on sending multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::async_send_to (2 of 2 overloads)] + +Start an asynchronous send. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_send_to( + const ConstBufferSequence & buffers, + const endpoint_type & destination, + socket_base::message_flags flags, + WriteHandler handler); + + +This function is used to asynchronously send raw data to the specified remote endpoint. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be sent to the remote endpoint. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[flags][Flags specifying how the send call is to be made.]] + +[[destination][The remote endpoint to which the data will be sent. Copies will be made of the endpoint as required.]] + +[[handler][The handler to be called when the send operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes sent. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post(). ]] + +] + + + +[endsect] + + +[endsect] + +[section:at_mark basic_raw_socket::at_mark] + +Determine whether the socket is at the out-of-band data mark. + + bool ``[link boost_asio.reference.basic_raw_socket.at_mark.overload1 at_mark]``() const; + + bool ``[link boost_asio.reference.basic_raw_socket.at_mark.overload2 at_mark]``( + boost::system::error_code & ec) const; + + +[section:overload1 basic_raw_socket::at_mark (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Determine whether the socket is at the out-of-band data mark. + + bool at_mark() const; + + +This function is used to check whether the socket input is currently positioned at the out-of-band data mark. + + +[heading Return Value] + +A bool indicating whether the socket is at the out-of-band data mark. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 basic_raw_socket::at_mark (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Determine whether the socket is at the out-of-band data mark. + + bool at_mark( + boost::system::error_code & ec) const; + + +This function is used to check whether the socket input is currently positioned at the out-of-band data mark. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +A bool indicating whether the socket is at the out-of-band data mark. + + + +[endsect] + + +[endsect] + +[section:available basic_raw_socket::available] + +Determine the number of bytes available for reading. + + std::size_t ``[link boost_asio.reference.basic_raw_socket.available.overload1 available]``() const; + + std::size_t ``[link boost_asio.reference.basic_raw_socket.available.overload2 available]``( + boost::system::error_code & ec) const; + + +[section:overload1 basic_raw_socket::available (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Determine the number of bytes available for reading. + + std::size_t available() const; + + +This function is used to determine the number of bytes that may be read without blocking. + + +[heading Return Value] + +The number of bytes that may be read without blocking, or 0 if an error occurs. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 basic_raw_socket::available (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Determine the number of bytes available for reading. + + std::size_t available( + boost::system::error_code & ec) const; + + +This function is used to determine the number of bytes that may be read without blocking. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes that may be read without blocking, or 0 if an error occurs. + + + +[endsect] + + +[endsect] + +[section:basic_raw_socket basic_raw_socket::basic_raw_socket] + +Construct a basic_raw_socket without opening it. + + ``[link boost_asio.reference.basic_raw_socket.basic_raw_socket.overload1 basic_raw_socket]``( + boost::asio::io_service & io_service); + + ``[link boost_asio.reference.basic_raw_socket.basic_raw_socket.overload2 basic_raw_socket]``( + boost::asio::io_service & io_service, + const protocol_type & protocol); + + ``[link boost_asio.reference.basic_raw_socket.basic_raw_socket.overload3 basic_raw_socket]``( + boost::asio::io_service & io_service, + const endpoint_type & endpoint); + + ``[link boost_asio.reference.basic_raw_socket.basic_raw_socket.overload4 basic_raw_socket]``( + boost::asio::io_service & io_service, + const protocol_type & protocol, + const native_type & native_socket); + + +[section:overload1 basic_raw_socket::basic_raw_socket (1 of 4 overloads)] + +Construct a basic_raw_socket without opening it. + + basic_raw_socket( + boost::asio::io_service & io_service); + + +This constructor creates a raw socket without opening it. The open() function must be called before data can be sent or received on the socket. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the raw socket will use to dispatch handlers for any asynchronous operations performed on the socket. ]] + +] + + + +[endsect] + + + +[section:overload2 basic_raw_socket::basic_raw_socket (2 of 4 overloads)] + +Construct and open a basic_raw_socket. + + basic_raw_socket( + boost::asio::io_service & io_service, + const protocol_type & protocol); + + +This constructor creates and opens a raw socket. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the raw socket will use to dispatch handlers for any asynchronous operations performed on the socket.]] + +[[protocol][An object specifying protocol parameters to be used.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload3 basic_raw_socket::basic_raw_socket (3 of 4 overloads)] + +Construct a basic_raw_socket, opening it and binding it to the given local endpoint. + + basic_raw_socket( + boost::asio::io_service & io_service, + const endpoint_type & endpoint); + + +This constructor creates a raw socket and automatically opens it bound to the specified endpoint on the local machine. The protocol used is the protocol associated with the given endpoint. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the raw socket will use to dispatch handlers for any asynchronous operations performed on the socket.]] + +[[endpoint][An endpoint on the local machine to which the raw socket will be bound.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload4 basic_raw_socket::basic_raw_socket (4 of 4 overloads)] + +Construct a basic_raw_socket on an existing native socket. + + basic_raw_socket( + boost::asio::io_service & io_service, + const protocol_type & protocol, + const native_type & native_socket); + + +This constructor creates a raw socket object to hold an existing native socket. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the raw socket will use to dispatch handlers for any asynchronous operations performed on the socket.]] + +[[protocol][An object specifying protocol parameters to be used.]] + +[[native_socket][The new underlying socket implementation.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + +[endsect] + +[section:bind basic_raw_socket::bind] + +Bind the socket to the given local endpoint. + + void ``[link boost_asio.reference.basic_raw_socket.bind.overload1 bind]``( + const endpoint_type & endpoint); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.bind.overload2 bind]``( + const endpoint_type & endpoint, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::bind (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Bind the socket to the given local endpoint. + + void bind( + const endpoint_type & endpoint); + + +This function binds the socket to the specified endpoint on the local machine. + + +[heading Parameters] + + +[variablelist + +[[endpoint][An endpoint on the local machine to which the socket will be bound.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + socket.open(boost::asio::ip::tcp::v4()); + socket.bind(boost::asio::ip::tcp::endpoint( + boost::asio::ip::tcp::v4(), 12345)); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::bind (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Bind the socket to the given local endpoint. + + boost::system::error_code bind( + const endpoint_type & endpoint, + boost::system::error_code & ec); + + +This function binds the socket to the specified endpoint on the local machine. + + +[heading Parameters] + + +[variablelist + +[[endpoint][An endpoint on the local machine to which the socket will be bound.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + socket.open(boost::asio::ip::tcp::v4()); + boost::system::error_code ec; + socket.bind(boost::asio::ip::tcp::endpoint( + boost::asio::ip::tcp::v4(), 12345), ec); + if (ec) + { + // An error occurred. + } + + + + + + +[endsect] + + +[endsect] + + +[section:broadcast basic_raw_socket::broadcast] + + +['Inherited from socket_base.] + +Socket option to permit sending of broadcast messages. + + typedef implementation_defined broadcast; + + + +Implements the SOL\_SOCKET/SO\_BROADCAST socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::udp::socket socket(io_service); + ... + boost::asio::socket_base::broadcast option(true); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::udp::socket socket(io_service); + ... + boost::asio::socket_base::broadcast option; + socket.get_option(option); + bool is_set = option.value(); + + + + + + +[endsect] + + + +[section:bytes_readable basic_raw_socket::bytes_readable] + + +['Inherited from socket_base.] + +IO control command to get the amount of data that can be read without blocking. + + typedef implementation_defined bytes_readable; + + + +Implements the FIONREAD IO control command. + + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::bytes_readable command(true); + socket.io_control(command); + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + +[section:cancel basic_raw_socket::cancel] + +Cancel all asynchronous operations associated with the socket. + + void ``[link boost_asio.reference.basic_raw_socket.cancel.overload1 cancel]``(); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.cancel.overload2 cancel]``( + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::cancel (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Cancel all asynchronous operations associated with the socket. + + void cancel(); + + +This function causes all outstanding asynchronous connect, send and receive operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +Calls to cancel() will always fail with boost::asio::error::operation\_not\_supported when run on Windows XP, Windows Server 2003, and earlier versions of Windows, unless BOOST\_ASIO\_ENABLE\_CANCELIO is defined. However, the CancelIo function has two issues that should be considered before enabling its use: + +* It will only cancel asynchronous operations that were initiated in the current thread. + +* It can appear to complete without error, but the request to cancel the unfinished operations may be silently ignored by the operating system. Whether it works or not seems to depend on the drivers that are installed. + +For portable cancellation, consider using one of the following alternatives: + + +* Disable asio's I/O completion port backend by defining BOOST_ASIO_DISABLE_IOCP. + +* Use the close() function to simultaneously cancel the outstanding operations and close the socket. + +When running on Windows Vista, Windows Server 2008, and later, the CancelIoEx function is always used. This function does not have the problems described above. + + +[endsect] + + + +[section:overload2 basic_raw_socket::cancel (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Cancel all asynchronous operations associated with the socket. + + boost::system::error_code cancel( + boost::system::error_code & ec); + + +This function causes all outstanding asynchronous connect, send and receive operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Remarks] + +Calls to cancel() will always fail with boost::asio::error::operation\_not\_supported when run on Windows XP, Windows Server 2003, and earlier versions of Windows, unless BOOST\_ASIO\_ENABLE\_CANCELIO is defined. However, the CancelIo function has two issues that should be considered before enabling its use: + +* It will only cancel asynchronous operations that were initiated in the current thread. + +* It can appear to complete without error, but the request to cancel the unfinished operations may be silently ignored by the operating system. Whether it works or not seems to depend on the drivers that are installed. + +For portable cancellation, consider using one of the following alternatives: + + +* Disable asio's I/O completion port backend by defining BOOST_ASIO_DISABLE_IOCP. + +* Use the close() function to simultaneously cancel the outstanding operations and close the socket. + +When running on Windows Vista, Windows Server 2008, and later, the CancelIoEx function is always used. This function does not have the problems described above. + + +[endsect] + + +[endsect] + +[section:close basic_raw_socket::close] + +Close the socket. + + void ``[link boost_asio.reference.basic_raw_socket.close.overload1 close]``(); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.close.overload2 close]``( + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::close (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Close the socket. + + void close(); + + +This function is used to close the socket. Any asynchronous send, receive or connect operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +For portable behaviour with respect to graceful closure of a connected socket, call shutdown() before closing the socket. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::close (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Close the socket. + + boost::system::error_code close( + boost::system::error_code & ec); + + +This function is used to close the socket. Any asynchronous send, receive or connect operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::system::error_code ec; + socket.close(ec); + if (ec) + { + // An error occurred. + } + + + + +[heading Remarks] + +For portable behaviour with respect to graceful closure of a connected socket, call shutdown() before closing the socket. + + + +[endsect] + + +[endsect] + +[section:connect basic_raw_socket::connect] + +Connect the socket to the specified endpoint. + + void ``[link boost_asio.reference.basic_raw_socket.connect.overload1 connect]``( + const endpoint_type & peer_endpoint); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.connect.overload2 connect]``( + const endpoint_type & peer_endpoint, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::connect (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Connect the socket to the specified endpoint. + + void connect( + const endpoint_type & peer_endpoint); + + +This function is used to connect a socket to the specified remote endpoint. The function call will block until the connection is successfully made or an error occurs. + +The socket is automatically opened if it is not already open. If the connect fails, and the socket was automatically opened, the socket is returned to the closed state. + + +[heading Parameters] + + +[variablelist + +[[peer_endpoint][The remote endpoint to which the socket will be connected.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + boost::asio::ip::tcp::endpoint endpoint( + boost::asio::ip::address::from_string("1.2.3.4"), 12345); + socket.connect(endpoint); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::connect (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Connect the socket to the specified endpoint. + + boost::system::error_code connect( + const endpoint_type & peer_endpoint, + boost::system::error_code & ec); + + +This function is used to connect a socket to the specified remote endpoint. The function call will block until the connection is successfully made or an error occurs. + +The socket is automatically opened if it is not already open. If the connect fails, and the socket was automatically opened, the socket is returned to the closed state. + + +[heading Parameters] + + +[variablelist + +[[peer_endpoint][The remote endpoint to which the socket will be connected.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + boost::asio::ip::tcp::endpoint endpoint( + boost::asio::ip::address::from_string("1.2.3.4"), 12345); + boost::system::error_code ec; + socket.connect(endpoint, ec); + if (ec) + { + // An error occurred. + } + + + + + + +[endsect] + + +[endsect] + + +[section:debug basic_raw_socket::debug] + + +['Inherited from socket_base.] + +Socket option to enable socket-level debugging. + + typedef implementation_defined debug; + + + +Implements the SOL\_SOCKET/SO\_DEBUG socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::debug option(true); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::debug option; + socket.get_option(option); + bool is_set = option.value(); + + + + + + +[endsect] + + + +[section:do_not_route basic_raw_socket::do_not_route] + + +['Inherited from socket_base.] + +Socket option to prevent routing, use local interfaces only. + + typedef implementation_defined do_not_route; + + + +Implements the SOL\_SOCKET/SO\_DONTROUTE socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::udp::socket socket(io_service); + ... + boost::asio::socket_base::do_not_route option(true); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::udp::socket socket(io_service); + ... + boost::asio::socket_base::do_not_route option; + socket.get_option(option); + bool is_set = option.value(); + + + + + + +[endsect] + + + +[section:enable_connection_aborted basic_raw_socket::enable_connection_aborted] + + +['Inherited from socket_base.] + +Socket option to report aborted connections on accept. + + typedef implementation_defined enable_connection_aborted; + + + +Implements a custom socket option that determines whether or not an accept operation is permitted to fail with boost::asio::error::connection\_aborted. By default the option is false. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::acceptor acceptor(io_service); + ... + boost::asio::socket_base::enable_connection_aborted option(true); + acceptor.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::acceptor acceptor(io_service); + ... + boost::asio::socket_base::enable_connection_aborted option; + acceptor.get_option(option); + bool is_set = option.value(); + + + + + + +[endsect] + + + +[section:endpoint_type basic_raw_socket::endpoint_type] + +The endpoint type. + + typedef Protocol::endpoint endpoint_type; + + + + +[endsect] + + + +[section:get_io_service basic_raw_socket::get_io_service] + + +['Inherited from basic_io_object.] + +Get the io_service associated with the object. + + boost::asio::io_service & get_io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + +[section:get_option basic_raw_socket::get_option] + +Get an option from the socket. + + void ``[link boost_asio.reference.basic_raw_socket.get_option.overload1 get_option]``( + GettableSocketOption & option) const; + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.get_option.overload2 get_option]``( + GettableSocketOption & option, + boost::system::error_code & ec) const; + + +[section:overload1 basic_raw_socket::get_option (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Get an option from the socket. + + void get_option( + GettableSocketOption & option) const; + + +This function is used to get the current value of an option on the socket. + + +[heading Parameters] + + +[variablelist + +[[option][The option value to be obtained from the socket.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +Getting the value of the SOL\_SOCKET/SO\_KEEPALIVE option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::ip::tcp::socket::keep_alive option; + socket.get_option(option); + bool is_set = option.get(); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::get_option (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Get an option from the socket. + + boost::system::error_code get_option( + GettableSocketOption & option, + boost::system::error_code & ec) const; + + +This function is used to get the current value of an option on the socket. + + +[heading Parameters] + + +[variablelist + +[[option][The option value to be obtained from the socket.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + +Getting the value of the SOL\_SOCKET/SO\_KEEPALIVE option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::ip::tcp::socket::keep_alive option; + boost::system::error_code ec; + socket.get_option(option, ec); + if (ec) + { + // An error occurred. + } + bool is_set = option.get(); + + + + + + +[endsect] + + +[endsect] + + +[section:implementation basic_raw_socket::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + +[section:implementation_type basic_raw_socket::implementation_type] + + +['Inherited from basic_io_object.] + +The underlying implementation type of I/O object. + + typedef service_type::implementation_type implementation_type; + + + + +[endsect] + + +[section:io_control basic_raw_socket::io_control] + +Perform an IO control command on the socket. + + void ``[link boost_asio.reference.basic_raw_socket.io_control.overload1 io_control]``( + IoControlCommand & command); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.io_control.overload2 io_control]``( + IoControlCommand & command, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::io_control (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Perform an IO control command on the socket. + + void io_control( + IoControlCommand & command); + + +This function is used to execute an IO control command on the socket. + + +[heading Parameters] + + +[variablelist + +[[command][The IO control command to be performed on the socket.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +Getting the number of bytes ready to read: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::ip::tcp::socket::bytes_readable command; + socket.io_control(command); + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::io_control (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Perform an IO control command on the socket. + + boost::system::error_code io_control( + IoControlCommand & command, + boost::system::error_code & ec); + + +This function is used to execute an IO control command on the socket. + + +[heading Parameters] + + +[variablelist + +[[command][The IO control command to be performed on the socket.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + +Getting the number of bytes ready to read: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::ip::tcp::socket::bytes_readable command; + boost::system::error_code ec; + socket.io_control(command, ec); + if (ec) + { + // An error occurred. + } + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + +[endsect] + + +[section:io_service basic_raw_socket::io_service] + + +['Inherited from basic_io_object.] + +(Deprecated: use get_io_service().) Get the io_service associated with the object. + + boost::asio::io_service & io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:is_open basic_raw_socket::is_open] + + +['Inherited from basic_socket.] + +Determine whether the socket is open. + + bool is_open() const; + + + +[endsect] + + + +[section:keep_alive basic_raw_socket::keep_alive] + + +['Inherited from socket_base.] + +Socket option to send keep-alives. + + typedef implementation_defined keep_alive; + + + +Implements the SOL\_SOCKET/SO\_KEEPALIVE socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::keep_alive option(true); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::keep_alive option; + socket.get_option(option); + bool is_set = option.value(); + + + + + + +[endsect] + + + +[section:linger basic_raw_socket::linger] + + +['Inherited from socket_base.] + +Socket option to specify whether the socket lingers on close if unsent data is present. + + typedef implementation_defined linger; + + + +Implements the SOL\_SOCKET/SO\_LINGER socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::linger option(true, 30); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::linger option; + socket.get_option(option); + bool is_set = option.enabled(); + unsigned short timeout = option.timeout(); + + + + + + +[endsect] + + +[section:local_endpoint basic_raw_socket::local_endpoint] + +Get the local endpoint of the socket. + + endpoint_type ``[link boost_asio.reference.basic_raw_socket.local_endpoint.overload1 local_endpoint]``() const; + + endpoint_type ``[link boost_asio.reference.basic_raw_socket.local_endpoint.overload2 local_endpoint]``( + boost::system::error_code & ec) const; + + +[section:overload1 basic_raw_socket::local_endpoint (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Get the local endpoint of the socket. + + endpoint_type local_endpoint() const; + + +This function is used to obtain the locally bound endpoint of the socket. + + +[heading Return Value] + +An object that represents the local endpoint of the socket. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::local_endpoint (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Get the local endpoint of the socket. + + endpoint_type local_endpoint( + boost::system::error_code & ec) const; + + +This function is used to obtain the locally bound endpoint of the socket. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +An object that represents the local endpoint of the socket. Returns a default-constructed endpoint object if an error occurred. + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::system::error_code ec; + boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); + if (ec) + { + // An error occurred. + } + + + + + + +[endsect] + + +[endsect] + + +[section:lowest_layer basic_raw_socket::lowest_layer] + + +['Inherited from basic_socket.] + +Get a reference to the lowest layer. + + lowest_layer_type & lowest_layer(); + + +This function returns a reference to the lowest layer in a stack of layers. Since a basic_socket cannot contain any further layers, it simply returns a reference to itself. + + +[heading Return Value] + +A reference to the lowest layer in the stack of layers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:lowest_layer_type basic_raw_socket::lowest_layer_type] + + +['Inherited from basic_socket.] + +A basic_socket is always the lowest layer. + + typedef basic_socket< Protocol, RawSocketService > lowest_layer_type; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_socket.broadcast [*broadcast]]] + [Socket option to permit sending of broadcast messages. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.debug [*debug]]] + [Socket option to enable socket-level debugging. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.do_not_route [*do_not_route]]] + [Socket option to prevent routing, use local interfaces only. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.enable_connection_aborted [*enable_connection_aborted]]] + [Socket option to report aborted connections on accept. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.endpoint_type [*endpoint_type]]] + [The endpoint type. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.keep_alive [*keep_alive]]] + [Socket option to send keep-alives. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.linger [*linger]]] + [Socket option to specify whether the socket lingers on close if unsent data is present. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.lowest_layer_type [*lowest_layer_type]]] + [A basic_socket is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.message_flags [*message_flags]]] + [Bitmask type for flags that can be passed to send and receive operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.native_type [*native_type]]] + [The native representation of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.protocol_type [*protocol_type]]] + [The protocol type. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.receive_buffer_size [*receive_buffer_size]]] + [Socket option for the receive buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.receive_low_watermark [*receive_low_watermark]]] + [Socket option for the receive low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.reuse_address [*reuse_address]]] + [Socket option to allow the socket to be bound to an address that is already in use. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.send_buffer_size [*send_buffer_size]]] + [Socket option for the send buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.send_low_watermark [*send_low_watermark]]] + [Socket option for the send low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket.shutdown_type [*shutdown_type]]] + [Different ways a socket may be shutdown. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket.assign [*assign]]] + [Assign an existing native socket to the socket. ] + ] + + [ + [[link boost_asio.reference.basic_socket.async_connect [*async_connect]]] + [Start an asynchronous connect. ] + ] + + [ + [[link boost_asio.reference.basic_socket.at_mark [*at_mark]]] + [Determine whether the socket is at the out-of-band data mark. ] + ] + + [ + [[link boost_asio.reference.basic_socket.available [*available]]] + [Determine the number of bytes available for reading. ] + ] + + [ + [[link boost_asio.reference.basic_socket.basic_socket [*basic_socket]]] + [Construct a basic_socket without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_socket.bind [*bind]]] + [Bind the socket to the given local endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_socket.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the socket. ] + ] + + [ + [[link boost_asio.reference.basic_socket.close [*close]]] + [Close the socket. ] + ] + + [ + [[link boost_asio.reference.basic_socket.connect [*connect]]] + [Connect the socket to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_socket.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_socket.get_option [*get_option]]] + [Get an option from the socket. ] + ] + + [ + [[link boost_asio.reference.basic_socket.io_control [*io_control]]] + [Perform an IO control command on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_socket.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_socket.is_open [*is_open]]] + [Determine whether the socket is open. ] + ] + + [ + [[link boost_asio.reference.basic_socket.local_endpoint [*local_endpoint]]] + [Get the local endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_socket.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.basic_socket.native [*native]]] + [Get the native socket representation. ] + ] + + [ + [[link boost_asio.reference.basic_socket.open [*open]]] + [Open the socket using the specified protocol. ] + ] + + [ + [[link boost_asio.reference.basic_socket.remote_endpoint [*remote_endpoint]]] + [Get the remote endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_socket.set_option [*set_option]]] + [Set an option on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_socket.shutdown [*shutdown]]] + [Disable sends or receives on the socket. ] + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket._basic_socket [*~basic_socket]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket.max_connections [*max_connections]]] + [The maximum length of the queue of pending incoming connections. ] + ] + + [ + [[link boost_asio.reference.basic_socket.message_do_not_route [*message_do_not_route]]] + [Specify that the data should not be subject to routing. ] + ] + + [ + [[link boost_asio.reference.basic_socket.message_out_of_band [*message_out_of_band]]] + [Process out-of-band data. ] + ] + + [ + [[link boost_asio.reference.basic_socket.message_peek [*message_peek]]] + [Peek at incoming data without removing it from the input queue. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_socket class template provides functionality that is common to both stream-oriented and datagram-oriented sockets. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:max_connections basic_raw_socket::max_connections] + + +['Inherited from socket_base.] + +The maximum length of the queue of pending incoming connections. + + static const int max_connections = implementation_defined; + + + +[endsect] + + + +[section:message_do_not_route basic_raw_socket::message_do_not_route] + + +['Inherited from socket_base.] + +Specify that the data should not be subject to routing. + + static const int message_do_not_route = implementation_defined; + + + +[endsect] + + + +[section:message_flags basic_raw_socket::message_flags] + + +['Inherited from socket_base.] + +Bitmask type for flags that can be passed to send and receive operations. + + typedef int message_flags; + + + + +[endsect] + + + +[section:message_out_of_band basic_raw_socket::message_out_of_band] + + +['Inherited from socket_base.] + +Process out-of-band data. + + static const int message_out_of_band = implementation_defined; + + + +[endsect] + + + +[section:message_peek basic_raw_socket::message_peek] + + +['Inherited from socket_base.] + +Peek at incoming data without removing it from the input queue. + + static const int message_peek = implementation_defined; + + + +[endsect] + + + +[section:native basic_raw_socket::native] + + +['Inherited from basic_socket.] + +Get the native socket representation. + + native_type native(); + + +This function may be used to obtain the underlying representation of the socket. This is intended to allow access to native socket functionality that is not otherwise provided. + + +[endsect] + + + +[section:native_type basic_raw_socket::native_type] + +The native representation of a socket. + + typedef RawSocketService::native_type native_type; + + + + +[endsect] + + + +[section:non_blocking_io basic_raw_socket::non_blocking_io] + + +['Inherited from socket_base.] + +IO control command to set the blocking mode of the socket. + + typedef implementation_defined non_blocking_io; + + + +Implements the FIONBIO IO control command. + + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::non_blocking_io command(true); + socket.io_control(command); + + + + + + +[endsect] + + +[section:open basic_raw_socket::open] + +Open the socket using the specified protocol. + + void ``[link boost_asio.reference.basic_raw_socket.open.overload1 open]``( + const protocol_type & protocol = protocol_type()); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.open.overload2 open]``( + const protocol_type & protocol, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::open (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Open the socket using the specified protocol. + + void open( + const protocol_type & protocol = protocol_type()); + + +This function opens the socket so that it will use the specified protocol. + + +[heading Parameters] + + +[variablelist + +[[protocol][An object specifying protocol parameters to be used.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + socket.open(boost::asio::ip::tcp::v4()); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::open (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Open the socket using the specified protocol. + + boost::system::error_code open( + const protocol_type & protocol, + boost::system::error_code & ec); + + +This function opens the socket so that it will use the specified protocol. + + +[heading Parameters] + + +[variablelist + +[[protocol][An object specifying which protocol is to be used.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + boost::system::error_code ec; + socket.open(boost::asio::ip::tcp::v4(), ec); + if (ec) + { + // An error occurred. + } + + + + + + +[endsect] + + +[endsect] + + +[section:protocol_type basic_raw_socket::protocol_type] + +The protocol type. + + typedef Protocol protocol_type; + + + + +[endsect] + + +[section:receive basic_raw_socket::receive] + +Receive some data on a connected socket. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.receive.overload1 receive]``( + const MutableBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.receive.overload2 receive]``( + const MutableBufferSequence & buffers, + socket_base::message_flags flags); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.receive.overload3 receive]``( + const MutableBufferSequence & buffers, + socket_base::message_flags flags, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::receive (1 of 3 overloads)] + +Receive some data on a connected socket. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t receive( + const MutableBufferSequence & buffers); + + +This function is used to receive data on the raw socket. The function call will block until data has been received successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received.]] + +] + +[heading Return Value] + +The number of bytes received. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +The receive operation can only be used with a connected socket. Use the receive\_from function to receive data on an unconnected raw socket. + +[heading Example] + +To receive into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + socket.receive(boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on receiving into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::receive (2 of 3 overloads)] + +Receive some data on a connected socket. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t receive( + const MutableBufferSequence & buffers, + socket_base::message_flags flags); + + +This function is used to receive data on the raw socket. The function call will block until data has been received successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received.]] + +[[flags][Flags specifying how the receive call is to be made.]] + +] + +[heading Return Value] + +The number of bytes received. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +The receive operation can only be used with a connected socket. Use the receive\_from function to receive data on an unconnected raw socket. + + + +[endsect] + + + +[section:overload3 basic_raw_socket::receive (3 of 3 overloads)] + +Receive some data on a connected socket. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t receive( + const MutableBufferSequence & buffers, + socket_base::message_flags flags, + boost::system::error_code & ec); + + +This function is used to receive data on the raw socket. The function call will block until data has been received successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received.]] + +[[flags][Flags specifying how the receive call is to be made.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes received. + +[heading Remarks] + +The receive operation can only be used with a connected socket. Use the receive\_from function to receive data on an unconnected raw socket. + + + +[endsect] + + +[endsect] + + +[section:receive_buffer_size basic_raw_socket::receive_buffer_size] + + +['Inherited from socket_base.] + +Socket option for the receive buffer size of a socket. + + typedef implementation_defined receive_buffer_size; + + + +Implements the SOL\_SOCKET/SO\_RCVBUF socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::receive_buffer_size option(8192); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::receive_buffer_size option; + socket.get_option(option); + int size = option.value(); + + + + + + +[endsect] + + +[section:receive_from basic_raw_socket::receive_from] + +Receive raw data with the endpoint of the sender. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.receive_from.overload1 receive_from]``( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.receive_from.overload2 receive_from]``( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + socket_base::message_flags flags); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.receive_from.overload3 receive_from]``( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + socket_base::message_flags flags, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::receive_from (1 of 3 overloads)] + +Receive raw data with the endpoint of the sender. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t receive_from( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint); + + +This function is used to receive raw data. The function call will block until data has been received successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received.]] + +[[sender_endpoint][An endpoint object that receives the endpoint of the remote sender of the data.]] + +] + +[heading Return Value] + +The number of bytes received. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +To receive into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::ip::udp::endpoint sender_endpoint; + socket.receive_from( + boost::asio::buffer(data, size), sender_endpoint); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on receiving into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::receive_from (2 of 3 overloads)] + +Receive raw data with the endpoint of the sender. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t receive_from( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + socket_base::message_flags flags); + + +This function is used to receive raw data. The function call will block until data has been received successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received.]] + +[[sender_endpoint][An endpoint object that receives the endpoint of the remote sender of the data.]] + +[[flags][Flags specifying how the receive call is to be made.]] + +] + +[heading Return Value] + +The number of bytes received. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload3 basic_raw_socket::receive_from (3 of 3 overloads)] + +Receive raw data with the endpoint of the sender. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t receive_from( + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + socket_base::message_flags flags, + boost::system::error_code & ec); + + +This function is used to receive raw data. The function call will block until data has been received successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be received.]] + +[[sender_endpoint][An endpoint object that receives the endpoint of the remote sender of the data.]] + +[[flags][Flags specifying how the receive call is to be made.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes received. + + + +[endsect] + + +[endsect] + + +[section:receive_low_watermark basic_raw_socket::receive_low_watermark] + + +['Inherited from socket_base.] + +Socket option for the receive low watermark. + + typedef implementation_defined receive_low_watermark; + + + +Implements the SOL\_SOCKET/SO\_RCVLOWAT socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::receive_low_watermark option(1024); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::receive_low_watermark option; + socket.get_option(option); + int size = option.value(); + + + + + + +[endsect] + + +[section:remote_endpoint basic_raw_socket::remote_endpoint] + +Get the remote endpoint of the socket. + + endpoint_type ``[link boost_asio.reference.basic_raw_socket.remote_endpoint.overload1 remote_endpoint]``() const; + + endpoint_type ``[link boost_asio.reference.basic_raw_socket.remote_endpoint.overload2 remote_endpoint]``( + boost::system::error_code & ec) const; + + +[section:overload1 basic_raw_socket::remote_endpoint (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Get the remote endpoint of the socket. + + endpoint_type remote_endpoint() const; + + +This function is used to obtain the remote endpoint of the socket. + + +[heading Return Value] + +An object that represents the remote endpoint of the socket. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::remote_endpoint (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Get the remote endpoint of the socket. + + endpoint_type remote_endpoint( + boost::system::error_code & ec) const; + + +This function is used to obtain the remote endpoint of the socket. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +An object that represents the remote endpoint of the socket. Returns a default-constructed endpoint object if an error occurred. + +[heading Example] + + + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::system::error_code ec; + boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); + if (ec) + { + // An error occurred. + } + + + + + + +[endsect] + + +[endsect] + + +[section:reuse_address basic_raw_socket::reuse_address] + + +['Inherited from socket_base.] + +Socket option to allow the socket to be bound to an address that is already in use. + + typedef implementation_defined reuse_address; + + + +Implements the SOL\_SOCKET/SO\_REUSEADDR socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::acceptor acceptor(io_service); + ... + boost::asio::socket_base::reuse_address option(true); + acceptor.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::acceptor acceptor(io_service); + ... + boost::asio::socket_base::reuse_address option; + acceptor.get_option(option); + bool is_set = option.value(); + + + + + + +[endsect] + + +[section:send basic_raw_socket::send] + +Send some data on a connected socket. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.send.overload1 send]``( + const ConstBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.send.overload2 send]``( + const ConstBufferSequence & buffers, + socket_base::message_flags flags); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.send.overload3 send]``( + const ConstBufferSequence & buffers, + socket_base::message_flags flags, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::send (1 of 3 overloads)] + +Send some data on a connected socket. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t send( + const ConstBufferSequence & buffers); + + +This function is used to send data on the raw socket. The function call will block until the data has been sent successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One ore more data buffers to be sent on the socket.]] + +] + +[heading Return Value] + +The number of bytes sent. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +The send operation can only be used with a connected socket. Use the send\_to function to send data on an unconnected raw socket. + +[heading Example] + +To send a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + socket.send(boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on sending multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::send (2 of 3 overloads)] + +Send some data on a connected socket. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t send( + const ConstBufferSequence & buffers, + socket_base::message_flags flags); + + +This function is used to send data on the raw socket. The function call will block until the data has been sent successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One ore more data buffers to be sent on the socket.]] + +[[flags][Flags specifying how the send call is to be made.]] + +] + +[heading Return Value] + +The number of bytes sent. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +The send operation can only be used with a connected socket. Use the send\_to function to send data on an unconnected raw socket. + + + +[endsect] + + + +[section:overload3 basic_raw_socket::send (3 of 3 overloads)] + +Send some data on a connected socket. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t send( + const ConstBufferSequence & buffers, + socket_base::message_flags flags, + boost::system::error_code & ec); + + +This function is used to send data on the raw socket. The function call will block until the data has been sent successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be sent on the socket.]] + +[[flags][Flags specifying how the send call is to be made.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes sent. + +[heading Remarks] + +The send operation can only be used with a connected socket. Use the send\_to function to send data on an unconnected raw socket. + + + +[endsect] + + +[endsect] + + +[section:send_buffer_size basic_raw_socket::send_buffer_size] + + +['Inherited from socket_base.] + +Socket option for the send buffer size of a socket. + + typedef implementation_defined send_buffer_size; + + + +Implements the SOL\_SOCKET/SO\_SNDBUF socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::send_buffer_size option(8192); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::send_buffer_size option; + socket.get_option(option); + int size = option.value(); + + + + + + +[endsect] + + + +[section:send_low_watermark basic_raw_socket::send_low_watermark] + + +['Inherited from socket_base.] + +Socket option for the send low watermark. + + typedef implementation_defined send_low_watermark; + + + +Implements the SOL\_SOCKET/SO\_SNDLOWAT socket option. + + +[heading Examples] + +Setting the option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::send_low_watermark option(1024); + socket.set_option(option); + + + + +Getting the current option value: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::socket_base::send_low_watermark option; + socket.get_option(option); + int size = option.value(); + + + + + + +[endsect] + + +[section:send_to basic_raw_socket::send_to] + +Send raw data to the specified endpoint. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.send_to.overload1 send_to]``( + const ConstBufferSequence & buffers, + const endpoint_type & destination); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.send_to.overload2 send_to]``( + const ConstBufferSequence & buffers, + const endpoint_type & destination, + socket_base::message_flags flags); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_raw_socket.send_to.overload3 send_to]``( + const ConstBufferSequence & buffers, + const endpoint_type & destination, + socket_base::message_flags flags, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::send_to (1 of 3 overloads)] + +Send raw data to the specified endpoint. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t send_to( + const ConstBufferSequence & buffers, + const endpoint_type & destination); + + +This function is used to send raw data to the specified remote endpoint. The function call will block until the data has been sent successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be sent to the remote endpoint.]] + +[[destination][The remote endpoint to which the data will be sent.]] + +] + +[heading Return Value] + +The number of bytes sent. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +To send a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::ip::udp::endpoint destination( + boost::asio::ip::address::from_string("1.2.3.4"), 12345); + socket.send_to(boost::asio::buffer(data, size), destination); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on sending multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_raw_socket::send_to (2 of 3 overloads)] + +Send raw data to the specified endpoint. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t send_to( + const ConstBufferSequence & buffers, + const endpoint_type & destination, + socket_base::message_flags flags); + + +This function is used to send raw data to the specified remote endpoint. The function call will block until the data has been sent successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be sent to the remote endpoint.]] + +[[destination][The remote endpoint to which the data will be sent.]] + +[[flags][Flags specifying how the send call is to be made.]] + +] + +[heading Return Value] + +The number of bytes sent. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload3 basic_raw_socket::send_to (3 of 3 overloads)] + +Send raw data to the specified endpoint. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t send_to( + const ConstBufferSequence & buffers, + const endpoint_type & destination, + socket_base::message_flags flags, + boost::system::error_code & ec); + + +This function is used to send raw data to the specified remote endpoint. The function call will block until the data has been sent successfully or an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be sent to the remote endpoint.]] + +[[destination][The remote endpoint to which the data will be sent.]] + +[[flags][Flags specifying how the send call is to be made.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes sent. + + + +[endsect] + + +[endsect] + + +[section:service basic_raw_socket::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + +[section:service_type basic_raw_socket::service_type] + + +['Inherited from basic_io_object.] + +The type of the service that will be used to provide I/O operations. + + typedef RawSocketService service_type; + + + + +[endsect] + + +[section:set_option basic_raw_socket::set_option] + +Set an option on the socket. + + void ``[link boost_asio.reference.basic_raw_socket.set_option.overload1 set_option]``( + const SettableSocketOption & option); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.set_option.overload2 set_option]``( + const SettableSocketOption & option, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::set_option (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Set an option on the socket. + + void set_option( + const SettableSocketOption & option); + + +This function is used to set an option on the socket. + + +[heading Parameters] + + +[variablelist + +[[option][The new option value to be set on the socket.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +Setting the IPPROTO\_TCP/TCP\_NODELAY option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::ip::tcp::no_delay option(true); + socket.set_option(option); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::set_option (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Set an option on the socket. + + boost::system::error_code set_option( + const SettableSocketOption & option, + boost::system::error_code & ec); + + +This function is used to set an option on the socket. + + +[heading Parameters] + + +[variablelist + +[[option][The new option value to be set on the socket.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + +Setting the IPPROTO\_TCP/TCP\_NODELAY option: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::asio::ip::tcp::no_delay option(true); + boost::system::error_code ec; + socket.set_option(option, ec); + if (ec) + { + // An error occurred. + } + + + + + + +[endsect] + + +[endsect] + +[section:shutdown basic_raw_socket::shutdown] + +Disable sends or receives on the socket. + + void ``[link boost_asio.reference.basic_raw_socket.shutdown.overload1 shutdown]``( + shutdown_type what); + + boost::system::error_code ``[link boost_asio.reference.basic_raw_socket.shutdown.overload2 shutdown]``( + shutdown_type what, + boost::system::error_code & ec); + + +[section:overload1 basic_raw_socket::shutdown (1 of 2 overloads)] + + +['Inherited from basic_socket.] + +Disable sends or receives on the socket. + + void shutdown( + shutdown_type what); + + +This function is used to disable send operations, receive operations, or both. + + +[heading Parameters] + + +[variablelist + +[[what][Determines what types of operation will no longer be allowed.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +Shutting down the send side of the socket: + + boost::asio::ip::tcp::socket socket(io_service); + ... + socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); + + + + + + +[endsect] + + + +[section:overload2 basic_raw_socket::shutdown (2 of 2 overloads)] + + +['Inherited from basic_socket.] + +Disable sends or receives on the socket. + + boost::system::error_code shutdown( + shutdown_type what, + boost::system::error_code & ec); + + +This function is used to disable send operations, receive operations, or both. + + +[heading Parameters] + + +[variablelist + +[[what][Determines what types of operation will no longer be allowed.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + +Shutting down the send side of the socket: + + boost::asio::ip::tcp::socket socket(io_service); + ... + boost::system::error_code ec; + socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); + if (ec) + { + // An error occurred. + } + + + + + + +[endsect] + + +[endsect] + + +[section:shutdown_type basic_raw_socket::shutdown_type] + + +['Inherited from socket_base.] + +Different ways a socket may be shutdown. + + enum shutdown_type + +[heading Values] +[variablelist + + [ + [shutdown_receive] + [Shutdown the receive side of the socket. ] + ] + + [ + [shutdown_send] + [Shutdown the send side of the socket. ] + ] + + [ + [shutdown_both] + [Shutdown both send and receive on the socket. ] + ] + +] + + + +[endsect] + + + +[endsect] + +[section:basic_serial_port basic_serial_port] + +Provides serial port functionality. + + template< + typename ``[link boost_asio.reference.SerialPortService SerialPortService]`` = serial_port_service> + class basic_serial_port : + public basic_io_object< SerialPortService >, + public serial_port_base + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_serial_port.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.lowest_layer_type [*lowest_layer_type]]] + [A basic_serial_port is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.native_type [*native_type]]] + [The native representation of a serial port. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_serial_port.assign [*assign]]] + [Assign an existing native serial port to the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.basic_serial_port [*basic_serial_port]]] + [Construct a basic_serial_port without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.close [*close]]] + [Close the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.get_option [*get_option]]] + [Get an option from the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.is_open [*is_open]]] + [Determine whether the serial port is open. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.native [*native]]] + [Get the native serial port representation. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.open [*open]]] + [Open the serial port using the specified device name. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.read_some [*read_some]]] + [Read some data from the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.send_break [*send_break]]] + [Send a break sequence to the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.set_option [*set_option]]] + [Set an option on the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.write_some [*write_some]]] + [Write some data to the serial port. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_serial_port.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_serial_port class template provides functionality that is common to all serial ports. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + +[section:assign basic_serial_port::assign] + +Assign an existing native serial port to the serial port. + + void ``[link boost_asio.reference.basic_serial_port.assign.overload1 assign]``( + const native_type & native_serial_port); + + boost::system::error_code ``[link boost_asio.reference.basic_serial_port.assign.overload2 assign]``( + const native_type & native_serial_port, + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::assign (1 of 2 overloads)] + +Assign an existing native serial port to the serial port. + + void assign( + const native_type & native_serial_port); + + + +[endsect] + + + +[section:overload2 basic_serial_port::assign (2 of 2 overloads)] + +Assign an existing native serial port to the serial port. + + boost::system::error_code assign( + const native_type & native_serial_port, + boost::system::error_code & ec); + + + +[endsect] + + +[endsect] + + +[section:async_read_some basic_serial_port::async_read_some] + +Start an asynchronous read. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_some( + const MutableBufferSequence & buffers, + ReadHandler handler); + + +This function is used to asynchronously read data from the serial port. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes read. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The read operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.async_read async_read] function if you need to ensure that the requested amount of data is read before the asynchronous operation completes. + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + serial_port.async_read_some(boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:async_write_some basic_serial_port::async_write_some] + +Start an asynchronous write. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_some( + const ConstBufferSequence & buffers, + WriteHandler handler); + + +This function is used to asynchronously write data to the serial port. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the serial port. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes written. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The write operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.async_write async_write] function if you need to ensure that all data is written before the asynchronous operation completes. + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + serial_port.async_write_some(boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + +[section:basic_serial_port basic_serial_port::basic_serial_port] + +Construct a basic_serial_port without opening it. + + ``[link boost_asio.reference.basic_serial_port.basic_serial_port.overload1 basic_serial_port]``( + boost::asio::io_service & io_service); + + ``[link boost_asio.reference.basic_serial_port.basic_serial_port.overload2 basic_serial_port]``( + boost::asio::io_service & io_service, + const char * device); + + ``[link boost_asio.reference.basic_serial_port.basic_serial_port.overload3 basic_serial_port]``( + boost::asio::io_service & io_service, + const std::string & device); + + ``[link boost_asio.reference.basic_serial_port.basic_serial_port.overload4 basic_serial_port]``( + boost::asio::io_service & io_service, + const native_type & native_serial_port); + + +[section:overload1 basic_serial_port::basic_serial_port (1 of 4 overloads)] + +Construct a basic_serial_port without opening it. + + basic_serial_port( + boost::asio::io_service & io_service); + + +This constructor creates a serial port without opening it. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the serial port will use to dispatch handlers for any asynchronous operations performed on the port. ]] + +] + + + +[endsect] + + + +[section:overload2 basic_serial_port::basic_serial_port (2 of 4 overloads)] + +Construct and open a basic_serial_port. + + basic_serial_port( + boost::asio::io_service & io_service, + const char * device); + + +This constructor creates and opens a serial port for the specified device name. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the serial port will use to dispatch handlers for any asynchronous operations performed on the port.]] + +[[device][The platform-specific device name for this serial port. ]] + +] + + + +[endsect] + + + +[section:overload3 basic_serial_port::basic_serial_port (3 of 4 overloads)] + +Construct and open a basic_serial_port. + + basic_serial_port( + boost::asio::io_service & io_service, + const std::string & device); + + +This constructor creates and opens a serial port for the specified device name. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the serial port will use to dispatch handlers for any asynchronous operations performed on the port.]] + +[[device][The platform-specific device name for this serial port. ]] + +] + + + +[endsect] + + + +[section:overload4 basic_serial_port::basic_serial_port (4 of 4 overloads)] + +Construct a basic_serial_port on an existing native serial port. + + basic_serial_port( + boost::asio::io_service & io_service, + const native_type & native_serial_port); + + +This constructor creates a serial port object to hold an existing native serial port. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the serial port will use to dispatch handlers for any asynchronous operations performed on the port.]] + +[[native_serial_port][A native serial port.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + +[endsect] + +[section:cancel basic_serial_port::cancel] + +Cancel all asynchronous operations associated with the serial port. + + void ``[link boost_asio.reference.basic_serial_port.cancel.overload1 cancel]``(); + + boost::system::error_code ``[link boost_asio.reference.basic_serial_port.cancel.overload2 cancel]``( + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::cancel (1 of 2 overloads)] + +Cancel all asynchronous operations associated with the serial port. + + void cancel(); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 basic_serial_port::cancel (2 of 2 overloads)] + +Cancel all asynchronous operations associated with the serial port. + + boost::system::error_code cancel( + boost::system::error_code & ec); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + +[section:close basic_serial_port::close] + +Close the serial port. + + void ``[link boost_asio.reference.basic_serial_port.close.overload1 close]``(); + + boost::system::error_code ``[link boost_asio.reference.basic_serial_port.close.overload2 close]``( + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::close (1 of 2 overloads)] + +Close the serial port. + + void close(); + + +This function is used to close the serial port. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 basic_serial_port::close (2 of 2 overloads)] + +Close the serial port. + + boost::system::error_code close( + boost::system::error_code & ec); + + +This function is used to close the serial port. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:get_io_service basic_serial_port::get_io_service] + + +['Inherited from basic_io_object.] + +Get the io_service associated with the object. + + boost::asio::io_service & get_io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + +[section:get_option basic_serial_port::get_option] + +Get an option from the serial port. + + template< + typename ``[link boost_asio.reference.GettableSerialPortOption GettableSerialPortOption]``> + void ``[link boost_asio.reference.basic_serial_port.get_option.overload1 get_option]``( + GettableSerialPortOption & option); + + template< + typename ``[link boost_asio.reference.GettableSerialPortOption GettableSerialPortOption]``> + boost::system::error_code ``[link boost_asio.reference.basic_serial_port.get_option.overload2 get_option]``( + GettableSerialPortOption & option, + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::get_option (1 of 2 overloads)] + +Get an option from the serial port. + + template< + typename ``[link boost_asio.reference.GettableSerialPortOption GettableSerialPortOption]``> + void get_option( + GettableSerialPortOption & option); + + +This function is used to get the current value of an option on the serial port. + + +[heading Parameters] + + +[variablelist + +[[option][The option value to be obtained from the serial port.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + + + +[endsect] + + + +[section:overload2 basic_serial_port::get_option (2 of 2 overloads)] + +Get an option from the serial port. + + template< + typename ``[link boost_asio.reference.GettableSerialPortOption GettableSerialPortOption]``> + boost::system::error_code get_option( + GettableSerialPortOption & option, + boost::system::error_code & ec); + + +This function is used to get the current value of an option on the serial port. + + +[heading Parameters] + + +[variablelist + +[[option][The option value to be obtained from the serial port.]] + +[[ec][Set to indicate what error occured, if any.]] + +] + + + +[endsect] + + +[endsect] + + +[section:implementation basic_serial_port::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + +[section:implementation_type basic_serial_port::implementation_type] + + +['Inherited from basic_io_object.] + +The underlying implementation type of I/O object. + + typedef service_type::implementation_type implementation_type; + + + + +[endsect] + + + +[section:io_service basic_serial_port::io_service] + + +['Inherited from basic_io_object.] + +(Deprecated: use get_io_service().) Get the io_service associated with the object. + + boost::asio::io_service & io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:is_open basic_serial_port::is_open] + +Determine whether the serial port is open. + + bool is_open() const; + + + +[endsect] + + + +[section:lowest_layer basic_serial_port::lowest_layer] + +Get a reference to the lowest layer. + + lowest_layer_type & lowest_layer(); + + +This function returns a reference to the lowest layer in a stack of layers. Since a basic_serial_port cannot contain any further layers, it simply returns a reference to itself. + + +[heading Return Value] + +A reference to the lowest layer in the stack of layers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:lowest_layer_type basic_serial_port::lowest_layer_type] + +A basic_serial_port is always the lowest layer. + + typedef basic_serial_port< SerialPortService > lowest_layer_type; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_serial_port.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.lowest_layer_type [*lowest_layer_type]]] + [A basic_serial_port is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.native_type [*native_type]]] + [The native representation of a serial port. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_serial_port.assign [*assign]]] + [Assign an existing native serial port to the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.basic_serial_port [*basic_serial_port]]] + [Construct a basic_serial_port without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.close [*close]]] + [Close the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.get_option [*get_option]]] + [Get an option from the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.is_open [*is_open]]] + [Determine whether the serial port is open. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.native [*native]]] + [Get the native serial port representation. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.open [*open]]] + [Open the serial port using the specified device name. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.read_some [*read_some]]] + [Read some data from the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.send_break [*send_break]]] + [Send a break sequence to the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.set_option [*set_option]]] + [Set an option on the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.write_some [*write_some]]] + [Write some data to the serial port. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_serial_port.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_serial_port class template provides functionality that is common to all serial ports. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:native basic_serial_port::native] + +Get the native serial port representation. + + native_type native(); + + +This function may be used to obtain the underlying representation of the serial port. This is intended to allow access to native serial port functionality that is not otherwise provided. + + +[endsect] + + + +[section:native_type basic_serial_port::native_type] + +The native representation of a serial port. + + typedef SerialPortService::native_type native_type; + + + + +[endsect] + + +[section:open basic_serial_port::open] + +Open the serial port using the specified device name. + + void ``[link boost_asio.reference.basic_serial_port.open.overload1 open]``( + const std::string & device); + + boost::system::error_code ``[link boost_asio.reference.basic_serial_port.open.overload2 open]``( + const std::string & device, + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::open (1 of 2 overloads)] + +Open the serial port using the specified device name. + + void open( + const std::string & device); + + +This function opens the serial port for the specified device name. + + +[heading Parameters] + + +[variablelist + +[[device][The platform-specific device name.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 basic_serial_port::open (2 of 2 overloads)] + +Open the serial port using the specified device name. + + boost::system::error_code open( + const std::string & device, + boost::system::error_code & ec); + + +This function opens the serial port using the given platform-specific device name. + + +[heading Parameters] + + +[variablelist + +[[device][The platform-specific device name.]] + +[[ec][Set the indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + +[section:read_some basic_serial_port::read_some] + +Read some data from the serial port. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_serial_port.read_some.overload1 read_some]``( + const MutableBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_serial_port.read_some.overload2 read_some]``( + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::read_some (1 of 2 overloads)] + +Read some data from the serial port. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + const MutableBufferSequence & buffers); + + +This function is used to read data from the serial port. The function call will block until one or more bytes of data has been read successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read.]] + +] + +[heading Return Value] + +The number of bytes read. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. An error code of boost::asio::error::eof indicates that the connection was closed by the peer.]] + +] + +[heading Remarks] + +The read\_some operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.read read] function if you need to ensure that the requested amount of data is read before the blocking operation completes. + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + serial_port.read_some(boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_serial_port::read_some (2 of 2 overloads)] + +Read some data from the serial port. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + +This function is used to read data from the serial port. The function call will block until one or more bytes of data has been read successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes read. Returns 0 if an error occurred. + +[heading Remarks] + +The read\_some operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.read read] function if you need to ensure that the requested amount of data is read before the blocking operation completes. + + + +[endsect] + + +[endsect] + +[section:send_break basic_serial_port::send_break] + +Send a break sequence to the serial port. + + void ``[link boost_asio.reference.basic_serial_port.send_break.overload1 send_break]``(); + + boost::system::error_code ``[link boost_asio.reference.basic_serial_port.send_break.overload2 send_break]``( + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::send_break (1 of 2 overloads)] + +Send a break sequence to the serial port. + + void send_break(); + + +This function causes a break sequence of platform-specific duration to be sent out the serial port. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 basic_serial_port::send_break (2 of 2 overloads)] + +Send a break sequence to the serial port. + + boost::system::error_code send_break( + boost::system::error_code & ec); + + +This function causes a break sequence of platform-specific duration to be sent out the serial port. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:service basic_serial_port::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + +[section:service_type basic_serial_port::service_type] + + +['Inherited from basic_io_object.] + +The type of the service that will be used to provide I/O operations. + + typedef SerialPortService service_type; + + + + +[endsect] + + +[section:set_option basic_serial_port::set_option] + +Set an option on the serial port. + + template< + typename ``[link boost_asio.reference.SettableSerialPortOption SettableSerialPortOption]``> + void ``[link boost_asio.reference.basic_serial_port.set_option.overload1 set_option]``( + const SettableSerialPortOption & option); + + template< + typename ``[link boost_asio.reference.SettableSerialPortOption SettableSerialPortOption]``> + boost::system::error_code ``[link boost_asio.reference.basic_serial_port.set_option.overload2 set_option]``( + const SettableSerialPortOption & option, + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::set_option (1 of 2 overloads)] + +Set an option on the serial port. + + template< + typename ``[link boost_asio.reference.SettableSerialPortOption SettableSerialPortOption]``> + void set_option( + const SettableSerialPortOption & option); + + +This function is used to set an option on the serial port. + + +[heading Parameters] + + +[variablelist + +[[option][The option value to be set on the serial port.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + + + +[endsect] + + + +[section:overload2 basic_serial_port::set_option (2 of 2 overloads)] + +Set an option on the serial port. + + template< + typename ``[link boost_asio.reference.SettableSerialPortOption SettableSerialPortOption]``> + boost::system::error_code set_option( + const SettableSerialPortOption & option, + boost::system::error_code & ec); + + +This function is used to set an option on the serial port. + + +[heading Parameters] + + +[variablelist + +[[option][The option value to be set on the serial port.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + + + +[endsect] + + +[endsect] + +[section:write_some basic_serial_port::write_some] + +Write some data to the serial port. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_serial_port.write_some.overload1 write_some]``( + const ConstBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.basic_serial_port.write_some.overload2 write_some]``( + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + +[section:overload1 basic_serial_port::write_some (1 of 2 overloads)] + +Write some data to the serial port. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + const ConstBufferSequence & buffers); + + +This function is used to write data to the serial port. The function call will block until one or more bytes of the data has been written successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the serial port.]] + +] + +[heading Return Value] + +The number of bytes written. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. An error code of boost::asio::error::eof indicates that the connection was closed by the peer.]] + +] + +[heading Remarks] + +The write\_some operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.write write] function if you need to ensure that all data is written before the blocking operation completes. + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + serial_port.write_some(boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 basic_serial_port::write_some (2 of 2 overloads)] + +Write some data to the serial port. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + +This function is used to write data to the serial port. The function call will block until one or more bytes of the data has been written successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the serial port.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes written. Returns 0 if an error occurred. + +[heading Remarks] + +The write\_some operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.write write] function if you need to ensure that all data is written before the blocking operation completes. + + + +[endsect] + + +[endsect] + + [endsect] [section:basic_socket basic_socket] @@ -6617,6 +13487,17 @@ Provides socket functionality. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket._basic_socket [*~basic_socket]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -6643,6 +13524,22 @@ Provides socket functionality. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_socket class template provides functionality that is common to both stream-oriented and datagram-oriented sockets. @@ -7818,6 +14715,21 @@ Getting the value of the SOL\_SOCKET/SO\_KEEPALIVE option: [endsect] +[section:implementation basic_socket::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + [section:implementation_type basic_socket::implementation_type] @@ -8460,6 +15372,17 @@ A basic_socket is always the lowest layer. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket._basic_socket [*~basic_socket]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -8486,6 +15409,22 @@ A basic_socket is always the lowest layer. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_socket class template provides functionality that is common to both stream-oriented and datagram-oriented sockets. @@ -9060,6 +15999,21 @@ Getting the current option value: +[endsect] + + + +[section:service basic_socket::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + [endsect] @@ -9333,6 +16287,18 @@ Different ways a socket may be shutdown. +[section:_basic_socket basic_socket::~basic_socket] + +Protected destructor to prevent deletion through this type. + + ~basic_socket(); + + + +[endsect] + + + [endsect] [section:basic_socket_acceptor basic_socket_acceptor] @@ -9605,6 +16571,22 @@ Provides the ability to accept new connections. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket_acceptor.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_socket_acceptor class template is used for accepting new socket connections. @@ -10818,6 +17800,21 @@ Getting the value of the SOL\_SOCKET/SO\_REUSEADDR option: [endsect] +[section:implementation basic_socket_acceptor::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + [section:implementation_type basic_socket_acceptor::implementation_type] @@ -11607,6 +18604,21 @@ Getting the current option value: +[endsect] + + + +[section:service basic_socket_acceptor::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + [endsect] @@ -12192,6 +19204,32 @@ Iostream streambuf for a socket. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket_streambuf.overflow [*overflow]]] + [] + ] + + [ + [[link boost_asio.reference.basic_socket_streambuf.setbuf [*setbuf]]] + [] + ] + + [ + [[link boost_asio.reference.basic_socket_streambuf.sync [*sync]]] + [] + ] + + [ + [[link boost_asio.reference.basic_socket_streambuf.underflow [*underflow]]] + [] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -12218,6 +19256,22 @@ Iostream streambuf for a socket. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket_streambuf.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket_streambuf.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + [section:assign basic_socket_streambuf::assign] Assign an existing native socket to the socket. @@ -13262,6 +20316,21 @@ Getting the value of the SOL\_SOCKET/SO\_KEEPALIVE option: [endsect] +[section:implementation basic_socket_streambuf::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + [section:implementation_type basic_socket_streambuf::implementation_type] @@ -13917,6 +20986,17 @@ A basic_socket is always the lowest layer. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket._basic_socket [*~basic_socket]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -13943,6 +21023,22 @@ A basic_socket is always the lowest layer. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_socket class template provides functionality that is common to both stream-oriented and datagram-oriented sockets. @@ -14208,6 +21304,19 @@ This function opens the socket so that it will use the specified protocol. [endsect] +[section:overflow basic_socket_streambuf::overflow] + + + + int_type overflow( + int_type c); + + + +[endsect] + + + [section:protocol_type basic_socket_streambuf::protocol_type] @@ -14538,6 +21647,21 @@ Getting the current option value: +[endsect] + + + +[section:service basic_socket_streambuf::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + [endsect] @@ -14669,6 +21793,20 @@ Setting the IPPROTO\_TCP/TCP\_NODELAY option: [endsect] + +[section:setbuf basic_socket_streambuf::setbuf] + + + + std::streambuf * setbuf( + char_type * s, + std::streamsize n); + + + +[endsect] + + [section:shutdown basic_socket_streambuf::shutdown] Disable sends or receives on the socket. @@ -14815,6 +21953,30 @@ Different ways a socket may be shutdown. +[section:sync basic_socket_streambuf::sync] + + + + int sync(); + + + +[endsect] + + + +[section:underflow basic_socket_streambuf::underflow] + + + + int_type underflow(); + + + +[endsect] + + + [section:_basic_socket_streambuf basic_socket_streambuf::~basic_socket_streambuf] Destructor flushes buffered data. @@ -15170,6 +22332,22 @@ Provides stream-oriented socket functionality. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_stream_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_stream_socket class template provides asynchronous and blocking stream-oriented socket functionality. @@ -16770,6 +23948,21 @@ Getting the value of the SOL\_SOCKET/SO\_KEEPALIVE option: [endsect] +[section:implementation basic_stream_socket::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + [section:implementation_type basic_stream_socket::implementation_type] @@ -17425,6 +24618,17 @@ A basic_socket is always the lowest layer. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket._basic_socket [*~basic_socket]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -17451,6 +24655,22 @@ A basic_socket is always the lowest layer. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_socket class template provides functionality that is common to both stream-oriented and datagram-oriented sockets. @@ -18522,6 +25742,21 @@ Getting the current option value: +[endsect] + + + +[section:service basic_stream_socket::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + [endsect] @@ -18986,6 +26221,27 @@ Automatically resizable buffer class based on std::streambuf. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_streambuf.overflow [*overflow]]] + [] + ] + + [ + [[link boost_asio.reference.basic_streambuf.reserve [*reserve]]] + [] + ] + + [ + [[link boost_asio.reference.basic_streambuf.underflow [*underflow]]] + [] + ] + +] + [section:basic_streambuf basic_streambuf::basic_streambuf] @@ -19077,6 +26333,19 @@ The type used to represent the put area as a list of buffers. +[section:overflow basic_streambuf::overflow] + + + + int_type overflow( + int_type c); + + + +[endsect] + + + [section:prepare basic_streambuf::prepare] Get a list of buffers that represents the put area, with the given size. @@ -19090,6 +26359,19 @@ Get a list of buffers that represents the put area, with the given size. +[section:reserve basic_streambuf::reserve] + + + + void reserve( + std::size_t n); + + + +[endsect] + + + [section:size basic_streambuf::size] Return the size of the get area in characters. @@ -19102,6 +26384,18 @@ Return the size of the get area in characters. +[section:underflow basic_streambuf::underflow] + + + + int_type underflow(); + + + +[endsect] + + + [endsect] [section:buffer buffer] @@ -21389,6 +28683,108 @@ Write the given data to the stream. Returns the number of bytes written, or 0 if [endsect] +[endsect] + + +[section:buffers_begin buffers_begin] + +Construct an iterator representing the beginning of the buffers' data. + + template< + typename ``[link boost_asio.reference.BufferSequence BufferSequence]``> + buffers_iterator< BufferSequence > buffers_begin( + const BufferSequence & buffers); + + + +[endsect] + + + +[section:buffers_end buffers_end] + +Construct an iterator representing the end of the buffers' data. + + template< + typename ``[link boost_asio.reference.BufferSequence BufferSequence]``> + buffers_iterator< BufferSequence > buffers_end( + const BufferSequence & buffers); + + + +[endsect] + + +[section:buffers_iterator buffers_iterator] + +A random access iterator over the bytes in a buffer sequence. + + template< + typename ``[link boost_asio.reference.BufferSequence BufferSequence]``, + typename ``[link boost_asio.reference.ByteType ByteType]`` = char> + class buffers_iterator + + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.buffers_iterator.begin [*begin]]] + [Construct an iterator representing the beginning of the buffers' data. ] + ] + + [ + [[link boost_asio.reference.buffers_iterator.buffers_iterator [*buffers_iterator]]] + [Default constructor. Creates an iterator in an undefined state. ] + ] + + [ + [[link boost_asio.reference.buffers_iterator.end [*end]]] + [Construct an iterator representing the end of the buffers' data. ] + ] + +] + + +[section:begin buffers_iterator::begin] + +Construct an iterator representing the beginning of the buffers' data. + + static buffers_iterator begin( + const BufferSequence & buffers); + + + +[endsect] + + + +[section:buffers_iterator buffers_iterator::buffers_iterator] + +Default constructor. Creates an iterator in an undefined state. + + buffers_iterator(); + + + +[endsect] + + + +[section:end buffers_iterator::end] + +Construct an iterator representing the end of the buffers' data. + + static buffers_iterator end( + const BufferSequence & buffers); + + + +[endsect] + + + [endsect] [section:const_buffer const_buffer] @@ -21409,18 +28805,23 @@ Holds a buffer that cannot be modified. ] -[heading Friends] +[heading Related Functions] [table [[Name][Description]] [ - [[link boost_asio.reference.const_buffer.buffer_cast_helper [*buffer_cast_helper]]] - [] + [[link boost_asio.reference.const_buffer.buffer_cast [*buffer_cast]]] + [Cast a non-modifiable buffer to a specified pointer to POD type. ] ] [ - [[link boost_asio.reference.const_buffer.buffer_size_helper [*buffer_size_helper]]] - [] + [[link boost_asio.reference.const_buffer.buffer_size [*buffer_size]]] + [Get the number of bytes in a non-modifiable buffer. ] + ] + + [ + [[link boost_asio.reference.const_buffer.operator_plus_ [*operator+]]] + [Create a new non-modifiable buffer that is offset from the start of another. ] ] ] @@ -21428,11 +28829,13 @@ Holds a buffer that cannot be modified. The const_buffer class provides a safe representation of a buffer that cannot be modified. It does not own the underlying data, and so is cheap to copy or assign. -[section:buffer_cast_helper const_buffer::buffer_cast_helper] +[section:buffer_cast const_buffer::buffer_cast] +Cast a non-modifiable buffer to a specified pointer to POD type. - - friend const void * buffer_cast_helper( + template< + typename ``[link boost_asio.reference.PointerToPodType PointerToPodType]``> + PointerToPodType buffer_cast( const const_buffer & b); @@ -21441,11 +28844,11 @@ The const_buffer class provides a safe representation of a buffer that cannot be -[section:buffer_size_helper const_buffer::buffer_size_helper] +[section:buffer_size const_buffer::buffer_size] +Get the number of bytes in a non-modifiable buffer. - - friend std::size_t buffer_size_helper( + std::size_t buffer_size( const const_buffer & b); @@ -21502,6 +28905,48 @@ Construct a non-modifiable buffer from a modifiable one. +[endsect] + + +[endsect] + +[section:operator_plus_ const_buffer::operator+] + +Create a new non-modifiable buffer that is offset from the start of another. + + const_buffer ``[link boost_asio.reference.const_buffer.operator_plus_.overload1 operator+]``( + const const_buffer & b, + std::size_t start); + + const_buffer ``[link boost_asio.reference.const_buffer.operator_plus_.overload2 operator+]``( + std::size_t start, + const const_buffer & b); + + +[section:overload1 const_buffer::operator+ (1 of 2 overloads)] + +Create a new non-modifiable buffer that is offset from the start of another. + + const_buffer operator+( + const const_buffer & b, + std::size_t start); + + + +[endsect] + + + +[section:overload2 const_buffer::operator+ (2 of 2 overloads)] + +Create a new non-modifiable buffer that is offset from the start of another. + + const_buffer operator+( + std::size_t start, + const const_buffer & b); + + + [endsect] @@ -21559,6 +29004,27 @@ Adapts a single non-modifiable buffer so that it meets the requirements of the C ] +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.const_buffers_1.buffer_cast [*buffer_cast]]] + [Cast a non-modifiable buffer to a specified pointer to POD type. ] + ] + + [ + [[link boost_asio.reference.const_buffers_1.buffer_size [*buffer_size]]] + [Get the number of bytes in a non-modifiable buffer. ] + ] + + [ + [[link boost_asio.reference.const_buffers_1.operator_plus_ [*operator+]]] + [Create a new non-modifiable buffer that is offset from the start of another. ] + ] + +] + [section:begin const_buffers_1::begin] @@ -21572,6 +29038,40 @@ Get a random-access iterator to the first element. +[section:buffer_cast const_buffers_1::buffer_cast] + + +['Inherited from const_buffer.] + +Cast a non-modifiable buffer to a specified pointer to POD type. + + template< + typename ``[link boost_asio.reference.PointerToPodType PointerToPodType]``> + PointerToPodType buffer_cast( + const const_buffer & b); + + + +[endsect] + + + +[section:buffer_size const_buffers_1::buffer_size] + + +['Inherited from const_buffer.] + +Get the number of bytes in a non-modifiable buffer. + + std::size_t buffer_size( + const const_buffer & b); + + + +[endsect] + + + [section:const_buffers_1 const_buffers_1::const_buffers_1] Construct to represent a single non-modifiable buffer. @@ -21609,6 +29109,54 @@ Get a random-access iterator for one past the last element. [endsect] +[section:operator_plus_ const_buffers_1::operator+] + +Create a new non-modifiable buffer that is offset from the start of another. + + const_buffer ``[link boost_asio.reference.const_buffers_1.operator_plus_.overload1 operator+]``( + const const_buffer & b, + std::size_t start); + + const_buffer ``[link boost_asio.reference.const_buffers_1.operator_plus_.overload2 operator+]``( + std::size_t start, + const const_buffer & b); + + +[section:overload1 const_buffers_1::operator+ (1 of 2 overloads)] + + +['Inherited from const_buffer.] + +Create a new non-modifiable buffer that is offset from the start of another. + + const_buffer operator+( + const const_buffer & b, + std::size_t start); + + + +[endsect] + + + +[section:overload2 const_buffers_1::operator+ (2 of 2 overloads)] + + +['Inherited from const_buffer.] + +Create a new non-modifiable buffer that is offset from the start of another. + + const_buffer operator+( + std::size_t start, + const const_buffer & b); + + + +[endsect] + + +[endsect] + [section:value_type const_buffers_1::value_type] @@ -21628,18 +29176,23 @@ The type for each element in the list of buffers. ] -[heading Friends] +[heading Related Functions] [table [[Name][Description]] [ - [[link boost_asio.reference.const_buffer.buffer_cast_helper [*buffer_cast_helper]]] - [] + [[link boost_asio.reference.const_buffer.buffer_cast [*buffer_cast]]] + [Cast a non-modifiable buffer to a specified pointer to POD type. ] ] [ - [[link boost_asio.reference.const_buffer.buffer_size_helper [*buffer_size_helper]]] - [] + [[link boost_asio.reference.const_buffer.buffer_size [*buffer_size]]] + [Get the number of bytes in a non-modifiable buffer. ] + ] + + [ + [[link boost_asio.reference.const_buffer.operator_plus_ [*operator+]]] + [Create a new non-modifiable buffer that is offset from the start of another. ] ] ] @@ -22519,6 +30072,22 @@ Typedef for the typical usage of timer. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_deadline_timer.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_deadline_timer.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_deadline_timer class template provides the ability to perform a blocking or asynchronous wait for a timer to expire. Most applications will use the boost::asio::deadline\_timer typedef. @@ -23133,6 +30702,11 @@ The time traits type. [Message too long. ] ] + [ + [name_too_long] + [The name was too long. ] + ] + [ [network_down] [Network is down. ] @@ -23483,11 +31057,6 @@ The time traits type. enum ssl_errors -[heading Values] -[variablelist - -] - [endsect] @@ -24422,6 +31991,22 @@ Base class for all io_service services. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.io_service__service.service [*service]]] + [Constructor. ] + ] + + [ + [[link boost_asio.reference.io_service__service._service [*~service]]] + [Destructor. ] + ] + +] + [section:get_io_service io_service::service::get_io_service] @@ -24447,6 +32032,42 @@ Get the io_service object that owns the service. +[section:service io_service::service::service] + +Constructor. + + service( + boost::asio::io_service & owner); + + + +[heading Parameters] + + +[variablelist + +[[owner][The io\_service object that owns the service. ]] + +] + + + +[endsect] + + + +[section:_service io_service::service::~service] + +Destructor. + + virtual ~service(); + + + +[endsect] + + + [endsect] [section:io_service__strand io_service::strand] @@ -24915,6 +32536,17 @@ Implements version-independent IP addresses. ] +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__address.operator_lt__lt_ [*operator<<]]] + [Output an address as a string. ] + ] + +] + The [link boost_asio.reference.ip__address ip::address] class provides the ability to use either IP version 4 or version 6 addresses. @@ -25117,6 +32749,42 @@ Compare addresses for ordering. +[endsect] + + + +[section:operator_lt__lt_ ip::address::operator<<] + +Output an address as a string. + + template< + typename ``[link boost_asio.reference.Elem Elem]``, + typename ``[link boost_asio.reference.Traits Traits]``> + std::basic_ostream< Elem, Traits > & operator<<( + std::basic_ostream< Elem, Traits > & os, + const address & addr); + + +Used to output a human-readable string for a specified address. + + +[heading Parameters] + + +[variablelist + +[[os][The output stream to which the string will be written.]] + +[[addr][The address to be written.]] + +] + +[heading Return Value] + +The output stream. + + + [endsect] @@ -25383,6 +33051,17 @@ Implements IP version 4 style addresses. ] +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__address_v4.operator_lt__lt_ [*operator<<]]] + [Output an address as a string. ] + ] + +] + The [link boost_asio.reference.ip__address_v4 ip::address_v4] class provides the ability to use and manipulate IP version 4 addresses. @@ -25701,6 +33380,42 @@ Compare addresses for ordering. +[section:operator_lt__lt_ ip::address_v4::operator<<] + +Output an address as a string. + + template< + typename ``[link boost_asio.reference.Elem Elem]``, + typename ``[link boost_asio.reference.Traits Traits]``> + std::basic_ostream< Elem, Traits > & operator<<( + std::basic_ostream< Elem, Traits > & os, + const address_v4 & addr); + + +Used to output a human-readable string for a specified address. + + +[heading Parameters] + + +[variablelist + +[[os][The output stream to which the string will be written.]] + +[[addr][The address to be written.]] + +] + +[heading Return Value] + +The output stream. + + + +[endsect] + + + [section:operator_lt__eq_ ip::address_v4::operator<=] Compare addresses for ordering. @@ -26009,6 +33724,17 @@ Implements IP version 6 style addresses. ] +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__address_v6.operator_lt__lt_ [*operator<<]]] + [Output an address as a string. ] + ] + +] + The [link boost_asio.reference.ip__address_v6 ip::address_v6] class provides the ability to use and manipulate IP version 6 addresses. @@ -26358,6 +34084,42 @@ Compare addresses for ordering. +[section:operator_lt__lt_ ip::address_v6::operator<<] + +Output an address as a string. + + template< + typename ``[link boost_asio.reference.Elem Elem]``, + typename ``[link boost_asio.reference.Traits Traits]``> + std::basic_ostream< Elem, Traits > & operator<<( + std::basic_ostream< Elem, Traits > & os, + const address_v6 & addr); + + +Used to output a human-readable string for a specified address. + + +[heading Parameters] + + +[variablelist + +[[os][The output stream to which the string will be written.]] + +[[addr][The address to be written.]] + +] + +[heading Return Value] + +The output stream. + + + +[endsect] + + + [section:operator_lt__eq_ ip::address_v6::operator<=] Compare addresses for ordering. @@ -26656,6 +34418,17 @@ Describes an endpoint for a version-independent IP socket. ] +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_endpoint.operator_lt__lt_ [*operator<<]]] + [Output an endpoint as a string. ] + ] + +] + The [link boost_asio.reference.ip__basic_endpoint ip::basic_endpoint] class template describes an endpoint that may be associated with a particular socket. @@ -26880,6 +34653,39 @@ Compare endpoints for ordering. +[section:operator_lt__lt_ ip::basic_endpoint::operator<<] + +Output an endpoint as a string. + + std::basic_ostream< Elem, Traits > & operator<<( + std::basic_ostream< Elem, Traits > & os, + const basic_endpoint< InternetProtocol > & endpoint); + + +Used to output a human-readable string for a specified endpoint. + + +[heading Parameters] + + +[variablelist + +[[os][The output stream to which the string will be written.]] + +[[endpoint][The endpoint to be written.]] + +] + +[heading Return Value] + +The output stream. + + + +[endsect] + + + [section:operator_eq_ ip::basic_endpoint::operator=] Assign from another endpoint. @@ -27090,6 +34896,22 @@ Provides endpoint resolution functionality. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_resolver.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_resolver class template provides the ability to resolve a query to a list of endpoints. @@ -27287,6 +35109,21 @@ A reference to the io_service object that the I/O object will use to dispatch ha +[section:implementation ip::basic_resolver::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + [section:implementation_type ip::basic_resolver::implementation_type] @@ -27549,6 +35386,21 @@ A successful call to this function is guaranteed to return at least one entry. [endsect] +[section:service ip::basic_resolver::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + [section:service_type ip::basic_resolver::service_type] @@ -28237,6 +36089,973 @@ Get the current host name. [endsect] +[endsect] + +[section:ip__icmp ip::icmp] + +Encapsulates the flags needed for ICMP. + + class icmp + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.ip__icmp.endpoint [*endpoint]]] + [The type of a ICMP endpoint. ] + + ] + + [ + + [[link boost_asio.reference.ip__icmp.resolver [*resolver]]] + [The ICMP resolver type. ] + + ] + + [ + + [[link boost_asio.reference.ip__icmp.resolver_iterator [*resolver_iterator]]] + [The type of a resolver iterator. ] + + ] + + [ + + [[link boost_asio.reference.ip__icmp.resolver_query [*resolver_query]]] + [The type of a resolver query. ] + + ] + + [ + + [[link boost_asio.reference.ip__icmp.socket [*socket]]] + [The ICMP socket type. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__icmp.family [*family]]] + [Obtain an identifier for the protocol family. ] + ] + + [ + [[link boost_asio.reference.ip__icmp.protocol [*protocol]]] + [Obtain an identifier for the protocol. ] + ] + + [ + [[link boost_asio.reference.ip__icmp.type [*type]]] + [Obtain an identifier for the type of the protocol. ] + ] + + [ + [[link boost_asio.reference.ip__icmp.v4 [*v4]]] + [Construct to represent the IPv4 ICMP protocol. ] + ] + + [ + [[link boost_asio.reference.ip__icmp.v6 [*v6]]] + [Construct to represent the IPv6 ICMP protocol. ] + ] + +] + +[heading Friends] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__icmp.operator_not__eq_ [*operator!=]]] + [Compare two protocols for inequality. ] + ] + + [ + [[link boost_asio.reference.ip__icmp.operator_eq__eq_ [*operator==]]] + [Compare two protocols for equality. ] + ] + +] + +The +[link boost_asio.reference.ip__icmp ip::icmp] class contains flags necessary for ICMP sockets. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Safe. + + + +[section:endpoint ip::icmp::endpoint] + +The type of a ICMP endpoint. + + typedef basic_endpoint< icmp > endpoint; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.ip__basic_endpoint.data_type [*data_type]]] + [The type of the endpoint structure. This type is dependent on the underlying implementation of the socket layer. ] + + ] + + [ + + [[link boost_asio.reference.ip__basic_endpoint.protocol_type [*protocol_type]]] + [The protocol type associated with the endpoint. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_endpoint.address [*address]]] + [Get the IP address associated with the endpoint. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.basic_endpoint [*basic_endpoint]]] + [Default constructor. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.capacity [*capacity]]] + [Get the capacity of the endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.data [*data]]] + [Get the underlying endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.operator_eq_ [*operator=]]] + [Assign from another endpoint. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.port [*port]]] + [Get the port associated with the endpoint. The port number is always in the host's byte order. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.protocol [*protocol]]] + [The protocol associated with the endpoint. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.resize [*resize]]] + [Set the underlying size of the endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.size [*size]]] + [Get the underlying size of the endpoint in the native type. ] + ] + +] + +[heading Friends] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_endpoint.operator_not__eq_ [*operator!=]]] + [Compare two endpoints for inequality. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.operator_lt_ [*operator<]]] + [Compare endpoints for ordering. ] + ] + + [ + [[link boost_asio.reference.ip__basic_endpoint.operator_eq__eq_ [*operator==]]] + [Compare two endpoints for equality. ] + ] + +] + +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_endpoint.operator_lt__lt_ [*operator<<]]] + [Output an endpoint as a string. ] + ] + +] + +The +[link boost_asio.reference.ip__basic_endpoint ip::basic_endpoint] class template describes an endpoint that may be associated with a particular socket. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:family ip::icmp::family] + +Obtain an identifier for the protocol family. + + int family() const; + + + +[endsect] + + + +[section:operator_not__eq_ ip::icmp::operator!=] + +Compare two protocols for inequality. + + friend bool operator!=( + const icmp & p1, + const icmp & p2); + + + +[endsect] + + + +[section:operator_eq__eq_ ip::icmp::operator==] + +Compare two protocols for equality. + + friend bool operator==( + const icmp & p1, + const icmp & p2); + + + +[endsect] + + + +[section:protocol ip::icmp::protocol] + +Obtain an identifier for the protocol. + + int protocol() const; + + + +[endsect] + + + +[section:resolver ip::icmp::resolver] + +The ICMP resolver type. + + typedef basic_resolver< icmp > resolver; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.ip__basic_resolver.endpoint_type [*endpoint_type]]] + [The endpoint type. ] + + ] + + [ + + [[link boost_asio.reference.ip__basic_resolver.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.ip__basic_resolver.iterator [*iterator]]] + [The iterator type. ] + + ] + + [ + + [[link boost_asio.reference.ip__basic_resolver.protocol_type [*protocol_type]]] + [The protocol type. ] + + ] + + [ + + [[link boost_asio.reference.ip__basic_resolver.query [*query]]] + [The query type. ] + + ] + + [ + + [[link boost_asio.reference.ip__basic_resolver.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_resolver.async_resolve [*async_resolve]]] + [Asynchronously resolve a query to a list of entries. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.basic_resolver [*basic_resolver]]] + [Constructor. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.cancel [*cancel]]] + [Cancel any asynchronous operations that are waiting on the resolver. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.resolve [*resolve]]] + [Resolve a query to a list of entries. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_resolver.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_resolver class template provides the ability to resolve a query to a list of endpoints. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:resolver_iterator ip::icmp::resolver_iterator] + +The type of a resolver iterator. + + typedef basic_resolver_iterator< icmp > resolver_iterator; + + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_resolver_iterator.basic_resolver_iterator [*basic_resolver_iterator]]] + [Default constructor creates an end iterator. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_iterator.create [*create]]] + [Create an iterator from an addrinfo list returned by getaddrinfo. ] + ] + +] + +The +[link boost_asio.reference.ip__basic_resolver_iterator ip::basic_resolver_iterator] class template is used to define iterators over the results returned by a resolver. + +The iterator's value\_type, obtained when the iterator is dereferenced, is: + + const basic_resolver_entry + + + + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:resolver_query ip::icmp::resolver_query] + +The type of a resolver query. + + typedef basic_resolver_query< icmp > resolver_query; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.ip__basic_resolver_query.protocol_type [*protocol_type]]] + [The protocol type associated with the endpoint query. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.basic_resolver_query [*basic_resolver_query]]] + [Construct with specified service name for any protocol. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.hints [*hints]]] + [Get the hints associated with the query. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.host_name [*host_name]]] + [Get the host name associated with the query. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.service_name [*service_name]]] + [Get the service name associated with the query. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.address_configured [*address_configured]]] + [Only return IPv4 addresses if a non-loopback IPv4 address is configured for the system. Only return IPv6 addresses if a non-loopback IPv6 address is configured for the system. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.all_matching [*all_matching]]] + [If used with v4_mapped, return all matching IPv6 and IPv4 addresses. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.canonical_name [*canonical_name]]] + [Determine the canonical name of the host specified in the query. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.numeric_host [*numeric_host]]] + [Host name should be treated as a numeric string defining an IPv4 or IPv6 address and no name resolution should be attempted. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.numeric_service [*numeric_service]]] + [Service name should be treated as a numeric string defining a port number and no name resolution should be attempted. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.passive [*passive]]] + [Indicate that returned endpoint is intended for use as a locally bound socket endpoint. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver_query.v4_mapped [*v4_mapped]]] + [If the query protocol family is specified as IPv6, return IPv4-mapped IPv6 addresses on finding no IPv6 addresses. ] + ] + +] + +The +[link boost_asio.reference.ip__basic_resolver_query ip::basic_resolver_query] class template describes a query that can be passed to a resolver. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:socket ip::icmp::socket] + +The ICMP socket type. + + typedef basic_raw_socket< icmp > socket; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_raw_socket.broadcast [*broadcast]]] + [Socket option to permit sending of broadcast messages. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.debug [*debug]]] + [Socket option to enable socket-level debugging. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.do_not_route [*do_not_route]]] + [Socket option to prevent routing, use local interfaces only. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.enable_connection_aborted [*enable_connection_aborted]]] + [Socket option to report aborted connections on accept. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.endpoint_type [*endpoint_type]]] + [The endpoint type. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.keep_alive [*keep_alive]]] + [Socket option to send keep-alives. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.linger [*linger]]] + [Socket option to specify whether the socket lingers on close if unsent data is present. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.lowest_layer_type [*lowest_layer_type]]] + [A basic_socket is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.message_flags [*message_flags]]] + [Bitmask type for flags that can be passed to send and receive operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.native_type [*native_type]]] + [The native representation of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.protocol_type [*protocol_type]]] + [The protocol type. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.receive_buffer_size [*receive_buffer_size]]] + [Socket option for the receive buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.receive_low_watermark [*receive_low_watermark]]] + [Socket option for the receive low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.reuse_address [*reuse_address]]] + [Socket option to allow the socket to be bound to an address that is already in use. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.send_buffer_size [*send_buffer_size]]] + [Socket option for the send buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.send_low_watermark [*send_low_watermark]]] + [Socket option for the send low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_raw_socket.shutdown_type [*shutdown_type]]] + [Different ways a socket may be shutdown. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_raw_socket.assign [*assign]]] + [Assign an existing native socket to the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_connect [*async_connect]]] + [Start an asynchronous connect. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_receive [*async_receive]]] + [Start an asynchronous receive on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_receive_from [*async_receive_from]]] + [Start an asynchronous receive. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_send [*async_send]]] + [Start an asynchronous send on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.async_send_to [*async_send_to]]] + [Start an asynchronous send. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.at_mark [*at_mark]]] + [Determine whether the socket is at the out-of-band data mark. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.available [*available]]] + [Determine the number of bytes available for reading. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.basic_raw_socket [*basic_raw_socket]]] + [Construct a basic_raw_socket without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.bind [*bind]]] + [Bind the socket to the given local endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.close [*close]]] + [Close the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.connect [*connect]]] + [Connect the socket to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.get_option [*get_option]]] + [Get an option from the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.io_control [*io_control]]] + [Perform an IO control command on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.is_open [*is_open]]] + [Determine whether the socket is open. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.local_endpoint [*local_endpoint]]] + [Get the local endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.native [*native]]] + [Get the native socket representation. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.open [*open]]] + [Open the socket using the specified protocol. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.receive [*receive]]] + [Receive some data on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.receive_from [*receive_from]]] + [Receive raw data with the endpoint of the sender. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.remote_endpoint [*remote_endpoint]]] + [Get the remote endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.send [*send]]] + [Send some data on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.send_to [*send_to]]] + [Send raw data to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.set_option [*set_option]]] + [Set an option on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.shutdown [*shutdown]]] + [Disable sends or receives on the socket. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_raw_socket.max_connections [*max_connections]]] + [The maximum length of the queue of pending incoming connections. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.message_do_not_route [*message_do_not_route]]] + [Specify that the data should not be subject to routing. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.message_out_of_band [*message_out_of_band]]] + [Process out-of-band data. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.message_peek [*message_peek]]] + [Peek at incoming data without removing it from the input queue. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_raw_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_raw_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_raw_socket class template provides asynchronous and blocking raw-oriented socket functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:type ip::icmp::type] + +Obtain an identifier for the type of the protocol. + + int type() const; + + + +[endsect] + + + +[section:v4 ip::icmp::v4] + +Construct to represent the IPv4 ICMP protocol. + + static icmp v4(); + + + +[endsect] + + + +[section:v6 ip::icmp::v6] + +Construct to represent the IPv6 ICMP protocol. + + static icmp v6(); + + + +[endsect] + + + [endsect] @@ -28419,6 +37238,17 @@ The resolver_query_base class is used as a base for the basic_resolver_query cla class resolver_query_base +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__resolver_query_base._resolver_query_base [*~resolver_query_base]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -28545,6 +37375,18 @@ If the query protocol family is specified as IPv6, return IPv4-mapped IPv6 addre +[section:_resolver_query_base ip::resolver_query_base::~resolver_query_base] + +Protected destructor to prevent deletion through this type. + + ~resolver_query_base(); + + + +[endsect] + + + [endsect] [section:ip__resolver_service ip::resolver_service] @@ -29327,6 +38169,22 @@ The TCP acceptor type. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket_acceptor.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_socket_acceptor class template is used for accepting new socket connections. @@ -29456,6 +38314,17 @@ The type of a TCP endpoint. ] +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_endpoint.operator_lt__lt_ [*operator<<]]] + [Output an endpoint as a string. ] + ] + +] + The [link boost_asio.reference.ip__basic_endpoint ip::basic_endpoint] class template describes an endpoint that may be associated with a particular socket. @@ -29695,6 +38564,22 @@ The TCP resolver type. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_resolver.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_resolver class template provides the ability to resolve a query to a list of endpoints. @@ -30199,6 +39084,22 @@ The TCP socket type. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_stream_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_stream_socket class template provides asynchronous and blocking stream-oriented socket functionality. @@ -30459,6 +39360,17 @@ The type of a UDP endpoint. ] +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_endpoint.operator_lt__lt_ [*operator<<]]] + [Output an endpoint as a string. ] + ] + +] + The [link boost_asio.reference.ip__basic_endpoint ip::basic_endpoint] class template describes an endpoint that may be associated with a particular socket. @@ -30619,6 +39531,22 @@ The UDP resolver type. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ip__basic_resolver.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.ip__basic_resolver.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_resolver class template provides the ability to resolve a query to a list of endpoints. @@ -31123,6 +40051,22 @@ The UDP socket type. ] +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_datagram_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + The basic_datagram_socket class template provides asynchronous and blocking datagram-oriented socket functionality. @@ -31257,6 +40201,41 @@ Getting the current option value: [endsect] +[section:is_match_condition is_match_condition] + +Type trait used to determine whether a type can be used as a match condition function with read_until and async_read_until. + + template< + typename T> + struct is_match_condition + + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.is_match_condition.value [*value]]] + [The value member is true if the type may be used as a match condition. ] + ] + +] + + +[section:value is_match_condition::value] + +The value member is true if the type may be used as a match condition. + + static const bool value; + + + +[endsect] + + + +[endsect] + [section:is_read_buffered is_read_buffered] The is_read_buffered class is a traits class that may be used to determine whether a stream type supports buffering of read data. @@ -31325,6 +40304,2046 @@ The value member is true only if the Stream type supports buffering of written d +[endsect] + +[section:local__basic_endpoint local::basic_endpoint] + +Describes an endpoint for a UNIX socket. + + template< + typename ``[link boost_asio.reference.Protocol Protocol]``> + class basic_endpoint + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.local__basic_endpoint.data_type [*data_type]]] + [The type of the endpoint structure. This type is dependent on the underlying implementation of the socket layer. ] + + ] + + [ + + [[link boost_asio.reference.local__basic_endpoint.protocol_type [*protocol_type]]] + [The protocol type associated with the endpoint. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.basic_endpoint [*basic_endpoint]]] + [Default constructor. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.capacity [*capacity]]] + [Get the capacity of the endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.data [*data]]] + [Get the underlying endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_eq_ [*operator=]]] + [Assign from another endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.path [*path]]] + [Get the path associated with the endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.protocol [*protocol]]] + [The protocol associated with the endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.resize [*resize]]] + [Set the underlying size of the endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.size [*size]]] + [Get the underlying size of the endpoint in the native type. ] + ] + +] + +[heading Friends] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_not__eq_ [*operator!=]]] + [Compare two endpoints for inequality. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_lt_ [*operator<]]] + [Compare endpoints for ordering. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_eq__eq_ [*operator==]]] + [Compare two endpoints for equality. ] + ] + +] + +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_lt__lt_ [*operator<<]]] + [Output an endpoint as a string. ] + ] + +] + +The +[link boost_asio.reference.local__basic_endpoint local::basic_endpoint] class template describes an endpoint that may be associated with a particular UNIX socket. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + +[section:basic_endpoint local::basic_endpoint::basic_endpoint] + +Default constructor. + + ``[link boost_asio.reference.local__basic_endpoint.basic_endpoint.overload1 basic_endpoint]``(); + + ``[link boost_asio.reference.local__basic_endpoint.basic_endpoint.overload2 basic_endpoint]``( + const char * path); + + ``[link boost_asio.reference.local__basic_endpoint.basic_endpoint.overload3 basic_endpoint]``( + const std::string & path); + + ``[link boost_asio.reference.local__basic_endpoint.basic_endpoint.overload4 basic_endpoint]``( + const basic_endpoint & other); + + +[section:overload1 local::basic_endpoint::basic_endpoint (1 of 4 overloads)] + +Default constructor. + + basic_endpoint(); + + + +[endsect] + + + +[section:overload2 local::basic_endpoint::basic_endpoint (2 of 4 overloads)] + +Construct an endpoint using the specified path name. + + basic_endpoint( + const char * path); + + + +[endsect] + + + +[section:overload3 local::basic_endpoint::basic_endpoint (3 of 4 overloads)] + +Construct an endpoint using the specified path name. + + basic_endpoint( + const std::string & path); + + + +[endsect] + + + +[section:overload4 local::basic_endpoint::basic_endpoint (4 of 4 overloads)] + +Copy constructor. + + basic_endpoint( + const basic_endpoint & other); + + + +[endsect] + + +[endsect] + + +[section:capacity local::basic_endpoint::capacity] + +Get the capacity of the endpoint in the native type. + + std::size_t capacity() const; + + + +[endsect] + + +[section:data local::basic_endpoint::data] + +Get the underlying endpoint in the native type. + + data_type * ``[link boost_asio.reference.local__basic_endpoint.data.overload1 data]``(); + + const data_type * ``[link boost_asio.reference.local__basic_endpoint.data.overload2 data]``() const; + + +[section:overload1 local::basic_endpoint::data (1 of 2 overloads)] + +Get the underlying endpoint in the native type. + + data_type * data(); + + + +[endsect] + + + +[section:overload2 local::basic_endpoint::data (2 of 2 overloads)] + +Get the underlying endpoint in the native type. + + const data_type * data() const; + + + +[endsect] + + +[endsect] + + +[section:data_type local::basic_endpoint::data_type] + +The type of the endpoint structure. This type is dependent on the underlying implementation of the socket layer. + + typedef implementation_defined data_type; + + + + +[endsect] + + + +[section:operator_not__eq_ local::basic_endpoint::operator!=] + +Compare two endpoints for inequality. + + friend bool operator!=( + const basic_endpoint< Protocol > & e1, + const basic_endpoint< Protocol > & e2); + + + +[endsect] + + + +[section:operator_lt_ local::basic_endpoint::operator<] + +Compare endpoints for ordering. + + friend bool operator<( + const basic_endpoint< Protocol > & e1, + const basic_endpoint< Protocol > & e2); + + + +[endsect] + + + +[section:operator_lt__lt_ local::basic_endpoint::operator<<] + +Output an endpoint as a string. + + std::basic_ostream< Elem, Traits > & operator<<( + std::basic_ostream< Elem, Traits > & os, + const basic_endpoint< Protocol > & endpoint); + + +Used to output a human-readable string for a specified endpoint. + + +[heading Parameters] + + +[variablelist + +[[os][The output stream to which the string will be written.]] + +[[endpoint][The endpoint to be written.]] + +] + +[heading Return Value] + +The output stream. + + + +[endsect] + + + +[section:operator_eq_ local::basic_endpoint::operator=] + +Assign from another endpoint. + + basic_endpoint & operator=( + const basic_endpoint & other); + + + +[endsect] + + + +[section:operator_eq__eq_ local::basic_endpoint::operator==] + +Compare two endpoints for equality. + + friend bool operator==( + const basic_endpoint< Protocol > & e1, + const basic_endpoint< Protocol > & e2); + + + +[endsect] + + +[section:path local::basic_endpoint::path] + +Get the path associated with the endpoint. + + std::string ``[link boost_asio.reference.local__basic_endpoint.path.overload1 path]``() const; + + void ``[link boost_asio.reference.local__basic_endpoint.path.overload2 path]``( + const char * p); + + void ``[link boost_asio.reference.local__basic_endpoint.path.overload3 path]``( + const std::string & p); + + +[section:overload1 local::basic_endpoint::path (1 of 3 overloads)] + +Get the path associated with the endpoint. + + std::string path() const; + + + +[endsect] + + + +[section:overload2 local::basic_endpoint::path (2 of 3 overloads)] + +Set the path associated with the endpoint. + + void path( + const char * p); + + + +[endsect] + + + +[section:overload3 local::basic_endpoint::path (3 of 3 overloads)] + +Set the path associated with the endpoint. + + void path( + const std::string & p); + + + +[endsect] + + +[endsect] + + +[section:protocol local::basic_endpoint::protocol] + +The protocol associated with the endpoint. + + protocol_type protocol() const; + + + +[endsect] + + + +[section:protocol_type local::basic_endpoint::protocol_type] + +The protocol type associated with the endpoint. + + typedef Protocol protocol_type; + + + + +[endsect] + + + +[section:resize local::basic_endpoint::resize] + +Set the underlying size of the endpoint in the native type. + + void resize( + std::size_t size); + + + +[endsect] + + + +[section:size local::basic_endpoint::size] + +Get the underlying size of the endpoint in the native type. + + std::size_t size() const; + + + +[endsect] + + + +[endsect] + +[section:local__connect_pair local::connect_pair] + +Create a pair of connected sockets. + + template< + typename ``[link boost_asio.reference.Protocol Protocol]``, + typename ``[link boost_asio.reference.SocketService1 SocketService1]``, + typename ``[link boost_asio.reference.SocketService2 SocketService2]``> + void ``[link boost_asio.reference.local__connect_pair.overload1 connect_pair]``( + basic_socket< Protocol, SocketService1 > & socket1, + basic_socket< Protocol, SocketService2 > & socket2); + + template< + typename ``[link boost_asio.reference.Protocol Protocol]``, + typename ``[link boost_asio.reference.SocketService1 SocketService1]``, + typename ``[link boost_asio.reference.SocketService2 SocketService2]``> + boost::system::error_code ``[link boost_asio.reference.local__connect_pair.overload2 connect_pair]``( + basic_socket< Protocol, SocketService1 > & socket1, + basic_socket< Protocol, SocketService2 > & socket2, + boost::system::error_code & ec); + + +[section:overload1 local::connect_pair (1 of 2 overloads)] + +Create a pair of connected sockets. + + template< + typename ``[link boost_asio.reference.Protocol Protocol]``, + typename ``[link boost_asio.reference.SocketService1 SocketService1]``, + typename ``[link boost_asio.reference.SocketService2 SocketService2]``> + void connect_pair( + basic_socket< Protocol, SocketService1 > & socket1, + basic_socket< Protocol, SocketService2 > & socket2); + + + +[endsect] + + + +[section:overload2 local::connect_pair (2 of 2 overloads)] + +Create a pair of connected sockets. + + template< + typename ``[link boost_asio.reference.Protocol Protocol]``, + typename ``[link boost_asio.reference.SocketService1 SocketService1]``, + typename ``[link boost_asio.reference.SocketService2 SocketService2]``> + boost::system::error_code connect_pair( + basic_socket< Protocol, SocketService1 > & socket1, + basic_socket< Protocol, SocketService2 > & socket2, + boost::system::error_code & ec); + + + +[endsect] + + +[endsect] + +[section:local__datagram_protocol local::datagram_protocol] + +Encapsulates the flags needed for datagram-oriented UNIX sockets. + + class datagram_protocol + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.local__datagram_protocol.endpoint [*endpoint]]] + [The type of a UNIX domain endpoint. ] + + ] + + [ + + [[link boost_asio.reference.local__datagram_protocol.socket [*socket]]] + [The UNIX domain socket type. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__datagram_protocol.family [*family]]] + [Obtain an identifier for the protocol family. ] + ] + + [ + [[link boost_asio.reference.local__datagram_protocol.protocol [*protocol]]] + [Obtain an identifier for the protocol. ] + ] + + [ + [[link boost_asio.reference.local__datagram_protocol.type [*type]]] + [Obtain an identifier for the type of the protocol. ] + ] + +] + +The +[link boost_asio.reference.local__datagram_protocol local::datagram_protocol] class contains flags necessary for datagram-oriented UNIX domain sockets. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Safe. + + + +[section:endpoint local::datagram_protocol::endpoint] + +The type of a UNIX domain endpoint. + + typedef basic_endpoint< datagram_protocol > endpoint; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.local__basic_endpoint.data_type [*data_type]]] + [The type of the endpoint structure. This type is dependent on the underlying implementation of the socket layer. ] + + ] + + [ + + [[link boost_asio.reference.local__basic_endpoint.protocol_type [*protocol_type]]] + [The protocol type associated with the endpoint. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.basic_endpoint [*basic_endpoint]]] + [Default constructor. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.capacity [*capacity]]] + [Get the capacity of the endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.data [*data]]] + [Get the underlying endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_eq_ [*operator=]]] + [Assign from another endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.path [*path]]] + [Get the path associated with the endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.protocol [*protocol]]] + [The protocol associated with the endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.resize [*resize]]] + [Set the underlying size of the endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.size [*size]]] + [Get the underlying size of the endpoint in the native type. ] + ] + +] + +[heading Friends] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_not__eq_ [*operator!=]]] + [Compare two endpoints for inequality. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_lt_ [*operator<]]] + [Compare endpoints for ordering. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_eq__eq_ [*operator==]]] + [Compare two endpoints for equality. ] + ] + +] + +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_lt__lt_ [*operator<<]]] + [Output an endpoint as a string. ] + ] + +] + +The +[link boost_asio.reference.local__basic_endpoint local::basic_endpoint] class template describes an endpoint that may be associated with a particular UNIX socket. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:family local::datagram_protocol::family] + +Obtain an identifier for the protocol family. + + int family() const; + + + +[endsect] + + + +[section:protocol local::datagram_protocol::protocol] + +Obtain an identifier for the protocol. + + int protocol() const; + + + +[endsect] + + + +[section:socket local::datagram_protocol::socket] + +The UNIX domain socket type. + + typedef basic_datagram_socket< datagram_protocol > socket; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_datagram_socket.broadcast [*broadcast]]] + [Socket option to permit sending of broadcast messages. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.debug [*debug]]] + [Socket option to enable socket-level debugging. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.do_not_route [*do_not_route]]] + [Socket option to prevent routing, use local interfaces only. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.enable_connection_aborted [*enable_connection_aborted]]] + [Socket option to report aborted connections on accept. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.endpoint_type [*endpoint_type]]] + [The endpoint type. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.keep_alive [*keep_alive]]] + [Socket option to send keep-alives. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.linger [*linger]]] + [Socket option to specify whether the socket lingers on close if unsent data is present. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.lowest_layer_type [*lowest_layer_type]]] + [A basic_socket is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.message_flags [*message_flags]]] + [Bitmask type for flags that can be passed to send and receive operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.native_type [*native_type]]] + [The native representation of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.protocol_type [*protocol_type]]] + [The protocol type. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.receive_buffer_size [*receive_buffer_size]]] + [Socket option for the receive buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.receive_low_watermark [*receive_low_watermark]]] + [Socket option for the receive low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.reuse_address [*reuse_address]]] + [Socket option to allow the socket to be bound to an address that is already in use. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.send_buffer_size [*send_buffer_size]]] + [Socket option for the send buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.send_low_watermark [*send_low_watermark]]] + [Socket option for the send low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_datagram_socket.shutdown_type [*shutdown_type]]] + [Different ways a socket may be shutdown. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_datagram_socket.assign [*assign]]] + [Assign an existing native socket to the socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.async_connect [*async_connect]]] + [Start an asynchronous connect. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.async_receive [*async_receive]]] + [Start an asynchronous receive on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.async_receive_from [*async_receive_from]]] + [Start an asynchronous receive. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.async_send [*async_send]]] + [Start an asynchronous send on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.async_send_to [*async_send_to]]] + [Start an asynchronous send. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.at_mark [*at_mark]]] + [Determine whether the socket is at the out-of-band data mark. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.available [*available]]] + [Determine the number of bytes available for reading. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.basic_datagram_socket [*basic_datagram_socket]]] + [Construct a basic_datagram_socket without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.bind [*bind]]] + [Bind the socket to the given local endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.close [*close]]] + [Close the socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.connect [*connect]]] + [Connect the socket to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.get_option [*get_option]]] + [Get an option from the socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.io_control [*io_control]]] + [Perform an IO control command on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.is_open [*is_open]]] + [Determine whether the socket is open. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.local_endpoint [*local_endpoint]]] + [Get the local endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.native [*native]]] + [Get the native socket representation. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.open [*open]]] + [Open the socket using the specified protocol. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.receive [*receive]]] + [Receive some data on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.receive_from [*receive_from]]] + [Receive a datagram with the endpoint of the sender. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.remote_endpoint [*remote_endpoint]]] + [Get the remote endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.send [*send]]] + [Send some data on a connected socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.send_to [*send_to]]] + [Send a datagram to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.set_option [*set_option]]] + [Set an option on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.shutdown [*shutdown]]] + [Disable sends or receives on the socket. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_datagram_socket.max_connections [*max_connections]]] + [The maximum length of the queue of pending incoming connections. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.message_do_not_route [*message_do_not_route]]] + [Specify that the data should not be subject to routing. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.message_out_of_band [*message_out_of_band]]] + [Process out-of-band data. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.message_peek [*message_peek]]] + [Peek at incoming data without removing it from the input queue. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_datagram_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_datagram_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_datagram_socket class template provides asynchronous and blocking datagram-oriented socket functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:type local::datagram_protocol::type] + +Obtain an identifier for the type of the protocol. + + int type() const; + + + +[endsect] + + + +[endsect] + +[section:local__stream_protocol local::stream_protocol] + +Encapsulates the flags needed for stream-oriented UNIX sockets. + + class stream_protocol + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.local__stream_protocol.acceptor [*acceptor]]] + [The UNIX domain acceptor type. ] + + ] + + [ + + [[link boost_asio.reference.local__stream_protocol.endpoint [*endpoint]]] + [The type of a UNIX domain endpoint. ] + + ] + + [ + + [[link boost_asio.reference.local__stream_protocol.iostream [*iostream]]] + [The UNIX domain iostream type. ] + + ] + + [ + + [[link boost_asio.reference.local__stream_protocol.socket [*socket]]] + [The UNIX domain socket type. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__stream_protocol.family [*family]]] + [Obtain an identifier for the protocol family. ] + ] + + [ + [[link boost_asio.reference.local__stream_protocol.protocol [*protocol]]] + [Obtain an identifier for the protocol. ] + ] + + [ + [[link boost_asio.reference.local__stream_protocol.type [*type]]] + [Obtain an identifier for the type of the protocol. ] + ] + +] + +The +[link boost_asio.reference.local__stream_protocol local::stream_protocol] class contains flags necessary for stream-oriented UNIX domain sockets. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Safe. + + + +[section:acceptor local::stream_protocol::acceptor] + +The UNIX domain acceptor type. + + typedef basic_socket_acceptor< stream_protocol > acceptor; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.broadcast [*broadcast]]] + [Socket option to permit sending of broadcast messages. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.debug [*debug]]] + [Socket option to enable socket-level debugging. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.do_not_route [*do_not_route]]] + [Socket option to prevent routing, use local interfaces only. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.enable_connection_aborted [*enable_connection_aborted]]] + [Socket option to report aborted connections on accept. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.endpoint_type [*endpoint_type]]] + [The endpoint type. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.keep_alive [*keep_alive]]] + [Socket option to send keep-alives. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.linger [*linger]]] + [Socket option to specify whether the socket lingers on close if unsent data is present. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.message_flags [*message_flags]]] + [Bitmask type for flags that can be passed to send and receive operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.native_type [*native_type]]] + [The native representation of an acceptor. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.protocol_type [*protocol_type]]] + [The protocol type. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.receive_buffer_size [*receive_buffer_size]]] + [Socket option for the receive buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.receive_low_watermark [*receive_low_watermark]]] + [Socket option for the receive low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.reuse_address [*reuse_address]]] + [Socket option to allow the socket to be bound to an address that is already in use. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.send_buffer_size [*send_buffer_size]]] + [Socket option for the send buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.send_low_watermark [*send_low_watermark]]] + [Socket option for the send low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_socket_acceptor.shutdown_type [*shutdown_type]]] + [Different ways a socket may be shutdown. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket_acceptor.accept [*accept]]] + [Accept a new connection. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.assign [*assign]]] + [Assigns an existing native acceptor to the acceptor. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.async_accept [*async_accept]]] + [Start an asynchronous accept. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.basic_socket_acceptor [*basic_socket_acceptor]]] + [Construct an acceptor without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.bind [*bind]]] + [Bind the acceptor to the given local endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the acceptor. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.close [*close]]] + [Close the acceptor. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.get_option [*get_option]]] + [Get an option from the acceptor. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.is_open [*is_open]]] + [Determine whether the acceptor is open. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.listen [*listen]]] + [Place the acceptor into the state where it will listen for new connections. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.local_endpoint [*local_endpoint]]] + [Get the local endpoint of the acceptor. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.native [*native]]] + [Get the native acceptor representation. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.open [*open]]] + [Open the acceptor using the specified protocol. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.set_option [*set_option]]] + [Set an option on the acceptor. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket_acceptor.max_connections [*max_connections]]] + [The maximum length of the queue of pending incoming connections. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.message_do_not_route [*message_do_not_route]]] + [Specify that the data should not be subject to routing. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.message_out_of_band [*message_out_of_band]]] + [Process out-of-band data. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.message_peek [*message_peek]]] + [Peek at incoming data without removing it from the input queue. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket_acceptor.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_socket_acceptor.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_socket_acceptor class template is used for accepting new socket connections. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + +[heading Example] + +Opening a socket acceptor with the SO\_REUSEADDR option enabled: + + boost::asio::ip::tcp::acceptor acceptor(io_service); + boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); + acceptor.open(endpoint.protocol()); + acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor.bind(endpoint); + acceptor.listen(); + + + + + + + +[endsect] + + + +[section:endpoint local::stream_protocol::endpoint] + +The type of a UNIX domain endpoint. + + typedef basic_endpoint< stream_protocol > endpoint; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.local__basic_endpoint.data_type [*data_type]]] + [The type of the endpoint structure. This type is dependent on the underlying implementation of the socket layer. ] + + ] + + [ + + [[link boost_asio.reference.local__basic_endpoint.protocol_type [*protocol_type]]] + [The protocol type associated with the endpoint. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.basic_endpoint [*basic_endpoint]]] + [Default constructor. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.capacity [*capacity]]] + [Get the capacity of the endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.data [*data]]] + [Get the underlying endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_eq_ [*operator=]]] + [Assign from another endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.path [*path]]] + [Get the path associated with the endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.protocol [*protocol]]] + [The protocol associated with the endpoint. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.resize [*resize]]] + [Set the underlying size of the endpoint in the native type. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.size [*size]]] + [Get the underlying size of the endpoint in the native type. ] + ] + +] + +[heading Friends] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_not__eq_ [*operator!=]]] + [Compare two endpoints for inequality. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_lt_ [*operator<]]] + [Compare endpoints for ordering. ] + ] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_eq__eq_ [*operator==]]] + [Compare two endpoints for equality. ] + ] + +] + +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.local__basic_endpoint.operator_lt__lt_ [*operator<<]]] + [Output an endpoint as a string. ] + ] + +] + +The +[link boost_asio.reference.local__basic_endpoint local::basic_endpoint] class template describes an endpoint that may be associated with a particular UNIX socket. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:family local::stream_protocol::family] + +Obtain an identifier for the protocol family. + + int family() const; + + + +[endsect] + + + +[section:iostream local::stream_protocol::iostream] + +The UNIX domain iostream type. + + typedef basic_socket_iostream< stream_protocol > iostream; + + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_socket_iostream.basic_socket_iostream [*basic_socket_iostream]]] + [Construct a basic_socket_iostream without establishing a connection. ] + ] + + [ + [[link boost_asio.reference.basic_socket_iostream.close [*close]]] + [Close the connection. ] + ] + + [ + [[link boost_asio.reference.basic_socket_iostream.connect [*connect]]] + [Establish a connection to an endpoint corresponding to a resolver query. ] + ] + + [ + [[link boost_asio.reference.basic_socket_iostream.rdbuf [*rdbuf]]] + [Return a pointer to the underlying streambuf. ] + ] + +] + + + +[endsect] + + + +[section:protocol local::stream_protocol::protocol] + +Obtain an identifier for the protocol. + + int protocol() const; + + + +[endsect] + + + +[section:socket local::stream_protocol::socket] + +The UNIX domain socket type. + + typedef basic_stream_socket< stream_protocol > socket; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_stream_socket.broadcast [*broadcast]]] + [Socket option to permit sending of broadcast messages. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.debug [*debug]]] + [Socket option to enable socket-level debugging. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.do_not_route [*do_not_route]]] + [Socket option to prevent routing, use local interfaces only. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.enable_connection_aborted [*enable_connection_aborted]]] + [Socket option to report aborted connections on accept. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.endpoint_type [*endpoint_type]]] + [The endpoint type. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.keep_alive [*keep_alive]]] + [Socket option to send keep-alives. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.linger [*linger]]] + [Socket option to specify whether the socket lingers on close if unsent data is present. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.lowest_layer_type [*lowest_layer_type]]] + [A basic_socket is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.message_flags [*message_flags]]] + [Bitmask type for flags that can be passed to send and receive operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.native_type [*native_type]]] + [The native representation of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.protocol_type [*protocol_type]]] + [The protocol type. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.receive_buffer_size [*receive_buffer_size]]] + [Socket option for the receive buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.receive_low_watermark [*receive_low_watermark]]] + [Socket option for the receive low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.reuse_address [*reuse_address]]] + [Socket option to allow the socket to be bound to an address that is already in use. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.send_buffer_size [*send_buffer_size]]] + [Socket option for the send buffer size of a socket. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.send_low_watermark [*send_low_watermark]]] + [Socket option for the send low watermark. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + + [ + + [[link boost_asio.reference.basic_stream_socket.shutdown_type [*shutdown_type]]] + [Different ways a socket may be shutdown. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_stream_socket.assign [*assign]]] + [Assign an existing native socket to the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.async_connect [*async_connect]]] + [Start an asynchronous connect. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.async_receive [*async_receive]]] + [Start an asynchronous receive. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.async_send [*async_send]]] + [Start an asynchronous send. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.at_mark [*at_mark]]] + [Determine whether the socket is at the out-of-band data mark. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.available [*available]]] + [Determine the number of bytes available for reading. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.basic_stream_socket [*basic_stream_socket]]] + [Construct a basic_stream_socket without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.bind [*bind]]] + [Bind the socket to the given local endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.close [*close]]] + [Close the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.connect [*connect]]] + [Connect the socket to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.get_option [*get_option]]] + [Get an option from the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.io_control [*io_control]]] + [Perform an IO control command on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.is_open [*is_open]]] + [Determine whether the socket is open. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.local_endpoint [*local_endpoint]]] + [Get the local endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.native [*native]]] + [Get the native socket representation. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.open [*open]]] + [Open the socket using the specified protocol. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.read_some [*read_some]]] + [Read some data from the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.receive [*receive]]] + [Receive some data on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.remote_endpoint [*remote_endpoint]]] + [Get the remote endpoint of the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.send [*send]]] + [Send some data on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.set_option [*set_option]]] + [Set an option on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.shutdown [*shutdown]]] + [Disable sends or receives on the socket. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.write_some [*write_some]]] + [Write some data to the socket. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_stream_socket.max_connections [*max_connections]]] + [The maximum length of the queue of pending incoming connections. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.message_do_not_route [*message_do_not_route]]] + [Specify that the data should not be subject to routing. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.message_out_of_band [*message_out_of_band]]] + [Process out-of-band data. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.message_peek [*message_peek]]] + [Peek at incoming data without removing it from the input queue. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_stream_socket.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_stream_socket.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_stream_socket class template provides asynchronous and blocking stream-oriented socket functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:type local::stream_protocol::type] + +Obtain an identifier for the type of the protocol. + + int type() const; + + + +[endsect] + + + [endsect] [section:mutable_buffer mutable_buffer] @@ -31345,18 +42364,23 @@ Holds a buffer that can be modified. ] -[heading Friends] +[heading Related Functions] [table [[Name][Description]] [ - [[link boost_asio.reference.mutable_buffer.buffer_cast_helper [*buffer_cast_helper]]] - [] + [[link boost_asio.reference.mutable_buffer.buffer_cast [*buffer_cast]]] + [Cast a non-modifiable buffer to a specified pointer to POD type. ] ] [ - [[link boost_asio.reference.mutable_buffer.buffer_size_helper [*buffer_size_helper]]] - [] + [[link boost_asio.reference.mutable_buffer.buffer_size [*buffer_size]]] + [Get the number of bytes in a non-modifiable buffer. ] + ] + + [ + [[link boost_asio.reference.mutable_buffer.operator_plus_ [*operator+]]] + [Create a new modifiable buffer that is offset from the start of another. ] ] ] @@ -31364,11 +42388,13 @@ Holds a buffer that can be modified. The mutable_buffer class provides a safe representation of a buffer that can be modified. It does not own the underlying data, and so is cheap to copy or assign. -[section:buffer_cast_helper mutable_buffer::buffer_cast_helper] +[section:buffer_cast mutable_buffer::buffer_cast] +Cast a non-modifiable buffer to a specified pointer to POD type. - - friend void * buffer_cast_helper( + template< + typename ``[link boost_asio.reference.PointerToPodType PointerToPodType]``> + PointerToPodType buffer_cast( const mutable_buffer & b); @@ -31377,11 +42403,11 @@ The mutable_buffer class provides a safe representation of a buffer that can be -[section:buffer_size_helper mutable_buffer::buffer_size_helper] +[section:buffer_size mutable_buffer::buffer_size] +Get the number of bytes in a non-modifiable buffer. - - friend std::size_t buffer_size_helper( + std::size_t buffer_size( const mutable_buffer & b); @@ -31422,6 +42448,48 @@ Construct a buffer to represent a given memory range. +[endsect] + + +[endsect] + +[section:operator_plus_ mutable_buffer::operator+] + +Create a new modifiable buffer that is offset from the start of another. + + mutable_buffer ``[link boost_asio.reference.mutable_buffer.operator_plus_.overload1 operator+]``( + const mutable_buffer & b, + std::size_t start); + + mutable_buffer ``[link boost_asio.reference.mutable_buffer.operator_plus_.overload2 operator+]``( + std::size_t start, + const mutable_buffer & b); + + +[section:overload1 mutable_buffer::operator+ (1 of 2 overloads)] + +Create a new modifiable buffer that is offset from the start of another. + + mutable_buffer operator+( + const mutable_buffer & b, + std::size_t start); + + + +[endsect] + + + +[section:overload2 mutable_buffer::operator+ (2 of 2 overloads)] + +Create a new modifiable buffer that is offset from the start of another. + + mutable_buffer operator+( + std::size_t start, + const mutable_buffer & b); + + + [endsect] @@ -31479,6 +42547,27 @@ Adapts a single modifiable buffer so that it meets the requirements of the Mutab ] +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.mutable_buffers_1.buffer_cast [*buffer_cast]]] + [Cast a non-modifiable buffer to a specified pointer to POD type. ] + ] + + [ + [[link boost_asio.reference.mutable_buffers_1.buffer_size [*buffer_size]]] + [Get the number of bytes in a non-modifiable buffer. ] + ] + + [ + [[link boost_asio.reference.mutable_buffers_1.operator_plus_ [*operator+]]] + [Create a new modifiable buffer that is offset from the start of another. ] + ] + +] + [section:begin mutable_buffers_1::begin] @@ -31492,6 +42581,40 @@ Get a random-access iterator to the first element. +[section:buffer_cast mutable_buffers_1::buffer_cast] + + +['Inherited from mutable_buffer.] + +Cast a non-modifiable buffer to a specified pointer to POD type. + + template< + typename ``[link boost_asio.reference.PointerToPodType PointerToPodType]``> + PointerToPodType buffer_cast( + const mutable_buffer & b); + + + +[endsect] + + + +[section:buffer_size mutable_buffers_1::buffer_size] + + +['Inherited from mutable_buffer.] + +Get the number of bytes in a non-modifiable buffer. + + std::size_t buffer_size( + const mutable_buffer & b); + + + +[endsect] + + + [section:const_iterator mutable_buffers_1::const_iterator] A random-access iterator type that may be used to read elements. @@ -31529,6 +42652,54 @@ Construct to represent a single modifiable buffer. [endsect] +[section:operator_plus_ mutable_buffers_1::operator+] + +Create a new modifiable buffer that is offset from the start of another. + + mutable_buffer ``[link boost_asio.reference.mutable_buffers_1.operator_plus_.overload1 operator+]``( + const mutable_buffer & b, + std::size_t start); + + mutable_buffer ``[link boost_asio.reference.mutable_buffers_1.operator_plus_.overload2 operator+]``( + std::size_t start, + const mutable_buffer & b); + + +[section:overload1 mutable_buffers_1::operator+ (1 of 2 overloads)] + + +['Inherited from mutable_buffer.] + +Create a new modifiable buffer that is offset from the start of another. + + mutable_buffer operator+( + const mutable_buffer & b, + std::size_t start); + + + +[endsect] + + + +[section:overload2 mutable_buffers_1::operator+ (2 of 2 overloads)] + + +['Inherited from mutable_buffer.] + +Create a new modifiable buffer that is offset from the start of another. + + mutable_buffer operator+( + std::size_t start, + const mutable_buffer & b); + + + +[endsect] + + +[endsect] + [section:value_type mutable_buffers_1::value_type] @@ -31548,18 +42719,153 @@ The type for each element in the list of buffers. ] -[heading Friends] +[heading Related Functions] [table [[Name][Description]] [ - [[link boost_asio.reference.mutable_buffer.buffer_cast_helper [*buffer_cast_helper]]] - [] + [[link boost_asio.reference.mutable_buffer.buffer_cast [*buffer_cast]]] + [Cast a non-modifiable buffer to a specified pointer to POD type. ] ] [ - [[link boost_asio.reference.mutable_buffer.buffer_size_helper [*buffer_size_helper]]] - [] + [[link boost_asio.reference.mutable_buffer.buffer_size [*buffer_size]]] + [Get the number of bytes in a non-modifiable buffer. ] + ] + + [ + [[link boost_asio.reference.mutable_buffer.operator_plus_ [*operator+]]] + [Create a new modifiable buffer that is offset from the start of another. ] + ] + +] + +The mutable_buffer class provides a safe representation of a buffer that can be modified. It does not own the underlying data, and so is cheap to copy or assign. + + + +[endsect] + + + +[endsect] + +[section:null_buffers null_buffers] + +An implementation of both the ConstBufferSequence and MutableBufferSequence concepts to represent a null buffer sequence. + + class null_buffers + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.null_buffers.const_iterator [*const_iterator]]] + [A random-access iterator type that may be used to read elements. ] + + ] + + [ + + [[link boost_asio.reference.null_buffers.value_type [*value_type]]] + [The type for each element in the list of buffers. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.null_buffers.begin [*begin]]] + [Get a random-access iterator to the first element. ] + ] + + [ + [[link boost_asio.reference.null_buffers.end [*end]]] + [Get a random-access iterator for one past the last element. ] + ] + +] + + +[section:begin null_buffers::begin] + +Get a random-access iterator to the first element. + + const_iterator begin() const; + + + +[endsect] + + + +[section:const_iterator null_buffers::const_iterator] + +A random-access iterator type that may be used to read elements. + + typedef const mutable_buffer * const_iterator; + + + + +[endsect] + + + +[section:end null_buffers::end] + +Get a random-access iterator for one past the last element. + + const_iterator end() const; + + + +[endsect] + + + +[section:value_type null_buffers::value_type] + +The type for each element in the list of buffers. + + typedef mutable_buffer value_type; + + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.mutable_buffer.mutable_buffer [*mutable_buffer]]] + [Construct an empty buffer. ] + ] + +] + +[heading Related Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.mutable_buffer.buffer_cast [*buffer_cast]]] + [Cast a non-modifiable buffer to a specified pointer to POD type. ] + ] + + [ + [[link boost_asio.reference.mutable_buffer.buffer_size [*buffer_size]]] + [Get the number of bytes in a non-modifiable buffer. ] + ] + + [ + [[link boost_asio.reference.mutable_buffer.operator_plus_ [*operator+]]] + [Create a new modifiable buffer that is offset from the start of another. ] ] ] @@ -31610,6 +42916,3638 @@ An argument placeholder, for use with boost::bind(), that corresponds to the ite [endsect] +[section:posix__basic_descriptor posix::basic_descriptor] + +Provides POSIX descriptor functionality. + + template< + typename ``[link boost_asio.reference.DescriptorService DescriptorService]``> + class basic_descriptor : + public basic_io_object< DescriptorService >, + public posix::descriptor_base + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.lowest_layer_type [*lowest_layer_type]]] + [A basic_descriptor is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.native_type [*native_type]]] + [The native representation of a descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor.assign [*assign]]] + [Assign an existing native descriptor to the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.basic_descriptor [*basic_descriptor]]] + [Construct a basic_descriptor without opening it. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.close [*close]]] + [Close the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.io_control [*io_control]]] + [Perform an IO control command on the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.is_open [*is_open]]] + [Determine whether the descriptor is open. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.native [*native]]] + [Get the native descriptor representation. ] + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor._basic_descriptor [*~basic_descriptor]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The posix::basic_descriptor class template provides the ability to wrap a POSIX descriptor. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + +[section:assign posix::basic_descriptor::assign] + +Assign an existing native descriptor to the descriptor. + + void ``[link boost_asio.reference.posix__basic_descriptor.assign.overload1 assign]``( + const native_type & native_descriptor); + + boost::system::error_code ``[link boost_asio.reference.posix__basic_descriptor.assign.overload2 assign]``( + const native_type & native_descriptor, + boost::system::error_code & ec); + + +[section:overload1 posix::basic_descriptor::assign (1 of 2 overloads)] + +Assign an existing native descriptor to the descriptor. + + void assign( + const native_type & native_descriptor); + + + +[endsect] + + + +[section:overload2 posix::basic_descriptor::assign (2 of 2 overloads)] + +Assign an existing native descriptor to the descriptor. + + boost::system::error_code assign( + const native_type & native_descriptor, + boost::system::error_code & ec); + + + +[endsect] + + +[endsect] + +[section:basic_descriptor posix::basic_descriptor::basic_descriptor] + +Construct a basic_descriptor without opening it. + + ``[link boost_asio.reference.posix__basic_descriptor.basic_descriptor.overload1 basic_descriptor]``( + boost::asio::io_service & io_service); + + ``[link boost_asio.reference.posix__basic_descriptor.basic_descriptor.overload2 basic_descriptor]``( + boost::asio::io_service & io_service, + const native_type & native_descriptor); + + +[section:overload1 posix::basic_descriptor::basic_descriptor (1 of 2 overloads)] + +Construct a basic_descriptor without opening it. + + basic_descriptor( + boost::asio::io_service & io_service); + + +This constructor creates a descriptor without opening it. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the descriptor will use to dispatch handlers for any asynchronous operations performed on the descriptor. ]] + +] + + + +[endsect] + + + +[section:overload2 posix::basic_descriptor::basic_descriptor (2 of 2 overloads)] + +Construct a basic_descriptor on an existing native descriptor. + + basic_descriptor( + boost::asio::io_service & io_service, + const native_type & native_descriptor); + + +This constructor creates a descriptor object to hold an existing native descriptor. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the descriptor will use to dispatch handlers for any asynchronous operations performed on the descriptor.]] + +[[native_descriptor][A native descriptor.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:bytes_readable posix::basic_descriptor::bytes_readable] + + +['Inherited from posix::descriptor_base.] + +IO control command to get the amount of data that can be read without blocking. + + typedef implementation_defined bytes_readable; + + + +Implements the FIONREAD IO control command. + + +[heading Example] + + + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::descriptor_base::bytes_readable command(true); + descriptor.io_control(command); + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + +[section:cancel posix::basic_descriptor::cancel] + +Cancel all asynchronous operations associated with the descriptor. + + void ``[link boost_asio.reference.posix__basic_descriptor.cancel.overload1 cancel]``(); + + boost::system::error_code ``[link boost_asio.reference.posix__basic_descriptor.cancel.overload2 cancel]``( + boost::system::error_code & ec); + + +[section:overload1 posix::basic_descriptor::cancel (1 of 2 overloads)] + +Cancel all asynchronous operations associated with the descriptor. + + void cancel(); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 posix::basic_descriptor::cancel (2 of 2 overloads)] + +Cancel all asynchronous operations associated with the descriptor. + + boost::system::error_code cancel( + boost::system::error_code & ec); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + +[section:close posix::basic_descriptor::close] + +Close the descriptor. + + void ``[link boost_asio.reference.posix__basic_descriptor.close.overload1 close]``(); + + boost::system::error_code ``[link boost_asio.reference.posix__basic_descriptor.close.overload2 close]``( + boost::system::error_code & ec); + + +[section:overload1 posix::basic_descriptor::close (1 of 2 overloads)] + +Close the descriptor. + + void close(); + + +This function is used to close the descriptor. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 posix::basic_descriptor::close (2 of 2 overloads)] + +Close the descriptor. + + boost::system::error_code close( + boost::system::error_code & ec); + + +This function is used to close the descriptor. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:get_io_service posix::basic_descriptor::get_io_service] + + +['Inherited from basic_io_object.] + +Get the io_service associated with the object. + + boost::asio::io_service & get_io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:implementation posix::basic_descriptor::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + +[section:implementation_type posix::basic_descriptor::implementation_type] + + +['Inherited from basic_io_object.] + +The underlying implementation type of I/O object. + + typedef service_type::implementation_type implementation_type; + + + + +[endsect] + + +[section:io_control posix::basic_descriptor::io_control] + +Perform an IO control command on the descriptor. + + template< + typename ``[link boost_asio.reference.IoControlCommand IoControlCommand]``> + void ``[link boost_asio.reference.posix__basic_descriptor.io_control.overload1 io_control]``( + IoControlCommand & command); + + template< + typename ``[link boost_asio.reference.IoControlCommand IoControlCommand]``> + boost::system::error_code ``[link boost_asio.reference.posix__basic_descriptor.io_control.overload2 io_control]``( + IoControlCommand & command, + boost::system::error_code & ec); + + +[section:overload1 posix::basic_descriptor::io_control (1 of 2 overloads)] + +Perform an IO control command on the descriptor. + + template< + typename ``[link boost_asio.reference.IoControlCommand IoControlCommand]``> + void io_control( + IoControlCommand & command); + + +This function is used to execute an IO control command on the descriptor. + + +[heading Parameters] + + +[variablelist + +[[command][The IO control command to be performed on the descriptor.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +Getting the number of bytes ready to read: + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::posix::stream_descriptor::bytes_readable command; + descriptor.io_control(command); + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + + +[section:overload2 posix::basic_descriptor::io_control (2 of 2 overloads)] + +Perform an IO control command on the descriptor. + + template< + typename ``[link boost_asio.reference.IoControlCommand IoControlCommand]``> + boost::system::error_code io_control( + IoControlCommand & command, + boost::system::error_code & ec); + + +This function is used to execute an IO control command on the descriptor. + + +[heading Parameters] + + +[variablelist + +[[command][The IO control command to be performed on the descriptor.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + +Getting the number of bytes ready to read: + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::posix::stream_descriptor::bytes_readable command; + boost::system::error_code ec; + descriptor.io_control(command, ec); + if (ec) + { + // An error occurred. + } + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + +[endsect] + + +[section:io_service posix::basic_descriptor::io_service] + + +['Inherited from basic_io_object.] + +(Deprecated: use get_io_service().) Get the io_service associated with the object. + + boost::asio::io_service & io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:is_open posix::basic_descriptor::is_open] + +Determine whether the descriptor is open. + + bool is_open() const; + + + +[endsect] + + + +[section:lowest_layer posix::basic_descriptor::lowest_layer] + +Get a reference to the lowest layer. + + lowest_layer_type & lowest_layer(); + + +This function returns a reference to the lowest layer in a stack of layers. Since a basic_descriptor cannot contain any further layers, it simply returns a reference to itself. + + +[heading Return Value] + +A reference to the lowest layer in the stack of layers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:lowest_layer_type posix::basic_descriptor::lowest_layer_type] + +A basic_descriptor is always the lowest layer. + + typedef basic_descriptor< DescriptorService > lowest_layer_type; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.lowest_layer_type [*lowest_layer_type]]] + [A basic_descriptor is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.native_type [*native_type]]] + [The native representation of a descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor.assign [*assign]]] + [Assign an existing native descriptor to the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.basic_descriptor [*basic_descriptor]]] + [Construct a basic_descriptor without opening it. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.close [*close]]] + [Close the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.io_control [*io_control]]] + [Perform an IO control command on the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.is_open [*is_open]]] + [Determine whether the descriptor is open. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.native [*native]]] + [Get the native descriptor representation. ] + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor._basic_descriptor [*~basic_descriptor]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The posix::basic_descriptor class template provides the ability to wrap a POSIX descriptor. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:native posix::basic_descriptor::native] + +Get the native descriptor representation. + + native_type native(); + + +This function may be used to obtain the underlying representation of the descriptor. This is intended to allow access to native descriptor functionality that is not otherwise provided. + + +[endsect] + + + +[section:native_type posix::basic_descriptor::native_type] + +The native representation of a descriptor. + + typedef DescriptorService::native_type native_type; + + + + +[endsect] + + + +[section:non_blocking_io posix::basic_descriptor::non_blocking_io] + + +['Inherited from posix::descriptor_base.] + +IO control command to set the blocking mode of the descriptor. + + typedef implementation_defined non_blocking_io; + + + +Implements the FIONBIO IO control command. + + +[heading Example] + + + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::descriptor_base::non_blocking_io command(true); + descriptor.io_control(command); + + + + + + +[endsect] + + + +[section:service posix::basic_descriptor::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + +[section:service_type posix::basic_descriptor::service_type] + + +['Inherited from basic_io_object.] + +The type of the service that will be used to provide I/O operations. + + typedef DescriptorService service_type; + + + + +[endsect] + + + +[section:_basic_descriptor posix::basic_descriptor::~basic_descriptor] + +Protected destructor to prevent deletion through this type. + + ~basic_descriptor(); + + + +[endsect] + + + +[endsect] + +[section:posix__basic_stream_descriptor posix::basic_stream_descriptor] + +Provides stream-oriented descriptor functionality. + + template< + typename ``[link boost_asio.reference.StreamDescriptorService StreamDescriptorService]`` = stream_descriptor_service> + class basic_stream_descriptor : + public posix::basic_descriptor< StreamDescriptorService > + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.lowest_layer_type [*lowest_layer_type]]] + [A basic_descriptor is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.native_type [*native_type]]] + [The native representation of a descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.assign [*assign]]] + [Assign an existing native descriptor to the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.basic_stream_descriptor [*basic_stream_descriptor]]] + [Construct a basic_stream_descriptor without opening it. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.close [*close]]] + [Close the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.io_control [*io_control]]] + [Perform an IO control command on the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.is_open [*is_open]]] + [Determine whether the descriptor is open. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.native [*native]]] + [Get the native descriptor representation. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.read_some [*read_some]]] + [Read some data from the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.write_some [*write_some]]] + [Write some data to the descriptor. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The posix::basic_stream_descriptor class template provides asynchronous and blocking stream-oriented descriptor functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + +[section:assign posix::basic_stream_descriptor::assign] + +Assign an existing native descriptor to the descriptor. + + void ``[link boost_asio.reference.posix__basic_stream_descriptor.assign.overload1 assign]``( + const native_type & native_descriptor); + + boost::system::error_code ``[link boost_asio.reference.posix__basic_stream_descriptor.assign.overload2 assign]``( + const native_type & native_descriptor, + boost::system::error_code & ec); + + +[section:overload1 posix::basic_stream_descriptor::assign (1 of 2 overloads)] + + +['Inherited from posix::basic_descriptor.] + +Assign an existing native descriptor to the descriptor. + + void assign( + const native_type & native_descriptor); + + + +[endsect] + + + +[section:overload2 posix::basic_stream_descriptor::assign (2 of 2 overloads)] + + +['Inherited from posix::basic_descriptor.] + +Assign an existing native descriptor to the descriptor. + + boost::system::error_code assign( + const native_type & native_descriptor, + boost::system::error_code & ec); + + + +[endsect] + + +[endsect] + + +[section:async_read_some posix::basic_stream_descriptor::async_read_some] + +Start an asynchronous read. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_some( + const MutableBufferSequence & buffers, + ReadHandler handler); + + +This function is used to asynchronously read data from the stream descriptor. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes read. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The read operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.async_read async_read] function if you need to ensure that the requested amount of data is read before the asynchronous operation completes. + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + descriptor.async_read_some(boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:async_write_some posix::basic_stream_descriptor::async_write_some] + +Start an asynchronous write. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_some( + const ConstBufferSequence & buffers, + WriteHandler handler); + + +This function is used to asynchronously write data to the stream descriptor. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the descriptor. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes written. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The write operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.async_write async_write] function if you need to ensure that all data is written before the asynchronous operation completes. + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + descriptor.async_write_some(boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + +[section:basic_stream_descriptor posix::basic_stream_descriptor::basic_stream_descriptor] + +Construct a basic_stream_descriptor without opening it. + + ``[link boost_asio.reference.posix__basic_stream_descriptor.basic_stream_descriptor.overload1 basic_stream_descriptor]``( + boost::asio::io_service & io_service); + + ``[link boost_asio.reference.posix__basic_stream_descriptor.basic_stream_descriptor.overload2 basic_stream_descriptor]``( + boost::asio::io_service & io_service, + const native_type & native_descriptor); + + +[section:overload1 posix::basic_stream_descriptor::basic_stream_descriptor (1 of 2 overloads)] + +Construct a basic_stream_descriptor without opening it. + + basic_stream_descriptor( + boost::asio::io_service & io_service); + + +This constructor creates a stream descriptor without opening it. The descriptor needs to be opened and then connected or accepted before data can be sent or received on it. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the stream descriptor will use to dispatch handlers for any asynchronous operations performed on the descriptor. ]] + +] + + + +[endsect] + + + +[section:overload2 posix::basic_stream_descriptor::basic_stream_descriptor (2 of 2 overloads)] + +Construct a basic_stream_descriptor on an existing native descriptor. + + basic_stream_descriptor( + boost::asio::io_service & io_service, + const native_type & native_descriptor); + + +This constructor creates a stream descriptor object to hold an existing native descriptor. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the stream descriptor will use to dispatch handlers for any asynchronous operations performed on the descriptor.]] + +[[native_descriptor][The new underlying descriptor implementation.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:bytes_readable posix::basic_stream_descriptor::bytes_readable] + + +['Inherited from posix::descriptor_base.] + +IO control command to get the amount of data that can be read without blocking. + + typedef implementation_defined bytes_readable; + + + +Implements the FIONREAD IO control command. + + +[heading Example] + + + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::descriptor_base::bytes_readable command(true); + descriptor.io_control(command); + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + +[section:cancel posix::basic_stream_descriptor::cancel] + +Cancel all asynchronous operations associated with the descriptor. + + void ``[link boost_asio.reference.posix__basic_stream_descriptor.cancel.overload1 cancel]``(); + + boost::system::error_code ``[link boost_asio.reference.posix__basic_stream_descriptor.cancel.overload2 cancel]``( + boost::system::error_code & ec); + + +[section:overload1 posix::basic_stream_descriptor::cancel (1 of 2 overloads)] + + +['Inherited from posix::basic_descriptor.] + +Cancel all asynchronous operations associated with the descriptor. + + void cancel(); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 posix::basic_stream_descriptor::cancel (2 of 2 overloads)] + + +['Inherited from posix::basic_descriptor.] + +Cancel all asynchronous operations associated with the descriptor. + + boost::system::error_code cancel( + boost::system::error_code & ec); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + +[section:close posix::basic_stream_descriptor::close] + +Close the descriptor. + + void ``[link boost_asio.reference.posix__basic_stream_descriptor.close.overload1 close]``(); + + boost::system::error_code ``[link boost_asio.reference.posix__basic_stream_descriptor.close.overload2 close]``( + boost::system::error_code & ec); + + +[section:overload1 posix::basic_stream_descriptor::close (1 of 2 overloads)] + + +['Inherited from posix::basic_descriptor.] + +Close the descriptor. + + void close(); + + +This function is used to close the descriptor. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 posix::basic_stream_descriptor::close (2 of 2 overloads)] + + +['Inherited from posix::basic_descriptor.] + +Close the descriptor. + + boost::system::error_code close( + boost::system::error_code & ec); + + +This function is used to close the descriptor. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:get_io_service posix::basic_stream_descriptor::get_io_service] + + +['Inherited from basic_io_object.] + +Get the io_service associated with the object. + + boost::asio::io_service & get_io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:implementation posix::basic_stream_descriptor::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + +[section:implementation_type posix::basic_stream_descriptor::implementation_type] + + +['Inherited from basic_io_object.] + +The underlying implementation type of I/O object. + + typedef service_type::implementation_type implementation_type; + + + + +[endsect] + + +[section:io_control posix::basic_stream_descriptor::io_control] + +Perform an IO control command on the descriptor. + + void ``[link boost_asio.reference.posix__basic_stream_descriptor.io_control.overload1 io_control]``( + IoControlCommand & command); + + boost::system::error_code ``[link boost_asio.reference.posix__basic_stream_descriptor.io_control.overload2 io_control]``( + IoControlCommand & command, + boost::system::error_code & ec); + + +[section:overload1 posix::basic_stream_descriptor::io_control (1 of 2 overloads)] + + +['Inherited from posix::basic_descriptor.] + +Perform an IO control command on the descriptor. + + void io_control( + IoControlCommand & command); + + +This function is used to execute an IO control command on the descriptor. + + +[heading Parameters] + + +[variablelist + +[[command][The IO control command to be performed on the descriptor.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +Getting the number of bytes ready to read: + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::posix::stream_descriptor::bytes_readable command; + descriptor.io_control(command); + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + + +[section:overload2 posix::basic_stream_descriptor::io_control (2 of 2 overloads)] + + +['Inherited from posix::basic_descriptor.] + +Perform an IO control command on the descriptor. + + boost::system::error_code io_control( + IoControlCommand & command, + boost::system::error_code & ec); + + +This function is used to execute an IO control command on the descriptor. + + +[heading Parameters] + + +[variablelist + +[[command][The IO control command to be performed on the descriptor.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Example] + +Getting the number of bytes ready to read: + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::posix::stream_descriptor::bytes_readable command; + boost::system::error_code ec; + descriptor.io_control(command, ec); + if (ec) + { + // An error occurred. + } + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + +[endsect] + + +[section:io_service posix::basic_stream_descriptor::io_service] + + +['Inherited from basic_io_object.] + +(Deprecated: use get_io_service().) Get the io_service associated with the object. + + boost::asio::io_service & io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:is_open posix::basic_stream_descriptor::is_open] + + +['Inherited from posix::basic_descriptor.] + +Determine whether the descriptor is open. + + bool is_open() const; + + + +[endsect] + + + +[section:lowest_layer posix::basic_stream_descriptor::lowest_layer] + + +['Inherited from posix::basic_descriptor.] + +Get a reference to the lowest layer. + + lowest_layer_type & lowest_layer(); + + +This function returns a reference to the lowest layer in a stack of layers. Since a basic_descriptor cannot contain any further layers, it simply returns a reference to itself. + + +[heading Return Value] + +A reference to the lowest layer in the stack of layers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:lowest_layer_type posix::basic_stream_descriptor::lowest_layer_type] + + +['Inherited from posix::basic_descriptor.] + +A basic_descriptor is always the lowest layer. + + typedef basic_descriptor< StreamDescriptorService > lowest_layer_type; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.lowest_layer_type [*lowest_layer_type]]] + [A basic_descriptor is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.native_type [*native_type]]] + [The native representation of a descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_descriptor.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor.assign [*assign]]] + [Assign an existing native descriptor to the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.basic_descriptor [*basic_descriptor]]] + [Construct a basic_descriptor without opening it. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.close [*close]]] + [Close the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.io_control [*io_control]]] + [Perform an IO control command on the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.is_open [*is_open]]] + [Determine whether the descriptor is open. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.native [*native]]] + [Get the native descriptor representation. ] + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor._basic_descriptor [*~basic_descriptor]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_descriptor.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_descriptor.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The posix::basic_descriptor class template provides the ability to wrap a POSIX descriptor. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:native posix::basic_stream_descriptor::native] + + +['Inherited from posix::basic_descriptor.] + +Get the native descriptor representation. + + native_type native(); + + +This function may be used to obtain the underlying representation of the descriptor. This is intended to allow access to native descriptor functionality that is not otherwise provided. + + +[endsect] + + + +[section:native_type posix::basic_stream_descriptor::native_type] + +The native representation of a descriptor. + + typedef StreamDescriptorService::native_type native_type; + + + + +[endsect] + + + +[section:non_blocking_io posix::basic_stream_descriptor::non_blocking_io] + + +['Inherited from posix::descriptor_base.] + +IO control command to set the blocking mode of the descriptor. + + typedef implementation_defined non_blocking_io; + + + +Implements the FIONBIO IO control command. + + +[heading Example] + + + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::descriptor_base::non_blocking_io command(true); + descriptor.io_control(command); + + + + + + +[endsect] + + +[section:read_some posix::basic_stream_descriptor::read_some] + +Read some data from the descriptor. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.posix__basic_stream_descriptor.read_some.overload1 read_some]``( + const MutableBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.posix__basic_stream_descriptor.read_some.overload2 read_some]``( + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + +[section:overload1 posix::basic_stream_descriptor::read_some (1 of 2 overloads)] + +Read some data from the descriptor. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + const MutableBufferSequence & buffers); + + +This function is used to read data from the stream descriptor. The function call will block until one or more bytes of data has been read successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read.]] + +] + +[heading Return Value] + +The number of bytes read. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. An error code of boost::asio::error::eof indicates that the connection was closed by the peer.]] + +] + +[heading Remarks] + +The read\_some operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.read read] function if you need to ensure that the requested amount of data is read before the blocking operation completes. + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + descriptor.read_some(boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 posix::basic_stream_descriptor::read_some (2 of 2 overloads)] + +Read some data from the descriptor. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + +This function is used to read data from the stream descriptor. The function call will block until one or more bytes of data has been read successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes read. Returns 0 if an error occurred. + +[heading Remarks] + +The read\_some operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.read read] function if you need to ensure that the requested amount of data is read before the blocking operation completes. + + + +[endsect] + + +[endsect] + + +[section:service posix::basic_stream_descriptor::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + +[section:service_type posix::basic_stream_descriptor::service_type] + + +['Inherited from basic_io_object.] + +The type of the service that will be used to provide I/O operations. + + typedef StreamDescriptorService service_type; + + + + +[endsect] + + +[section:write_some posix::basic_stream_descriptor::write_some] + +Write some data to the descriptor. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.posix__basic_stream_descriptor.write_some.overload1 write_some]``( + const ConstBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.posix__basic_stream_descriptor.write_some.overload2 write_some]``( + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + +[section:overload1 posix::basic_stream_descriptor::write_some (1 of 2 overloads)] + +Write some data to the descriptor. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + const ConstBufferSequence & buffers); + + +This function is used to write data to the stream descriptor. The function call will block until one or more bytes of the data has been written successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the descriptor.]] + +] + +[heading Return Value] + +The number of bytes written. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. An error code of boost::asio::error::eof indicates that the connection was closed by the peer.]] + +] + +[heading Remarks] + +The write\_some operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.write write] function if you need to ensure that all data is written before the blocking operation completes. + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + descriptor.write_some(boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 posix::basic_stream_descriptor::write_some (2 of 2 overloads)] + +Write some data to the descriptor. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + +This function is used to write data to the stream descriptor. The function call will block until one or more bytes of the data has been written successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the descriptor.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes written. Returns 0 if an error occurred. + +[heading Remarks] + +The write\_some operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.write write] function if you need to ensure that all data is written before the blocking operation completes. + + + +[endsect] + + +[endsect] + + +[endsect] + +[section:posix__descriptor_base posix::descriptor_base] + +The descriptor_base class is used as a base for the basic_stream_descriptor class template so that we have a common place to define the associated IO control commands. + + class descriptor_base + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.posix__descriptor_base.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.posix__descriptor_base.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the descriptor. ] + + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__descriptor_base._descriptor_base [*~descriptor_base]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + + +[section:bytes_readable posix::descriptor_base::bytes_readable] + +IO control command to get the amount of data that can be read without blocking. + + typedef implementation_defined bytes_readable; + + + +Implements the FIONREAD IO control command. + + +[heading Example] + + + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::descriptor_base::bytes_readable command(true); + descriptor.io_control(command); + std::size_t bytes_readable = command.get(); + + + + + + +[endsect] + + + +[section:non_blocking_io posix::descriptor_base::non_blocking_io] + +IO control command to set the blocking mode of the descriptor. + + typedef implementation_defined non_blocking_io; + + + +Implements the FIONBIO IO control command. + + +[heading Example] + + + + boost::asio::posix::stream_descriptor descriptor(io_service); + ... + boost::asio::descriptor_base::non_blocking_io command(true); + descriptor.io_control(command); + + + + + + +[endsect] + + + +[section:_descriptor_base posix::descriptor_base::~descriptor_base] + +Protected destructor to prevent deletion through this type. + + ~descriptor_base(); + + + +[endsect] + + + +[endsect] + + +[section:posix__stream_descriptor posix::stream_descriptor] + +Typedef for the typical usage of a stream-oriented descriptor. + + typedef basic_stream_descriptor stream_descriptor; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.bytes_readable [*bytes_readable]]] + [IO control command to get the amount of data that can be read without blocking. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.lowest_layer_type [*lowest_layer_type]]] + [A basic_descriptor is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.native_type [*native_type]]] + [The native representation of a descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.non_blocking_io [*non_blocking_io]]] + [IO control command to set the blocking mode of the descriptor. ] + + ] + + [ + + [[link boost_asio.reference.posix__basic_stream_descriptor.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.assign [*assign]]] + [Assign an existing native descriptor to the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.basic_stream_descriptor [*basic_stream_descriptor]]] + [Construct a basic_stream_descriptor without opening it. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.close [*close]]] + [Close the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.io_control [*io_control]]] + [Perform an IO control command on the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.is_open [*is_open]]] + [Determine whether the descriptor is open. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.native [*native]]] + [Get the native descriptor representation. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.read_some [*read_some]]] + [Read some data from the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.write_some [*write_some]]] + [Write some data to the descriptor. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.posix__basic_stream_descriptor.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The posix::basic_stream_descriptor class template provides asynchronous and blocking stream-oriented descriptor functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + +[section:posix__stream_descriptor_service posix::stream_descriptor_service] + +Default service implementation for a stream descriptor. + + class stream_descriptor_service : + public io_service::service + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.posix__stream_descriptor_service.implementation_type [*implementation_type]]] + [The type of a stream descriptor implementation. ] + + ] + + [ + + [[link boost_asio.reference.posix__stream_descriptor_service.native_type [*native_type]]] + [The native descriptor type. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.assign [*assign]]] + [Assign an existing native descriptor to a stream descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.close [*close]]] + [Close a stream descriptor implementation. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.construct [*construct]]] + [Construct a new stream descriptor implementation. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.destroy [*destroy]]] + [Destroy a stream descriptor implementation. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.get_io_service [*get_io_service]]] + [Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.io_control [*io_control]]] + [Perform an IO control command on the descriptor. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.is_open [*is_open]]] + [Determine whether the descriptor is open. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.native [*native]]] + [Get the native descriptor implementation. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.read_some [*read_some]]] + [Read some data from the stream. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.shutdown_service [*shutdown_service]]] + [Destroy all user-defined descriptorr objects owned by the service. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.stream_descriptor_service [*stream_descriptor_service]]] + [Construct a new stream descriptor service for the specified io_service. ] + ] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.write_some [*write_some]]] + [Write the given data to the stream. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.posix__stream_descriptor_service.id [*id]]] + [The unique service identifier. ] + ] + +] + + +[section:assign posix::stream_descriptor_service::assign] + +Assign an existing native descriptor to a stream descriptor. + + boost::system::error_code assign( + implementation_type & impl, + const native_type & native_descriptor, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:async_read_some posix::stream_descriptor_service::async_read_some] + +Start an asynchronous read. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_some( + implementation_type & impl, + const MutableBufferSequence & buffers, + ReadHandler descriptorr); + + + +[endsect] + + + +[section:async_write_some posix::stream_descriptor_service::async_write_some] + +Start an asynchronous write. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_some( + implementation_type & impl, + const ConstBufferSequence & buffers, + WriteHandler descriptorr); + + + +[endsect] + + + +[section:cancel posix::stream_descriptor_service::cancel] + +Cancel all asynchronous operations associated with the descriptor. + + boost::system::error_code cancel( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:close posix::stream_descriptor_service::close] + +Close a stream descriptor implementation. + + boost::system::error_code close( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:construct posix::stream_descriptor_service::construct] + +Construct a new stream descriptor implementation. + + void construct( + implementation_type & impl); + + + +[endsect] + + + +[section:destroy posix::stream_descriptor_service::destroy] + +Destroy a stream descriptor implementation. + + void destroy( + implementation_type & impl); + + + +[endsect] + + + +[section:get_io_service posix::stream_descriptor_service::get_io_service] + + +['Inherited from io_service.] + +Get the io_service object that owns the service. + + boost::asio::io_service & get_io_service(); + + + +[endsect] + + + +[section:id posix::stream_descriptor_service::id] + +The unique service identifier. + + static boost::asio::io_service::id id; + + + +[endsect] + + + +[section:implementation_type posix::stream_descriptor_service::implementation_type] + +The type of a stream descriptor implementation. + + typedef implementation_defined implementation_type; + + + + +[endsect] + + + +[section:io_control posix::stream_descriptor_service::io_control] + +Perform an IO control command on the descriptor. + + template< + typename ``[link boost_asio.reference.IoControlCommand IoControlCommand]``> + boost::system::error_code io_control( + implementation_type & impl, + IoControlCommand & command, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:io_service posix::stream_descriptor_service::io_service] + + +['Inherited from io_service.] + +(Deprecated: use get_io_service().) Get the io_service object that owns the service. + + boost::asio::io_service & io_service(); + + + +[endsect] + + + +[section:is_open posix::stream_descriptor_service::is_open] + +Determine whether the descriptor is open. + + bool is_open( + const implementation_type & impl) const; + + + +[endsect] + + + +[section:native posix::stream_descriptor_service::native] + +Get the native descriptor implementation. + + native_type native( + implementation_type & impl); + + + +[endsect] + + + +[section:native_type posix::stream_descriptor_service::native_type] + +The native descriptor type. + + typedef implementation_defined native_type; + + + + +[endsect] + + + +[section:read_some posix::stream_descriptor_service::read_some] + +Read some data from the stream. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + implementation_type & impl, + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:shutdown_service posix::stream_descriptor_service::shutdown_service] + +Destroy all user-defined descriptorr objects owned by the service. + + void shutdown_service(); + + + +[endsect] + + + +[section:stream_descriptor_service posix::stream_descriptor_service::stream_descriptor_service] + +Construct a new stream descriptor service for the specified io_service. + + stream_descriptor_service( + boost::asio::io_service & io_service); + + + +[endsect] + + + +[section:write_some posix::stream_descriptor_service::write_some] + +Write the given data to the stream. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + implementation_type & impl, + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + + +[endsect] + + + +[endsect] + +[section:raw_socket_service raw_socket_service] + +Default service implementation for a raw socket. + + template< + typename ``[link boost_asio.reference.Protocol Protocol]``> + class raw_socket_service : + public io_service::service + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.raw_socket_service.endpoint_type [*endpoint_type]]] + [The endpoint type. ] + + ] + + [ + + [[link boost_asio.reference.raw_socket_service.implementation_type [*implementation_type]]] + [The type of a raw socket. ] + + ] + + [ + + [[link boost_asio.reference.raw_socket_service.native_type [*native_type]]] + [The native socket type. ] + + ] + + [ + + [[link boost_asio.reference.raw_socket_service.protocol_type [*protocol_type]]] + [The protocol type. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.raw_socket_service.assign [*assign]]] + [Assign an existing native socket to a raw socket. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.async_connect [*async_connect]]] + [Start an asynchronous connect. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.async_receive [*async_receive]]] + [Start an asynchronous receive. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.async_receive_from [*async_receive_from]]] + [Start an asynchronous receive that will get the endpoint of the sender. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.async_send [*async_send]]] + [Start an asynchronous send. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.async_send_to [*async_send_to]]] + [Start an asynchronous send. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.at_mark [*at_mark]]] + [Determine whether the socket is at the out-of-band data mark. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.available [*available]]] + [Determine the number of bytes available for reading. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.bind [*bind]]] + [] + ] + + [ + [[link boost_asio.reference.raw_socket_service.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the socket. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.close [*close]]] + [Close a raw socket implementation. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.connect [*connect]]] + [Connect the raw socket to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.construct [*construct]]] + [Construct a new raw socket implementation. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.destroy [*destroy]]] + [Destroy a raw socket implementation. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.get_io_service [*get_io_service]]] + [Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.get_option [*get_option]]] + [Get a socket option. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.io_control [*io_control]]] + [Perform an IO control command on the socket. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.is_open [*is_open]]] + [Determine whether the socket is open. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.local_endpoint [*local_endpoint]]] + [Get the local endpoint. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.native [*native]]] + [Get the native socket implementation. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.open [*open]]] + [] + ] + + [ + [[link boost_asio.reference.raw_socket_service.raw_socket_service [*raw_socket_service]]] + [Construct a new raw socket service for the specified io_service. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.receive [*receive]]] + [Receive some data from the peer. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.receive_from [*receive_from]]] + [Receive raw data with the endpoint of the sender. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.remote_endpoint [*remote_endpoint]]] + [Get the remote endpoint. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.send [*send]]] + [Send the given data to the peer. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.send_to [*send_to]]] + [Send raw data to the specified endpoint. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.set_option [*set_option]]] + [Set a socket option. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.shutdown [*shutdown]]] + [Disable sends or receives on the socket. ] + ] + + [ + [[link boost_asio.reference.raw_socket_service.shutdown_service [*shutdown_service]]] + [Destroy all user-defined handler objects owned by the service. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.raw_socket_service.id [*id]]] + [The unique service identifier. ] + ] + +] + + +[section:assign raw_socket_service::assign] + +Assign an existing native socket to a raw socket. + + boost::system::error_code assign( + implementation_type & impl, + const protocol_type & protocol, + const native_type & native_socket, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:async_connect raw_socket_service::async_connect] + +Start an asynchronous connect. + + template< + typename ``[link boost_asio.reference.ConnectHandler ConnectHandler]``> + void async_connect( + implementation_type & impl, + const endpoint_type & peer_endpoint, + ConnectHandler handler); + + + +[endsect] + + + +[section:async_receive raw_socket_service::async_receive] + +Start an asynchronous receive. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_receive( + implementation_type & impl, + const MutableBufferSequence & buffers, + socket_base::message_flags flags, + ReadHandler handler); + + + +[endsect] + + + +[section:async_receive_from raw_socket_service::async_receive_from] + +Start an asynchronous receive that will get the endpoint of the sender. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_receive_from( + implementation_type & impl, + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + socket_base::message_flags flags, + ReadHandler handler); + + + +[endsect] + + + +[section:async_send raw_socket_service::async_send] + +Start an asynchronous send. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_send( + implementation_type & impl, + const ConstBufferSequence & buffers, + socket_base::message_flags flags, + WriteHandler handler); + + + +[endsect] + + + +[section:async_send_to raw_socket_service::async_send_to] + +Start an asynchronous send. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_send_to( + implementation_type & impl, + const ConstBufferSequence & buffers, + const endpoint_type & destination, + socket_base::message_flags flags, + WriteHandler handler); + + + +[endsect] + + + +[section:at_mark raw_socket_service::at_mark] + +Determine whether the socket is at the out-of-band data mark. + + bool at_mark( + const implementation_type & impl, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:available raw_socket_service::available] + +Determine the number of bytes available for reading. + + std::size_t available( + const implementation_type & impl, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:bind raw_socket_service::bind] + + + + boost::system::error_code bind( + implementation_type & impl, + const endpoint_type & endpoint, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:cancel raw_socket_service::cancel] + +Cancel all asynchronous operations associated with the socket. + + boost::system::error_code cancel( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:close raw_socket_service::close] + +Close a raw socket implementation. + + boost::system::error_code close( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:connect raw_socket_service::connect] + +Connect the raw socket to the specified endpoint. + + boost::system::error_code connect( + implementation_type & impl, + const endpoint_type & peer_endpoint, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:construct raw_socket_service::construct] + +Construct a new raw socket implementation. + + void construct( + implementation_type & impl); + + + +[endsect] + + + +[section:destroy raw_socket_service::destroy] + +Destroy a raw socket implementation. + + void destroy( + implementation_type & impl); + + + +[endsect] + + + +[section:endpoint_type raw_socket_service::endpoint_type] + +The endpoint type. + + typedef Protocol::endpoint endpoint_type; + + + + +[endsect] + + + +[section:get_io_service raw_socket_service::get_io_service] + + +['Inherited from io_service.] + +Get the io_service object that owns the service. + + boost::asio::io_service & get_io_service(); + + + +[endsect] + + + +[section:get_option raw_socket_service::get_option] + +Get a socket option. + + template< + typename ``[link boost_asio.reference.GettableSocketOption GettableSocketOption]``> + boost::system::error_code get_option( + const implementation_type & impl, + GettableSocketOption & option, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:id raw_socket_service::id] + +The unique service identifier. + + static boost::asio::io_service::id id; + + + +[endsect] + + + +[section:implementation_type raw_socket_service::implementation_type] + +The type of a raw socket. + + typedef implementation_defined implementation_type; + + + + +[endsect] + + + +[section:io_control raw_socket_service::io_control] + +Perform an IO control command on the socket. + + template< + typename ``[link boost_asio.reference.IoControlCommand IoControlCommand]``> + boost::system::error_code io_control( + implementation_type & impl, + IoControlCommand & command, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:io_service raw_socket_service::io_service] + + +['Inherited from io_service.] + +(Deprecated: use get_io_service().) Get the io_service object that owns the service. + + boost::asio::io_service & io_service(); + + + +[endsect] + + + +[section:is_open raw_socket_service::is_open] + +Determine whether the socket is open. + + bool is_open( + const implementation_type & impl) const; + + + +[endsect] + + + +[section:local_endpoint raw_socket_service::local_endpoint] + +Get the local endpoint. + + endpoint_type local_endpoint( + const implementation_type & impl, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:native raw_socket_service::native] + +Get the native socket implementation. + + native_type native( + implementation_type & impl); + + + +[endsect] + + + +[section:native_type raw_socket_service::native_type] + +The native socket type. + + typedef implementation_defined native_type; + + + + +[endsect] + + + +[section:open raw_socket_service::open] + + + + boost::system::error_code open( + implementation_type & impl, + const protocol_type & protocol, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:protocol_type raw_socket_service::protocol_type] + +The protocol type. + + typedef Protocol protocol_type; + + + + +[endsect] + + + +[section:raw_socket_service raw_socket_service::raw_socket_service] + +Construct a new raw socket service for the specified io_service. + + raw_socket_service( + boost::asio::io_service & io_service); + + + +[endsect] + + + +[section:receive raw_socket_service::receive] + +Receive some data from the peer. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t receive( + implementation_type & impl, + const MutableBufferSequence & buffers, + socket_base::message_flags flags, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:receive_from raw_socket_service::receive_from] + +Receive raw data with the endpoint of the sender. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t receive_from( + implementation_type & impl, + const MutableBufferSequence & buffers, + endpoint_type & sender_endpoint, + socket_base::message_flags flags, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:remote_endpoint raw_socket_service::remote_endpoint] + +Get the remote endpoint. + + endpoint_type remote_endpoint( + const implementation_type & impl, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:send raw_socket_service::send] + +Send the given data to the peer. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t send( + implementation_type & impl, + const ConstBufferSequence & buffers, + socket_base::message_flags flags, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:send_to raw_socket_service::send_to] + +Send raw data to the specified endpoint. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t send_to( + implementation_type & impl, + const ConstBufferSequence & buffers, + const endpoint_type & destination, + socket_base::message_flags flags, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:set_option raw_socket_service::set_option] + +Set a socket option. + + template< + typename ``[link boost_asio.reference.SettableSocketOption SettableSocketOption]``> + boost::system::error_code set_option( + implementation_type & impl, + const SettableSocketOption & option, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:shutdown raw_socket_service::shutdown] + +Disable sends or receives on the socket. + + boost::system::error_code shutdown( + implementation_type & impl, + socket_base::shutdown_type what, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:shutdown_service raw_socket_service::shutdown_service] + +Destroy all user-defined handler objects owned by the service. + + void shutdown_service(); + + + +[endsect] + + + +[endsect] + [section:read read] Attempt to read a certain amount of data from a stream before returning. @@ -32062,6 +47000,487 @@ The number of bytes read. If an error occurs, returns the total number of bytes +[endsect] + + +[endsect] + +[section:read_at read_at] + +Attempt to read a certain amount of data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.read_at.overload1 read_at]``( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename CompletionCondition> + std::size_t ``[link boost_asio.reference.read_at.overload2 read_at]``( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + CompletionCondition completion_condition); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename CompletionCondition> + std::size_t ``[link boost_asio.reference.read_at.overload3 read_at]``( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + CompletionCondition completion_condition, + boost::system::error_code & ec); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename Allocator> + std::size_t ``[link boost_asio.reference.read_at.overload4 read_at]``( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename Allocator, + typename CompletionCondition> + std::size_t ``[link boost_asio.reference.read_at.overload5 read_at]``( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename Allocator, + typename CompletionCondition> + std::size_t ``[link boost_asio.reference.read_at.overload6 read_at]``( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition, + boost::system::error_code & ec); + + +[section:overload1 read_at (1 of 6 overloads)] + +Attempt to read a certain amount of data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_at( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers); + + +This function is used to read a certain number of bytes of data from a random access device at the specified offset. The call will block until one of the following conditions is true: + + +* The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* An error occurred. + +This operation is implemented in terms of one or more calls to the device's read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the SyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[buffers][One or more buffers into which the data will be read. The sum of the buffer sizes indicates the maximum number of bytes to read from the device.]] + +] + +[heading Return Value] + +The number of bytes transferred. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::read_at(d, 42, boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + +[heading Remarks] + +This overload is equivalent to calling: + + boost::asio::read_at( + d, 42, buffers, + boost::asio::transfer_all()); + + + + + + +[endsect] + + + +[section:overload2 read_at (2 of 6 overloads)] + +Attempt to read a certain amount of data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename CompletionCondition> + std::size_t read_at( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + CompletionCondition completion_condition); + + +This function is used to read a certain number of bytes of data from a random access device at the specified offset. The call will block until one of the following conditions is true: + + +* The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the SyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[buffers][One or more buffers into which the data will be read. The sum of the buffer sizes indicates the maximum number of bytes to read from the device.]] + +[[completion_condition][The function object to be called to determine whether the read operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest read_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the read operation is complete. False indicates that further calls to the device's read\_some\_at function are required.]] + +] + +[heading Return Value] + +The number of bytes transferred. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::read_at(d, 42, boost::asio::buffer(data, size), + boost::asio::transfer_at_least(32)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload3 read_at (3 of 6 overloads)] + +Attempt to read a certain amount of data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename CompletionCondition> + std::size_t read_at( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + CompletionCondition completion_condition, + boost::system::error_code & ec); + + +This function is used to read a certain number of bytes of data from a random access device at the specified offset. The call will block until one of the following conditions is true: + + +* The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the SyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[buffers][One or more buffers into which the data will be read. The sum of the buffer sizes indicates the maximum number of bytes to read from the device.]] + +[[completion_condition][The function object to be called to determine whether the read operation is complete. The signature of the function object must be: +`` + bool completion_condition( + const boost::system::error_code& error, // Result of latest read_some_at + // operation. + + std::size_t bytes_transferred // Number of bytes transferred + // so far. + ); + +`` +A return value of true indicates that the read operation is complete. False indicates that further calls to the device's read\_some\_at function are required.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes read. If an error occurs, returns the total number of bytes successfully transferred prior to the error. + + + +[endsect] + + + +[section:overload4 read_at (4 of 6 overloads)] + +Attempt to read a certain amount of data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename Allocator> + std::size_t read_at( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b); + + +This function is used to read a certain number of bytes of data from a random access device at the specified offset. The call will block until one of the following conditions is true: + + +* An error occurred. + +This operation is implemented in terms of one or more calls to the device's read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the SyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[b][The basic\_streambuf object into which the data will be read.]] + +] + +[heading Return Value] + +The number of bytes transferred. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +This overload is equivalent to calling: + + boost::asio::read_at( + d, 42, b, + boost::asio::transfer_all()); + + + + + + +[endsect] + + + +[section:overload5 read_at (5 of 6 overloads)] + +Attempt to read a certain amount of data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename Allocator, + typename CompletionCondition> + std::size_t read_at( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition); + + +This function is used to read a certain number of bytes of data from a random access device at the specified offset. The call will block until one of the following conditions is true: + + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the SyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[b][The basic\_streambuf object into which the data will be read.]] + +[[completion_condition][The function object to be called to determine whether the read operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest read_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the read operation is complete. False indicates that further calls to the device's read\_some\_at function are required.]] + +] + +[heading Return Value] + +The number of bytes transferred. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload6 read_at (6 of 6 overloads)] + +Attempt to read a certain amount of data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessReadDevice SyncRandomAccessReadDevice]``, + typename Allocator, + typename CompletionCondition> + std::size_t read_at( + SyncRandomAccessReadDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition, + boost::system::error_code & ec); + + +This function is used to read a certain number of bytes of data from a random access device at the specified offset. The call will block until one of the following conditions is true: + + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's read\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device from which the data is to be read. The type must support the SyncRandomAccessReadDevice concept.]] + +[[offset][The offset at which the data will be read.]] + +[[b][The basic\_streambuf object into which the data will be read.]] + +[[completion_condition][The function object to be called to determine whether the read operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest read_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the read operation is complete. False indicates that further calls to the device's read\_some\_at function are required.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes read. If an error occurs, returns the total number of bytes successfully transferred prior to the error. + + + [endsect] @@ -32122,8 +47541,29 @@ Read data into a streambuf until a delimiter is encountered. const boost::regex & expr, boost::system::error_code & ec); + template< + typename ``[link boost_asio.reference.SyncReadStream SyncReadStream]``, + typename Allocator, + typename ``[link boost_asio.reference.MatchCondition MatchCondition]``> + std::size_t ``[link boost_asio.reference.read_until.overload7 read_until]``( + SyncReadStream & s, + boost::asio::basic_streambuf< Allocator > & b, + MatchCondition match_condition, + typename boost::enable_if< is_match_condition< MatchCondition > >::type * = 0); -[section:overload1 read_until (1 of 6 overloads)] + template< + typename ``[link boost_asio.reference.SyncReadStream SyncReadStream]``, + typename Allocator, + typename ``[link boost_asio.reference.MatchCondition MatchCondition]``> + std::size_t ``[link boost_asio.reference.read_until.overload8 read_until]``( + SyncReadStream & s, + boost::asio::basic_streambuf< Allocator > & b, + MatchCondition match_condition, + boost::system::error_code & ec, + typename boost::enable_if< is_match_condition< MatchCondition > >::type * = 0); + + +[section:overload1 read_until (1 of 8 overloads)] Read data into a streambuf until a delimiter is encountered. @@ -32191,7 +47631,7 @@ To read data into a streambuf until a newline is encountered: -[section:overload2 read_until (2 of 6 overloads)] +[section:overload2 read_until (2 of 8 overloads)] Read data into a streambuf until a delimiter is encountered. @@ -32240,7 +47680,7 @@ The number of bytes in the streambuf's get area up to and including the delimite -[section:overload3 read_until (3 of 6 overloads)] +[section:overload3 read_until (3 of 8 overloads)] Read data into a streambuf until a delimiter is encountered. @@ -32308,7 +47748,7 @@ To read data into a streambuf until a newline is encountered: -[section:overload4 read_until (4 of 6 overloads)] +[section:overload4 read_until (4 of 8 overloads)] Read data into a streambuf until a delimiter is encountered. @@ -32357,7 +47797,7 @@ The number of bytes in the streambuf's get area up to and including the delimite -[section:overload5 read_until (5 of 6 overloads)] +[section:overload5 read_until (5 of 8 overloads)] Read data into a streambuf until a regular expression is located. @@ -32425,7 +47865,7 @@ To read data into a streambuf until a CR-LF sequence is encountered: -[section:overload6 read_until (6 of 6 overloads)] +[section:overload6 read_until (6 of 8 overloads)] Read data into a streambuf until a regular expression is located. @@ -32473,6 +47913,1489 @@ The number of bytes in the streambuf's get area up to and including the substrin [endsect] + +[section:overload7 read_until (7 of 8 overloads)] + +Read data into a streambuf until a function object indicates a match. + + template< + typename ``[link boost_asio.reference.SyncReadStream SyncReadStream]``, + typename Allocator, + typename ``[link boost_asio.reference.MatchCondition MatchCondition]``> + std::size_t read_until( + SyncReadStream & s, + boost::asio::basic_streambuf< Allocator > & b, + MatchCondition match_condition, + typename boost::enable_if< is_match_condition< MatchCondition > >::type * = 0); + + +This function is used to read data into the specified streambuf until a user-defined match condition function object, when applied to the data contained in the streambuf, indicates a successful match. The call will block until one of the following conditions is true: + + +* The match condition function object returns a std::pair where the second element evaluates to true. + +* An error occurred. + +This operation is implemented in terms of zero or more calls to the stream's read\_some function. If the match condition function object already indicates a match, the function returns immediately. + + +[heading Parameters] + + +[variablelist + +[[s][The stream from which the data is to be read. The type must support the SyncReadStream concept.]] + +[[b][A streambuf object into which the data will be read.]] + +[[match_condition][The function object to be called to determine whether a match exists. The signature of the function object must be: +`` + pair match_condition(iterator begin, iterator end); + +`` +where iterator represents the type: +`` + buffers_iterator::const_buffers_type> + +`` +The iterator parameters begin and end define the range of bytes to be scanned to determine whether there is a match. The first member of the return value is an iterator marking one-past-the-end of the bytes that have been consumed by the match function. This iterator is used to calculate the begin parameter for any subsequent invocation of the match condition. The second member of the return value is true if a match has been found, false otherwise.]] + +] + +[heading Return Value] + +The number of bytes in the streambuf's get area that have been fully consumed by the match function. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +The default implementation of the is_match_condition type trait evaluates to true for function pointers and function objects with a result\_type typedef. It must be specialised for other user-defined function objects. + +[heading Examples] + +To read data into a streambuf until whitespace is encountered: + + typedef boost::asio::buffers_iterator< + boost::asio::streambuf::const_buffers_type> iterator; + + std::pair + match_whitespace(iterator begin, iterator end) + { + iterator i = begin; + while (i != end) + if (std::isspace(*i++)) + return std::make_pair(i, true); + return std::make_pair(i, false); + } + ... + boost::asio::streambuf b; + boost::asio::read_until(s, b, match_whitespace); + + + + +To read data into a streambuf until a matching character is found: + + class match_char + { + public: + explicit match_char(char c) : c_(c) {} + + template + std::pair operator()( + Iterator begin, Iterator end) const + { + Iterator i = begin; + while (i != end) + if (c_ == *i++) + return std::make_pair(i, true); + return std::make_pair(i, false); + } + + private: + char c_; + }; + + namespace asio { + template <> struct is_match_condition + : public boost::true_type {}; + } // namespace asio + ... + boost::asio::streambuf b; + boost::asio::read_until(s, b, match_char('a')); + + + + + +[endsect] + + + +[section:overload8 read_until (8 of 8 overloads)] + +Read data into a streambuf until a function object indicates a match. + + template< + typename ``[link boost_asio.reference.SyncReadStream SyncReadStream]``, + typename Allocator, + typename ``[link boost_asio.reference.MatchCondition MatchCondition]``> + std::size_t read_until( + SyncReadStream & s, + boost::asio::basic_streambuf< Allocator > & b, + MatchCondition match_condition, + boost::system::error_code & ec, + typename boost::enable_if< is_match_condition< MatchCondition > >::type * = 0); + + +This function is used to read data into the specified streambuf until a user-defined match condition function object, when applied to the data contained in the streambuf, indicates a successful match. The call will block until one of the following conditions is true: + + +* The match condition function object returns a std::pair where the second element evaluates to true. + +* An error occurred. + +This operation is implemented in terms of zero or more calls to the stream's read\_some function. If the match condition function object already indicates a match, the function returns immediately. + + +[heading Parameters] + + +[variablelist + +[[s][The stream from which the data is to be read. The type must support the SyncReadStream concept.]] + +[[b][A streambuf object into which the data will be read.]] + +[[match_condition][The function object to be called to determine whether a match exists. The signature of the function object must be: +`` + pair match_condition(iterator begin, iterator end); + +`` +where iterator represents the type: +`` + buffers_iterator::const_buffers_type> + +`` +The iterator parameters begin and end define the range of bytes to be scanned to determine whether there is a match. The first member of the return value is an iterator marking one-past-the-end of the bytes that have been consumed by the match function. This iterator is used to calculate the begin parameter for any subsequent invocation of the match condition. The second member of the return value is true if a match has been found, false otherwise.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes in the streambuf's get area that have been fully consumed by the match function. Returns 0 if an error occurred. + +[heading Remarks] + +The default implementation of the is_match_condition type trait evaluates to true for function pointers and function objects with a result\_type typedef. It must be specialised for other user-defined function objects. + + + +[endsect] + + +[endsect] + + +[section:serial_port serial_port] + +Typedef for the typical usage of a serial port. + + typedef basic_serial_port serial_port; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.basic_serial_port.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.lowest_layer_type [*lowest_layer_type]]] + [A basic_serial_port is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.native_type [*native_type]]] + [The native representation of a serial port. ] + + ] + + [ + + [[link boost_asio.reference.basic_serial_port.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_serial_port.assign [*assign]]] + [Assign an existing native serial port to the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.basic_serial_port [*basic_serial_port]]] + [Construct a basic_serial_port without opening it. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.close [*close]]] + [Close the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.get_option [*get_option]]] + [Get an option from the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.is_open [*is_open]]] + [Determine whether the serial port is open. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.native [*native]]] + [Get the native serial port representation. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.open [*open]]] + [Open the serial port using the specified device name. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.read_some [*read_some]]] + [Read some data from the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.send_break [*send_break]]] + [Send a break sequence to the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.set_option [*set_option]]] + [Set an option on the serial port. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.write_some [*write_some]]] + [Write some data to the serial port. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_serial_port.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.basic_serial_port.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The basic_serial_port class template provides functionality that is common to all serial ports. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + +[section:serial_port_base serial_port_base] + +The serial_port_base class is used as a base for the basic_serial_port class template so that we have a common place to define the serial port options. + + class serial_port_base + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.serial_port_base__baud_rate [*baud_rate]]] + [Serial port option to permit changing the baud rate. ] + + ] + + [ + + [[link boost_asio.reference.serial_port_base__character_size [*character_size]]] + [Serial port option to permit changing the character size. ] + + ] + + [ + + [[link boost_asio.reference.serial_port_base__flow_control [*flow_control]]] + [Serial port option to permit changing the flow control. ] + + ] + + [ + + [[link boost_asio.reference.serial_port_base__parity [*parity]]] + [Serial port option to permit changing the parity. ] + + ] + + [ + + [[link boost_asio.reference.serial_port_base__stop_bits [*stop_bits]]] + [Serial port option to permit changing the number of stop bits. ] + + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.serial_port_base._serial_port_base [*~serial_port_base]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + + +[section:_serial_port_base serial_port_base::~serial_port_base] + +Protected destructor to prevent deletion through this type. + + ~serial_port_base(); + + + +[endsect] + + + +[endsect] + +[section:serial_port_base__baud_rate serial_port_base::baud_rate] + +Serial port option to permit changing the baud rate. + + class baud_rate + + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.serial_port_base__baud_rate.baud_rate [*baud_rate]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__baud_rate.load [*load]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__baud_rate.store [*store]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__baud_rate.value [*value]]] + [] + ] + +] + +Implements changing the baud rate for a given serial port. + + +[section:baud_rate serial_port_base::baud_rate::baud_rate] + + + + baud_rate( + unsigned int rate = 0); + + + +[endsect] + + + +[section:load serial_port_base::baud_rate::load] + + + + boost::system::error_code load( + const BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:store serial_port_base::baud_rate::store] + + + + boost::system::error_code store( + BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:value serial_port_base::baud_rate::value] + + + + unsigned int value() const; + + + +[endsect] + + + +[endsect] + +[section:serial_port_base__character_size serial_port_base::character_size] + +Serial port option to permit changing the character size. + + class character_size + + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.serial_port_base__character_size.character_size [*character_size]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__character_size.load [*load]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__character_size.store [*store]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__character_size.value [*value]]] + [] + ] + +] + +Implements changing the character size for a given serial port. + + +[section:character_size serial_port_base::character_size::character_size] + + + + character_size( + unsigned int t = 8); + + + +[endsect] + + + +[section:load serial_port_base::character_size::load] + + + + boost::system::error_code load( + const BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:store serial_port_base::character_size::store] + + + + boost::system::error_code store( + BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:value serial_port_base::character_size::value] + + + + unsigned int value() const; + + + +[endsect] + + + +[endsect] + +[section:serial_port_base__flow_control serial_port_base::flow_control] + +Serial port option to permit changing the flow control. + + class flow_control + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.serial_port_base__flow_control.type [*type]]] + [] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.serial_port_base__flow_control.flow_control [*flow_control]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__flow_control.load [*load]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__flow_control.store [*store]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__flow_control.value [*value]]] + [] + ] + +] + +Implements changing the flow control for a given serial port. + + +[section:flow_control serial_port_base::flow_control::flow_control] + + + + flow_control( + type t = none); + + + +[endsect] + + + +[section:load serial_port_base::flow_control::load] + + + + boost::system::error_code load( + const BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:store serial_port_base::flow_control::store] + + + + boost::system::error_code store( + BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:type serial_port_base::flow_control::type] + + + + enum type + +[heading Values] +[variablelist + + [ + [none] + [] + ] + + [ + [software] + [] + ] + + [ + [hardware] + [] + ] + +] + + + +[endsect] + + + +[section:value serial_port_base::flow_control::value] + + + + type value() const; + + + +[endsect] + + + +[endsect] + +[section:serial_port_base__parity serial_port_base::parity] + +Serial port option to permit changing the parity. + + class parity + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.serial_port_base__parity.type [*type]]] + [] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.serial_port_base__parity.load [*load]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__parity.parity [*parity]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__parity.store [*store]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__parity.value [*value]]] + [] + ] + +] + +Implements changing the parity for a given serial port. + + +[section:load serial_port_base::parity::load] + + + + boost::system::error_code load( + const BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:parity serial_port_base::parity::parity] + + + + parity( + type t = none); + + + +[endsect] + + + +[section:store serial_port_base::parity::store] + + + + boost::system::error_code store( + BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:type serial_port_base::parity::type] + + + + enum type + +[heading Values] +[variablelist + + [ + [none] + [] + ] + + [ + [odd] + [] + ] + + [ + [even] + [] + ] + +] + + + +[endsect] + + + +[section:value serial_port_base::parity::value] + + + + type value() const; + + + +[endsect] + + + +[endsect] + +[section:serial_port_base__stop_bits serial_port_base::stop_bits] + +Serial port option to permit changing the number of stop bits. + + class stop_bits + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.serial_port_base__stop_bits.type [*type]]] + [] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.serial_port_base__stop_bits.load [*load]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__stop_bits.stop_bits [*stop_bits]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__stop_bits.store [*store]]] + [] + ] + + [ + [[link boost_asio.reference.serial_port_base__stop_bits.value [*value]]] + [] + ] + +] + +Implements changing the number of stop bits for a given serial port. + + +[section:load serial_port_base::stop_bits::load] + + + + boost::system::error_code load( + const BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:stop_bits serial_port_base::stop_bits::stop_bits] + + + + stop_bits( + type t = one); + + + +[endsect] + + + +[section:store serial_port_base::stop_bits::store] + + + + boost::system::error_code store( + BOOST_ASIO_OPTION_STORAGE & storage, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:type serial_port_base::stop_bits::type] + + + + enum type + +[heading Values] +[variablelist + + [ + [one] + [] + ] + + [ + [onepointfive] + [] + ] + + [ + [two] + [] + ] + +] + + + +[endsect] + + + +[section:value serial_port_base::stop_bits::value] + + + + type value() const; + + + +[endsect] + + + +[endsect] + +[section:serial_port_service serial_port_service] + +Default service implementation for a serial port. + + class serial_port_service : + public io_service::service + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.serial_port_service.implementation_type [*implementation_type]]] + [The type of a serial port implementation. ] + + ] + + [ + + [[link boost_asio.reference.serial_port_service.native_type [*native_type]]] + [The native handle type. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.serial_port_service.assign [*assign]]] + [Assign an existing native handle to a serial port. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.close [*close]]] + [Close a serial port implementation. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.construct [*construct]]] + [Construct a new serial port implementation. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.destroy [*destroy]]] + [Destroy a serial port implementation. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.get_io_service [*get_io_service]]] + [Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.get_option [*get_option]]] + [Get a serial port option. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.native [*native]]] + [Get the native handle implementation. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.open [*open]]] + [Open a serial port. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.read_some [*read_some]]] + [Read some data from the stream. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.send_break [*send_break]]] + [Send a break sequence to the serial port. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.serial_port_service [*serial_port_service]]] + [Construct a new serial port service for the specified io_service. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.set_option [*set_option]]] + [Set a serial port option. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.shutdown_service [*shutdown_service]]] + [Destroy all user-defined handler objects owned by the service. ] + ] + + [ + [[link boost_asio.reference.serial_port_service.write_some [*write_some]]] + [Write the given data to the stream. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.serial_port_service.id [*id]]] + [The unique service identifier. ] + ] + +] + + +[section:assign serial_port_service::assign] + +Assign an existing native handle to a serial port. + + boost::system::error_code assign( + implementation_type & impl, + const native_type & native_handle, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:async_read_some serial_port_service::async_read_some] + +Start an asynchronous read. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_some( + implementation_type & impl, + const MutableBufferSequence & buffers, + ReadHandler handler); + + + +[endsect] + + + +[section:async_write_some serial_port_service::async_write_some] + +Start an asynchronous write. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_some( + implementation_type & impl, + const ConstBufferSequence & buffers, + WriteHandler handler); + + + +[endsect] + + + +[section:cancel serial_port_service::cancel] + +Cancel all asynchronous operations associated with the handle. + + boost::system::error_code cancel( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:close serial_port_service::close] + +Close a serial port implementation. + + boost::system::error_code close( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:construct serial_port_service::construct] + +Construct a new serial port implementation. + + void construct( + implementation_type & impl); + + + +[endsect] + + + +[section:destroy serial_port_service::destroy] + +Destroy a serial port implementation. + + void destroy( + implementation_type & impl); + + + +[endsect] + + + +[section:get_io_service serial_port_service::get_io_service] + + +['Inherited from io_service.] + +Get the io_service object that owns the service. + + boost::asio::io_service & get_io_service(); + + + +[endsect] + + + +[section:get_option serial_port_service::get_option] + +Get a serial port option. + + template< + typename ``[link boost_asio.reference.GettableSerialPortOption GettableSerialPortOption]``> + boost::system::error_code get_option( + const implementation_type & impl, + GettableSerialPortOption & option, + boost::system::error_code & ec) const; + + + +[endsect] + + + +[section:id serial_port_service::id] + +The unique service identifier. + + static boost::asio::io_service::id id; + + + +[endsect] + + + +[section:implementation_type serial_port_service::implementation_type] + +The type of a serial port implementation. + + typedef implementation_defined implementation_type; + + + + +[endsect] + + + +[section:io_service serial_port_service::io_service] + + +['Inherited from io_service.] + +(Deprecated: use get_io_service().) Get the io_service object that owns the service. + + boost::asio::io_service & io_service(); + + + +[endsect] + + + +[section:is_open serial_port_service::is_open] + +Determine whether the handle is open. + + bool is_open( + const implementation_type & impl) const; + + + +[endsect] + + + +[section:native serial_port_service::native] + +Get the native handle implementation. + + native_type native( + implementation_type & impl); + + + +[endsect] + + + +[section:native_type serial_port_service::native_type] + +The native handle type. + + typedef implementation_defined native_type; + + + + +[endsect] + + + +[section:open serial_port_service::open] + +Open a serial port. + + boost::system::error_code open( + implementation_type & impl, + const std::string & device, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:read_some serial_port_service::read_some] + +Read some data from the stream. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + implementation_type & impl, + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:send_break serial_port_service::send_break] + +Send a break sequence to the serial port. + + boost::system::error_code send_break( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:serial_port_service serial_port_service::serial_port_service] + +Construct a new serial port service for the specified io_service. + + serial_port_service( + boost::asio::io_service & io_service); + + + +[endsect] + + + +[section:set_option serial_port_service::set_option] + +Set a serial port option. + + template< + typename ``[link boost_asio.reference.SettableSerialPortOption SettableSerialPortOption]``> + boost::system::error_code set_option( + implementation_type & impl, + const SettableSerialPortOption & option, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:shutdown_service serial_port_service::shutdown_service] + +Destroy all user-defined handler objects owned by the service. + + void shutdown_service(); + + + +[endsect] + + + +[section:write_some serial_port_service::write_some] + +Write the given data to the stream. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + implementation_type & impl, + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + + +[endsect] + + + [endsect] [section:service_already_exists service_already_exists] @@ -33152,6 +50075,17 @@ The socket_base class is used as a base for the basic_stream_socket and basic_da ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.socket_base._socket_base [*~socket_base]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -33772,6 +50706,18 @@ Different ways a socket may be shutdown. +[section:_socket_base socket_base::~socket_base] + +Protected destructor to prevent deletion through this type. + + ~socket_base(); + + + +[endsect] + + + [endsect] [section:ssl__basic_context ssl::basic_context] @@ -35393,6 +52339,17 @@ The context_base class is used as a base for the basic_context class template so ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ssl__context_base._context_base [*~context_base]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [heading Data Members] [table [[Name][Description]] @@ -35710,6 +52667,18 @@ Verify the peer. +[section:_context_base ssl::context_base::~context_base] + +Protected destructor to prevent deletion through this type. + + ~context_base(); + + + +[endsect] + + + [endsect] [section:ssl__context_service ssl::context_service] @@ -37187,6 +54156,17 @@ The stream_base class is used as a base for the boost::asio::ssl::stream class t ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.ssl__stream_base._stream_base [*~stream_base]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + [section:handshake_type ssl::stream_base::handshake_type] @@ -37215,6 +54195,18 @@ Different handshake types. +[section:_stream_base ssl::stream_base::~stream_base] + +Protected destructor to prevent deletion through this type. + + ~stream_base(); + + + +[endsect] + + + [endsect] [section:ssl__stream_service ssl::stream_service] @@ -38460,6 +55452,27 @@ Typedef for the typical usage of basic_streambuf. ] +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.basic_streambuf.overflow [*overflow]]] + [] + ] + + [ + [[link boost_asio.reference.basic_streambuf.reserve [*reserve]]] + [] + ] + + [ + [[link boost_asio.reference.basic_streambuf.underflow [*underflow]]] + [] + ] + +] + [endsect] @@ -38727,6 +55740,3886 @@ The service interface implementing the specified service type. Ownership of the [endsect] +[section:windows__basic_handle windows::basic_handle] + +Provides Windows handle functionality. + + template< + typename ``[link boost_asio.reference.HandleService HandleService]``> + class basic_handle : + public basic_io_object< HandleService > + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__basic_handle.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.lowest_layer_type [*lowest_layer_type]]] + [A basic_handle is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.native_type [*native_type]]] + [The native representation of a handle. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle.assign [*assign]]] + [Assign an existing native handle to the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.basic_handle [*basic_handle]]] + [Construct a basic_handle without opening it. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.close [*close]]] + [Close the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.native [*native]]] + [Get the native handle representation. ] + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle._basic_handle [*~basic_handle]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The windows::basic_handle class template provides the ability to wrap a Windows handle. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + +[section:assign windows::basic_handle::assign] + +Assign an existing native handle to the handle. + + void ``[link boost_asio.reference.windows__basic_handle.assign.overload1 assign]``( + const native_type & native_handle); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_handle.assign.overload2 assign]``( + const native_type & native_handle, + boost::system::error_code & ec); + + +[section:overload1 windows::basic_handle::assign (1 of 2 overloads)] + +Assign an existing native handle to the handle. + + void assign( + const native_type & native_handle); + + + +[endsect] + + + +[section:overload2 windows::basic_handle::assign (2 of 2 overloads)] + +Assign an existing native handle to the handle. + + boost::system::error_code assign( + const native_type & native_handle, + boost::system::error_code & ec); + + + +[endsect] + + +[endsect] + +[section:basic_handle windows::basic_handle::basic_handle] + +Construct a basic_handle without opening it. + + ``[link boost_asio.reference.windows__basic_handle.basic_handle.overload1 basic_handle]``( + boost::asio::io_service & io_service); + + ``[link boost_asio.reference.windows__basic_handle.basic_handle.overload2 basic_handle]``( + boost::asio::io_service & io_service, + const native_type & native_handle); + + +[section:overload1 windows::basic_handle::basic_handle (1 of 2 overloads)] + +Construct a basic_handle without opening it. + + basic_handle( + boost::asio::io_service & io_service); + + +This constructor creates a handle without opening it. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the handle will use to dispatch handlers for any asynchronous operations performed on the handle. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_handle::basic_handle (2 of 2 overloads)] + +Construct a basic_handle on an existing native handle. + + basic_handle( + boost::asio::io_service & io_service, + const native_type & native_handle); + + +This constructor creates a handle object to hold an existing native handle. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the handle will use to dispatch handlers for any asynchronous operations performed on the handle.]] + +[[native_handle][A native handle.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + +[endsect] + +[section:cancel windows::basic_handle::cancel] + +Cancel all asynchronous operations associated with the handle. + + void ``[link boost_asio.reference.windows__basic_handle.cancel.overload1 cancel]``(); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_handle.cancel.overload2 cancel]``( + boost::system::error_code & ec); + + +[section:overload1 windows::basic_handle::cancel (1 of 2 overloads)] + +Cancel all asynchronous operations associated with the handle. + + void cancel(); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_handle::cancel (2 of 2 overloads)] + +Cancel all asynchronous operations associated with the handle. + + boost::system::error_code cancel( + boost::system::error_code & ec); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + +[section:close windows::basic_handle::close] + +Close the handle. + + void ``[link boost_asio.reference.windows__basic_handle.close.overload1 close]``(); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_handle.close.overload2 close]``( + boost::system::error_code & ec); + + +[section:overload1 windows::basic_handle::close (1 of 2 overloads)] + +Close the handle. + + void close(); + + +This function is used to close the handle. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_handle::close (2 of 2 overloads)] + +Close the handle. + + boost::system::error_code close( + boost::system::error_code & ec); + + +This function is used to close the handle. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:get_io_service windows::basic_handle::get_io_service] + + +['Inherited from basic_io_object.] + +Get the io_service associated with the object. + + boost::asio::io_service & get_io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:implementation windows::basic_handle::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + +[section:implementation_type windows::basic_handle::implementation_type] + + +['Inherited from basic_io_object.] + +The underlying implementation type of I/O object. + + typedef service_type::implementation_type implementation_type; + + + + +[endsect] + + + +[section:io_service windows::basic_handle::io_service] + + +['Inherited from basic_io_object.] + +(Deprecated: use get_io_service().) Get the io_service associated with the object. + + boost::asio::io_service & io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:is_open windows::basic_handle::is_open] + +Determine whether the handle is open. + + bool is_open() const; + + + +[endsect] + + + +[section:lowest_layer windows::basic_handle::lowest_layer] + +Get a reference to the lowest layer. + + lowest_layer_type & lowest_layer(); + + +This function returns a reference to the lowest layer in a stack of layers. Since a basic_handle cannot contain any further layers, it simply returns a reference to itself. + + +[heading Return Value] + +A reference to the lowest layer in the stack of layers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:lowest_layer_type windows::basic_handle::lowest_layer_type] + +A basic_handle is always the lowest layer. + + typedef basic_handle< HandleService > lowest_layer_type; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__basic_handle.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.lowest_layer_type [*lowest_layer_type]]] + [A basic_handle is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.native_type [*native_type]]] + [The native representation of a handle. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle.assign [*assign]]] + [Assign an existing native handle to the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.basic_handle [*basic_handle]]] + [Construct a basic_handle without opening it. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.close [*close]]] + [Close the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.native [*native]]] + [Get the native handle representation. ] + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle._basic_handle [*~basic_handle]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The windows::basic_handle class template provides the ability to wrap a Windows handle. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:native windows::basic_handle::native] + +Get the native handle representation. + + native_type native(); + + +This function may be used to obtain the underlying representation of the handle. This is intended to allow access to native handle functionality that is not otherwise provided. + + +[endsect] + + + +[section:native_type windows::basic_handle::native_type] + +The native representation of a handle. + + typedef HandleService::native_type native_type; + + + + +[endsect] + + + +[section:service windows::basic_handle::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + +[section:service_type windows::basic_handle::service_type] + + +['Inherited from basic_io_object.] + +The type of the service that will be used to provide I/O operations. + + typedef HandleService service_type; + + + + +[endsect] + + + +[section:_basic_handle windows::basic_handle::~basic_handle] + +Protected destructor to prevent deletion through this type. + + ~basic_handle(); + + + +[endsect] + + + +[endsect] + +[section:windows__basic_random_access_handle windows::basic_random_access_handle] + +Provides random-access handle functionality. + + template< + typename ``[link boost_asio.reference.RandomAccessHandleService RandomAccessHandleService]`` = random_access_handle_service> + class basic_random_access_handle : + public windows::basic_handle< RandomAccessHandleService > + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__basic_random_access_handle.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_random_access_handle.lowest_layer_type [*lowest_layer_type]]] + [A basic_handle is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_random_access_handle.native_type [*native_type]]] + [The native representation of a handle. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_random_access_handle.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.assign [*assign]]] + [Assign an existing native handle to the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.async_read_some_at [*async_read_some_at]]] + [Start an asynchronous read at the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.async_write_some_at [*async_write_some_at]]] + [Start an asynchronous write at the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.basic_random_access_handle [*basic_random_access_handle]]] + [Construct a basic_random_access_handle without opening it. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.close [*close]]] + [Close the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.native [*native]]] + [Get the native handle representation. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.read_some_at [*read_some_at]]] + [Read some data from the handle at the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.write_some_at [*write_some_at]]] + [Write some data to the handle at the specified offset. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The windows::basic_random_access_handle class template provides asynchronous and blocking random-access handle functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + +[section:assign windows::basic_random_access_handle::assign] + +Assign an existing native handle to the handle. + + void ``[link boost_asio.reference.windows__basic_random_access_handle.assign.overload1 assign]``( + const native_type & native_handle); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_random_access_handle.assign.overload2 assign]``( + const native_type & native_handle, + boost::system::error_code & ec); + + +[section:overload1 windows::basic_random_access_handle::assign (1 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Assign an existing native handle to the handle. + + void assign( + const native_type & native_handle); + + + +[endsect] + + + +[section:overload2 windows::basic_random_access_handle::assign (2 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Assign an existing native handle to the handle. + + boost::system::error_code assign( + const native_type & native_handle, + boost::system::error_code & ec); + + + +[endsect] + + +[endsect] + + +[section:async_read_some_at windows::basic_random_access_handle::async_read_some_at] + +Start an asynchronous read at the specified offset. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_some_at( + boost::uint64_t offset, + const MutableBufferSequence & buffers, + ReadHandler handler); + + +This function is used to asynchronously read data from the random-access handle. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[offset][The offset at which the data will be read.]] + +[[buffers][One or more buffers into which the data will be read. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes read. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The read operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.async_read_at async_read_at] function if you need to ensure that the requested amount of data is read before the asynchronous operation completes. + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + handle.async_read_some_at(42, boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:async_write_some_at windows::basic_random_access_handle::async_write_some_at] + +Start an asynchronous write at the specified offset. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_some_at( + boost::uint64_t offset, + const ConstBufferSequence & buffers, + WriteHandler handler); + + +This function is used to asynchronously write data to the random-access handle. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[offset][The offset at which the data will be written.]] + +[[buffers][One or more data buffers to be written to the handle. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes written. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The write operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.async_write_at async_write_at] function if you need to ensure that all data is written before the asynchronous operation completes. + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + handle.async_write_some_at(42, boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + +[section:basic_random_access_handle windows::basic_random_access_handle::basic_random_access_handle] + +Construct a basic_random_access_handle without opening it. + + ``[link boost_asio.reference.windows__basic_random_access_handle.basic_random_access_handle.overload1 basic_random_access_handle]``( + boost::asio::io_service & io_service); + + ``[link boost_asio.reference.windows__basic_random_access_handle.basic_random_access_handle.overload2 basic_random_access_handle]``( + boost::asio::io_service & io_service, + const native_type & native_handle); + + +[section:overload1 windows::basic_random_access_handle::basic_random_access_handle (1 of 2 overloads)] + +Construct a basic_random_access_handle without opening it. + + basic_random_access_handle( + boost::asio::io_service & io_service); + + +This constructor creates a random-access handle without opening it. The handle needs to be opened before data can be written to or or read from it. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the random-access handle will use to dispatch handlers for any asynchronous operations performed on the handle. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_random_access_handle::basic_random_access_handle (2 of 2 overloads)] + +Construct a basic_random_access_handle on an existing native handle. + + basic_random_access_handle( + boost::asio::io_service & io_service, + const native_type & native_handle); + + +This constructor creates a random-access handle object to hold an existing native handle. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the random-access handle will use to dispatch handlers for any asynchronous operations performed on the handle.]] + +[[native_handle][The new underlying handle implementation.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + +[endsect] + +[section:cancel windows::basic_random_access_handle::cancel] + +Cancel all asynchronous operations associated with the handle. + + void ``[link boost_asio.reference.windows__basic_random_access_handle.cancel.overload1 cancel]``(); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_random_access_handle.cancel.overload2 cancel]``( + boost::system::error_code & ec); + + +[section:overload1 windows::basic_random_access_handle::cancel (1 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Cancel all asynchronous operations associated with the handle. + + void cancel(); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_random_access_handle::cancel (2 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Cancel all asynchronous operations associated with the handle. + + boost::system::error_code cancel( + boost::system::error_code & ec); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + +[section:close windows::basic_random_access_handle::close] + +Close the handle. + + void ``[link boost_asio.reference.windows__basic_random_access_handle.close.overload1 close]``(); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_random_access_handle.close.overload2 close]``( + boost::system::error_code & ec); + + +[section:overload1 windows::basic_random_access_handle::close (1 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Close the handle. + + void close(); + + +This function is used to close the handle. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_random_access_handle::close (2 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Close the handle. + + boost::system::error_code close( + boost::system::error_code & ec); + + +This function is used to close the handle. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:get_io_service windows::basic_random_access_handle::get_io_service] + + +['Inherited from basic_io_object.] + +Get the io_service associated with the object. + + boost::asio::io_service & get_io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:implementation windows::basic_random_access_handle::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + +[section:implementation_type windows::basic_random_access_handle::implementation_type] + + +['Inherited from basic_io_object.] + +The underlying implementation type of I/O object. + + typedef service_type::implementation_type implementation_type; + + + + +[endsect] + + + +[section:io_service windows::basic_random_access_handle::io_service] + + +['Inherited from basic_io_object.] + +(Deprecated: use get_io_service().) Get the io_service associated with the object. + + boost::asio::io_service & io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:is_open windows::basic_random_access_handle::is_open] + + +['Inherited from windows::basic_handle.] + +Determine whether the handle is open. + + bool is_open() const; + + + +[endsect] + + + +[section:lowest_layer windows::basic_random_access_handle::lowest_layer] + + +['Inherited from windows::basic_handle.] + +Get a reference to the lowest layer. + + lowest_layer_type & lowest_layer(); + + +This function returns a reference to the lowest layer in a stack of layers. Since a basic_handle cannot contain any further layers, it simply returns a reference to itself. + + +[heading Return Value] + +A reference to the lowest layer in the stack of layers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:lowest_layer_type windows::basic_random_access_handle::lowest_layer_type] + + +['Inherited from windows::basic_handle.] + +A basic_handle is always the lowest layer. + + typedef basic_handle< RandomAccessHandleService > lowest_layer_type; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__basic_handle.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.lowest_layer_type [*lowest_layer_type]]] + [A basic_handle is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.native_type [*native_type]]] + [The native representation of a handle. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle.assign [*assign]]] + [Assign an existing native handle to the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.basic_handle [*basic_handle]]] + [Construct a basic_handle without opening it. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.close [*close]]] + [Close the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.native [*native]]] + [Get the native handle representation. ] + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle._basic_handle [*~basic_handle]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The windows::basic_handle class template provides the ability to wrap a Windows handle. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:native windows::basic_random_access_handle::native] + + +['Inherited from windows::basic_handle.] + +Get the native handle representation. + + native_type native(); + + +This function may be used to obtain the underlying representation of the handle. This is intended to allow access to native handle functionality that is not otherwise provided. + + +[endsect] + + + +[section:native_type windows::basic_random_access_handle::native_type] + +The native representation of a handle. + + typedef RandomAccessHandleService::native_type native_type; + + + + +[endsect] + + +[section:read_some_at windows::basic_random_access_handle::read_some_at] + +Read some data from the handle at the specified offset. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.windows__basic_random_access_handle.read_some_at.overload1 read_some_at]``( + boost::uint64_t offset, + const MutableBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.windows__basic_random_access_handle.read_some_at.overload2 read_some_at]``( + boost::uint64_t offset, + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + +[section:overload1 windows::basic_random_access_handle::read_some_at (1 of 2 overloads)] + +Read some data from the handle at the specified offset. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some_at( + boost::uint64_t offset, + const MutableBufferSequence & buffers); + + +This function is used to read data from the random-access handle. The function call will block until one or more bytes of data has been read successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[offset][The offset at which the data will be read.]] + +[[buffers][One or more buffers into which the data will be read.]] + +] + +[heading Return Value] + +The number of bytes read. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. An error code of boost::asio::error::eof indicates that the connection was closed by the peer.]] + +] + +[heading Remarks] + +The read\_some operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.read_at read_at] function if you need to ensure that the requested amount of data is read before the blocking operation completes. + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + handle.read_some_at(42, boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 windows::basic_random_access_handle::read_some_at (2 of 2 overloads)] + +Read some data from the handle at the specified offset. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some_at( + boost::uint64_t offset, + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + +This function is used to read data from the random-access handle. The function call will block until one or more bytes of data has been read successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[offset][The offset at which the data will be read.]] + +[[buffers][One or more buffers into which the data will be read.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes read. Returns 0 if an error occurred. + +[heading Remarks] + +The read\_some operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.read_at read_at] function if you need to ensure that the requested amount of data is read before the blocking operation completes. + + + +[endsect] + + +[endsect] + + +[section:service windows::basic_random_access_handle::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + +[section:service_type windows::basic_random_access_handle::service_type] + + +['Inherited from basic_io_object.] + +The type of the service that will be used to provide I/O operations. + + typedef RandomAccessHandleService service_type; + + + + +[endsect] + + +[section:write_some_at windows::basic_random_access_handle::write_some_at] + +Write some data to the handle at the specified offset. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.windows__basic_random_access_handle.write_some_at.overload1 write_some_at]``( + boost::uint64_t offset, + const ConstBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.windows__basic_random_access_handle.write_some_at.overload2 write_some_at]``( + boost::uint64_t offset, + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + +[section:overload1 windows::basic_random_access_handle::write_some_at (1 of 2 overloads)] + +Write some data to the handle at the specified offset. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some_at( + boost::uint64_t offset, + const ConstBufferSequence & buffers); + + +This function is used to write data to the random-access handle. The function call will block until one or more bytes of the data has been written successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[offset][The offset at which the data will be written.]] + +[[buffers][One or more data buffers to be written to the handle.]] + +] + +[heading Return Value] + +The number of bytes written. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. An error code of boost::asio::error::eof indicates that the connection was closed by the peer.]] + +] + +[heading Remarks] + +The write\_some\_at operation may not write all of the data. Consider using the +[link boost_asio.reference.write_at write_at] function if you need to ensure that all data is written before the blocking operation completes. + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + handle.write_some_at(42, boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 windows::basic_random_access_handle::write_some_at (2 of 2 overloads)] + +Write some data to the handle at the specified offset. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some_at( + boost::uint64_t offset, + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + +This function is used to write data to the random-access handle. The function call will block until one or more bytes of the data has been written successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[offset][The offset at which the data will be written.]] + +[[buffers][One or more data buffers to be written to the handle.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes written. Returns 0 if an error occurred. + +[heading Remarks] + +The write\_some operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.write_at write_at] function if you need to ensure that all data is written before the blocking operation completes. + + + +[endsect] + + +[endsect] + + +[endsect] + +[section:windows__basic_stream_handle windows::basic_stream_handle] + +Provides stream-oriented handle functionality. + + template< + typename ``[link boost_asio.reference.StreamHandleService StreamHandleService]`` = stream_handle_service> + class basic_stream_handle : + public windows::basic_handle< StreamHandleService > + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__basic_stream_handle.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_stream_handle.lowest_layer_type [*lowest_layer_type]]] + [A basic_handle is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_stream_handle.native_type [*native_type]]] + [The native representation of a handle. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_stream_handle.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.assign [*assign]]] + [Assign an existing native handle to the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.basic_stream_handle [*basic_stream_handle]]] + [Construct a basic_stream_handle without opening it. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.close [*close]]] + [Close the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.native [*native]]] + [Get the native handle representation. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.read_some [*read_some]]] + [Read some data from the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.write_some [*write_some]]] + [Write some data to the handle. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The windows::basic_stream_handle class template provides asynchronous and blocking stream-oriented handle functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + +[section:assign windows::basic_stream_handle::assign] + +Assign an existing native handle to the handle. + + void ``[link boost_asio.reference.windows__basic_stream_handle.assign.overload1 assign]``( + const native_type & native_handle); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_stream_handle.assign.overload2 assign]``( + const native_type & native_handle, + boost::system::error_code & ec); + + +[section:overload1 windows::basic_stream_handle::assign (1 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Assign an existing native handle to the handle. + + void assign( + const native_type & native_handle); + + + +[endsect] + + + +[section:overload2 windows::basic_stream_handle::assign (2 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Assign an existing native handle to the handle. + + boost::system::error_code assign( + const native_type & native_handle, + boost::system::error_code & ec); + + + +[endsect] + + +[endsect] + + +[section:async_read_some windows::basic_stream_handle::async_read_some] + +Start an asynchronous read. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_some( + const MutableBufferSequence & buffers, + ReadHandler handler); + + +This function is used to asynchronously read data from the stream handle. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the read operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes read. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The read operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.async_read async_read] function if you need to ensure that the requested amount of data is read before the asynchronous operation completes. + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + handle.async_read_some(boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:async_write_some windows::basic_stream_handle::async_write_some] + +Start an asynchronous write. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_some( + const ConstBufferSequence & buffers, + WriteHandler handler); + + +This function is used to asynchronously write data to the stream handle. The function call always returns immediately. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the handle. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.]] + +[[handler][The handler to be called when the write operation completes. Copies will be made of the handler as required. The function signature of the handler must be: +`` + void handler( + const boost::system::error_code& error, // Result of operation. + std::size_t bytes_transferred // Number of bytes written. + ); + +`` +Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a manner equivalent to using boost::asio::io\_service::post().]] + +] + +[heading Remarks] + +The write operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.async_write async_write] function if you need to ensure that all data is written before the asynchronous operation completes. + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + handle.async_write_some(boost::asio::buffer(data, size), handler); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + +[section:basic_stream_handle windows::basic_stream_handle::basic_stream_handle] + +Construct a basic_stream_handle without opening it. + + ``[link boost_asio.reference.windows__basic_stream_handle.basic_stream_handle.overload1 basic_stream_handle]``( + boost::asio::io_service & io_service); + + ``[link boost_asio.reference.windows__basic_stream_handle.basic_stream_handle.overload2 basic_stream_handle]``( + boost::asio::io_service & io_service, + const native_type & native_handle); + + +[section:overload1 windows::basic_stream_handle::basic_stream_handle (1 of 2 overloads)] + +Construct a basic_stream_handle without opening it. + + basic_stream_handle( + boost::asio::io_service & io_service); + + +This constructor creates a stream handle without opening it. The handle needs to be opened and then connected or accepted before data can be sent or received on it. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the stream handle will use to dispatch handlers for any asynchronous operations performed on the handle. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_stream_handle::basic_stream_handle (2 of 2 overloads)] + +Construct a basic_stream_handle on an existing native handle. + + basic_stream_handle( + boost::asio::io_service & io_service, + const native_type & native_handle); + + +This constructor creates a stream handle object to hold an existing native handle. + + +[heading Parameters] + + +[variablelist + +[[io_service][The io\_service object that the stream handle will use to dispatch handlers for any asynchronous operations performed on the handle.]] + +[[native_handle][The new underlying handle implementation.]] + +] + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + +[endsect] + +[section:cancel windows::basic_stream_handle::cancel] + +Cancel all asynchronous operations associated with the handle. + + void ``[link boost_asio.reference.windows__basic_stream_handle.cancel.overload1 cancel]``(); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_stream_handle.cancel.overload2 cancel]``( + boost::system::error_code & ec); + + +[section:overload1 windows::basic_stream_handle::cancel (1 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Cancel all asynchronous operations associated with the handle. + + void cancel(); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_stream_handle::cancel (2 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Cancel all asynchronous operations associated with the handle. + + boost::system::error_code cancel( + boost::system::error_code & ec); + + +This function causes all outstanding asynchronous read or write operations to finish immediately, and the handlers for cancelled operations will be passed the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + +[section:close windows::basic_stream_handle::close] + +Close the handle. + + void ``[link boost_asio.reference.windows__basic_stream_handle.close.overload1 close]``(); + + boost::system::error_code ``[link boost_asio.reference.windows__basic_stream_handle.close.overload2 close]``( + boost::system::error_code & ec); + + +[section:overload1 windows::basic_stream_handle::close (1 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Close the handle. + + void close(); + + +This function is used to close the handle. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload2 windows::basic_stream_handle::close (2 of 2 overloads)] + + +['Inherited from windows::basic_handle.] + +Close the handle. + + boost::system::error_code close( + boost::system::error_code & ec); + + +This function is used to close the handle. Any asynchronous read or write operations will be cancelled immediately, and will complete with the boost::asio::error::operation\_aborted error. + + +[heading Parameters] + + +[variablelist + +[[ec][Set to indicate what error occurred, if any. ]] + +] + + + +[endsect] + + +[endsect] + + +[section:get_io_service windows::basic_stream_handle::get_io_service] + + +['Inherited from basic_io_object.] + +Get the io_service associated with the object. + + boost::asio::io_service & get_io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:implementation windows::basic_stream_handle::implementation] + + +['Inherited from basic_io_object.] + +The underlying implementation of the I/O object. + + implementation_type implementation; + + + +[endsect] + + + +[section:implementation_type windows::basic_stream_handle::implementation_type] + + +['Inherited from basic_io_object.] + +The underlying implementation type of I/O object. + + typedef service_type::implementation_type implementation_type; + + + + +[endsect] + + + +[section:io_service windows::basic_stream_handle::io_service] + + +['Inherited from basic_io_object.] + +(Deprecated: use get_io_service().) Get the io_service associated with the object. + + boost::asio::io_service & io_service(); + + +This function may be used to obtain the io_service object that the I/O object uses to dispatch handlers for asynchronous operations. + + +[heading Return Value] + +A reference to the io_service object that the I/O object will use to dispatch handlers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:is_open windows::basic_stream_handle::is_open] + + +['Inherited from windows::basic_handle.] + +Determine whether the handle is open. + + bool is_open() const; + + + +[endsect] + + + +[section:lowest_layer windows::basic_stream_handle::lowest_layer] + + +['Inherited from windows::basic_handle.] + +Get a reference to the lowest layer. + + lowest_layer_type & lowest_layer(); + + +This function returns a reference to the lowest layer in a stack of layers. Since a basic_handle cannot contain any further layers, it simply returns a reference to itself. + + +[heading Return Value] + +A reference to the lowest layer in the stack of layers. Ownership is not transferred to the caller. + + + +[endsect] + + + +[section:lowest_layer_type windows::basic_stream_handle::lowest_layer_type] + + +['Inherited from windows::basic_handle.] + +A basic_handle is always the lowest layer. + + typedef basic_handle< StreamHandleService > lowest_layer_type; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__basic_handle.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.lowest_layer_type [*lowest_layer_type]]] + [A basic_handle is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.native_type [*native_type]]] + [The native representation of a handle. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_handle.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle.assign [*assign]]] + [Assign an existing native handle to the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.basic_handle [*basic_handle]]] + [Construct a basic_handle without opening it. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.close [*close]]] + [Close the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.native [*native]]] + [Get the native handle representation. ] + ] + +] + +[heading Protected Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle._basic_handle [*~basic_handle]]] + [Protected destructor to prevent deletion through this type. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_handle.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_handle.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The windows::basic_handle class template provides the ability to wrap a Windows handle. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + + +[section:native windows::basic_stream_handle::native] + + +['Inherited from windows::basic_handle.] + +Get the native handle representation. + + native_type native(); + + +This function may be used to obtain the underlying representation of the handle. This is intended to allow access to native handle functionality that is not otherwise provided. + + +[endsect] + + + +[section:native_type windows::basic_stream_handle::native_type] + +The native representation of a handle. + + typedef StreamHandleService::native_type native_type; + + + + +[endsect] + + +[section:read_some windows::basic_stream_handle::read_some] + +Read some data from the handle. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.windows__basic_stream_handle.read_some.overload1 read_some]``( + const MutableBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t ``[link boost_asio.reference.windows__basic_stream_handle.read_some.overload2 read_some]``( + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + +[section:overload1 windows::basic_stream_handle::read_some (1 of 2 overloads)] + +Read some data from the handle. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + const MutableBufferSequence & buffers); + + +This function is used to read data from the stream handle. The function call will block until one or more bytes of data has been read successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read.]] + +] + +[heading Return Value] + +The number of bytes read. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. An error code of boost::asio::error::eof indicates that the connection was closed by the peer.]] + +] + +[heading Remarks] + +The read\_some operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.read read] function if you need to ensure that the requested amount of data is read before the blocking operation completes. + +[heading Example] + +To read into a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + handle.read_some(boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on reading into multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 windows::basic_stream_handle::read_some (2 of 2 overloads)] + +Read some data from the handle. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + +This function is used to read data from the stream handle. The function call will block until one or more bytes of data has been read successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more buffers into which the data will be read.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes read. Returns 0 if an error occurred. + +[heading Remarks] + +The read\_some operation may not read all of the requested number of bytes. Consider using the +[link boost_asio.reference.read read] function if you need to ensure that the requested amount of data is read before the blocking operation completes. + + + +[endsect] + + +[endsect] + + +[section:service windows::basic_stream_handle::service] + + +['Inherited from basic_io_object.] + +The service associated with the I/O object. + + service_type & service; + + + +[endsect] + + + +[section:service_type windows::basic_stream_handle::service_type] + + +['Inherited from basic_io_object.] + +The type of the service that will be used to provide I/O operations. + + typedef StreamHandleService service_type; + + + + +[endsect] + + +[section:write_some windows::basic_stream_handle::write_some] + +Write some data to the handle. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.windows__basic_stream_handle.write_some.overload1 write_some]``( + const ConstBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.windows__basic_stream_handle.write_some.overload2 write_some]``( + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + +[section:overload1 windows::basic_stream_handle::write_some (1 of 2 overloads)] + +Write some data to the handle. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + const ConstBufferSequence & buffers); + + +This function is used to write data to the stream handle. The function call will block until one or more bytes of the data has been written successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the handle.]] + +] + +[heading Return Value] + +The number of bytes written. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. An error code of boost::asio::error::eof indicates that the connection was closed by the peer.]] + +] + +[heading Remarks] + +The write\_some operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.write write] function if you need to ensure that all data is written before the blocking operation completes. + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + handle.write_some(boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload2 windows::basic_stream_handle::write_some (2 of 2 overloads)] + +Write some data to the handle. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + +This function is used to write data to the stream handle. The function call will block until one or more bytes of the data has been written successfully, or until an error occurs. + + +[heading Parameters] + + +[variablelist + +[[buffers][One or more data buffers to be written to the handle.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes written. Returns 0 if an error occurred. + +[heading Remarks] + +The write\_some operation may not transmit all of the data to the peer. Consider using the +[link boost_asio.reference.write write] function if you need to ensure that all data is written before the blocking operation completes. + + + +[endsect] + + +[endsect] + + +[endsect] + + +[section:windows__random_access_handle windows::random_access_handle] + +Typedef for the typical usage of a random-access handle. + + typedef basic_random_access_handle random_access_handle; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__basic_random_access_handle.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_random_access_handle.lowest_layer_type [*lowest_layer_type]]] + [A basic_handle is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_random_access_handle.native_type [*native_type]]] + [The native representation of a handle. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_random_access_handle.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.assign [*assign]]] + [Assign an existing native handle to the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.async_read_some_at [*async_read_some_at]]] + [Start an asynchronous read at the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.async_write_some_at [*async_write_some_at]]] + [Start an asynchronous write at the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.basic_random_access_handle [*basic_random_access_handle]]] + [Construct a basic_random_access_handle without opening it. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.close [*close]]] + [Close the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.native [*native]]] + [Get the native handle representation. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.read_some_at [*read_some_at]]] + [Read some data from the handle at the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.write_some_at [*write_some_at]]] + [Write some data to the handle at the specified offset. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_random_access_handle.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The windows::basic_random_access_handle class template provides asynchronous and blocking random-access handle functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + +[section:windows__random_access_handle_service windows::random_access_handle_service] + +Default service implementation for a random-access handle. + + class random_access_handle_service : + public io_service::service + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__random_access_handle_service.implementation_type [*implementation_type]]] + [The type of a random-access handle implementation. ] + + ] + + [ + + [[link boost_asio.reference.windows__random_access_handle_service.native_type [*native_type]]] + [The native handle type. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.assign [*assign]]] + [Assign an existing native handle to a random-access handle. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.async_read_some_at [*async_read_some_at]]] + [Start an asynchronous read at the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.async_write_some_at [*async_write_some_at]]] + [Start an asynchronous write at the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.close [*close]]] + [Close a random-access handle implementation. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.construct [*construct]]] + [Construct a new random-access handle implementation. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.destroy [*destroy]]] + [Destroy a random-access handle implementation. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.get_io_service [*get_io_service]]] + [Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.native [*native]]] + [Get the native handle implementation. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.random_access_handle_service [*random_access_handle_service]]] + [Construct a new random-access handle service for the specified io_service. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.read_some_at [*read_some_at]]] + [Read some data from the specified offset. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.shutdown_service [*shutdown_service]]] + [Destroy all user-defined handler objects owned by the service. ] + ] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.write_some_at [*write_some_at]]] + [Write the given data at the specified offset. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__random_access_handle_service.id [*id]]] + [The unique service identifier. ] + ] + +] + + +[section:assign windows::random_access_handle_service::assign] + +Assign an existing native handle to a random-access handle. + + boost::system::error_code assign( + implementation_type & impl, + const native_type & native_handle, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:async_read_some_at windows::random_access_handle_service::async_read_some_at] + +Start an asynchronous read at the specified offset. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_some_at( + implementation_type & impl, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + ReadHandler handler); + + + +[endsect] + + + +[section:async_write_some_at windows::random_access_handle_service::async_write_some_at] + +Start an asynchronous write at the specified offset. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_some_at( + implementation_type & impl, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + WriteHandler handler); + + + +[endsect] + + + +[section:cancel windows::random_access_handle_service::cancel] + +Cancel all asynchronous operations associated with the handle. + + boost::system::error_code cancel( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:close windows::random_access_handle_service::close] + +Close a random-access handle implementation. + + boost::system::error_code close( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:construct windows::random_access_handle_service::construct] + +Construct a new random-access handle implementation. + + void construct( + implementation_type & impl); + + + +[endsect] + + + +[section:destroy windows::random_access_handle_service::destroy] + +Destroy a random-access handle implementation. + + void destroy( + implementation_type & impl); + + + +[endsect] + + + +[section:get_io_service windows::random_access_handle_service::get_io_service] + + +['Inherited from io_service.] + +Get the io_service object that owns the service. + + boost::asio::io_service & get_io_service(); + + + +[endsect] + + + +[section:id windows::random_access_handle_service::id] + +The unique service identifier. + + static boost::asio::io_service::id id; + + + +[endsect] + + + +[section:implementation_type windows::random_access_handle_service::implementation_type] + +The type of a random-access handle implementation. + + typedef implementation_defined implementation_type; + + + + +[endsect] + + + +[section:io_service windows::random_access_handle_service::io_service] + + +['Inherited from io_service.] + +(Deprecated: use get_io_service().) Get the io_service object that owns the service. + + boost::asio::io_service & io_service(); + + + +[endsect] + + + +[section:is_open windows::random_access_handle_service::is_open] + +Determine whether the handle is open. + + bool is_open( + const implementation_type & impl) const; + + + +[endsect] + + + +[section:native windows::random_access_handle_service::native] + +Get the native handle implementation. + + native_type native( + implementation_type & impl); + + + +[endsect] + + + +[section:native_type windows::random_access_handle_service::native_type] + +The native handle type. + + typedef implementation_defined native_type; + + + + +[endsect] + + + +[section:random_access_handle_service windows::random_access_handle_service::random_access_handle_service] + +Construct a new random-access handle service for the specified io_service. + + random_access_handle_service( + boost::asio::io_service & io_service); + + + +[endsect] + + + +[section:read_some_at windows::random_access_handle_service::read_some_at] + +Read some data from the specified offset. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some_at( + implementation_type & impl, + boost::uint64_t offset, + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:shutdown_service windows::random_access_handle_service::shutdown_service] + +Destroy all user-defined handler objects owned by the service. + + void shutdown_service(); + + + +[endsect] + + + +[section:write_some_at windows::random_access_handle_service::write_some_at] + +Write the given data at the specified offset. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some_at( + implementation_type & impl, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + + +[endsect] + + + +[endsect] + + +[section:windows__stream_handle windows::stream_handle] + +Typedef for the typical usage of a stream-oriented handle. + + typedef basic_stream_handle stream_handle; + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__basic_stream_handle.implementation_type [*implementation_type]]] + [The underlying implementation type of I/O object. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_stream_handle.lowest_layer_type [*lowest_layer_type]]] + [A basic_handle is always the lowest layer. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_stream_handle.native_type [*native_type]]] + [The native representation of a handle. ] + + ] + + [ + + [[link boost_asio.reference.windows__basic_stream_handle.service_type [*service_type]]] + [The type of the service that will be used to provide I/O operations. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.assign [*assign]]] + [Assign an existing native handle to the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.basic_stream_handle [*basic_stream_handle]]] + [Construct a basic_stream_handle without opening it. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.close [*close]]] + [Close the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.get_io_service [*get_io_service]]] + [Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service associated with the object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.lowest_layer [*lowest_layer]]] + [Get a reference to the lowest layer. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.native [*native]]] + [Get the native handle representation. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.read_some [*read_some]]] + [Read some data from the handle. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.write_some [*write_some]]] + [Write some data to the handle. ] + ] + +] + +[heading Protected Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.implementation [*implementation]]] + [The underlying implementation of the I/O object. ] + ] + + [ + [[link boost_asio.reference.windows__basic_stream_handle.service [*service]]] + [The service associated with the I/O object. ] + ] + +] + +The windows::basic_stream_handle class template provides asynchronous and blocking stream-oriented handle functionality. + + +[heading Thread Safety] + +[*Distinct] [*objects:] Safe. + +[*Shared] [*objects:] Unsafe. + + + + +[endsect] + + +[section:windows__stream_handle_service windows::stream_handle_service] + +Default service implementation for a stream handle. + + class stream_handle_service : + public io_service::service + + +[heading Types] +[table + [[Name][Description]] + + [ + + [[link boost_asio.reference.windows__stream_handle_service.implementation_type [*implementation_type]]] + [The type of a stream handle implementation. ] + + ] + + [ + + [[link boost_asio.reference.windows__stream_handle_service.native_type [*native_type]]] + [The native handle type. ] + + ] + +] + +[heading Member Functions] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__stream_handle_service.assign [*assign]]] + [Assign an existing native handle to a stream handle. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.async_read_some [*async_read_some]]] + [Start an asynchronous read. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.async_write_some [*async_write_some]]] + [Start an asynchronous write. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.cancel [*cancel]]] + [Cancel all asynchronous operations associated with the handle. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.close [*close]]] + [Close a stream handle implementation. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.construct [*construct]]] + [Construct a new stream handle implementation. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.destroy [*destroy]]] + [Destroy a stream handle implementation. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.get_io_service [*get_io_service]]] + [Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.io_service [*io_service]]] + [(Deprecated: use get_io_service().) Get the io_service object that owns the service. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.is_open [*is_open]]] + [Determine whether the handle is open. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.native [*native]]] + [Get the native handle implementation. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.read_some [*read_some]]] + [Read some data from the stream. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.shutdown_service [*shutdown_service]]] + [Destroy all user-defined handler objects owned by the service. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.stream_handle_service [*stream_handle_service]]] + [Construct a new stream handle service for the specified io_service. ] + ] + + [ + [[link boost_asio.reference.windows__stream_handle_service.write_some [*write_some]]] + [Write the given data to the stream. ] + ] + +] + +[heading Data Members] +[table + [[Name][Description]] + + [ + [[link boost_asio.reference.windows__stream_handle_service.id [*id]]] + [The unique service identifier. ] + ] + +] + + +[section:assign windows::stream_handle_service::assign] + +Assign an existing native handle to a stream handle. + + boost::system::error_code assign( + implementation_type & impl, + const native_type & native_handle, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:async_read_some windows::stream_handle_service::async_read_some] + +Start an asynchronous read. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``, + typename ``[link boost_asio.reference.ReadHandler ReadHandler]``> + void async_read_some( + implementation_type & impl, + const MutableBufferSequence & buffers, + ReadHandler handler); + + + +[endsect] + + + +[section:async_write_some windows::stream_handle_service::async_write_some] + +Start an asynchronous write. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename ``[link boost_asio.reference.WriteHandler WriteHandler]``> + void async_write_some( + implementation_type & impl, + const ConstBufferSequence & buffers, + WriteHandler handler); + + + +[endsect] + + + +[section:cancel windows::stream_handle_service::cancel] + +Cancel all asynchronous operations associated with the handle. + + boost::system::error_code cancel( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:close windows::stream_handle_service::close] + +Close a stream handle implementation. + + boost::system::error_code close( + implementation_type & impl, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:construct windows::stream_handle_service::construct] + +Construct a new stream handle implementation. + + void construct( + implementation_type & impl); + + + +[endsect] + + + +[section:destroy windows::stream_handle_service::destroy] + +Destroy a stream handle implementation. + + void destroy( + implementation_type & impl); + + + +[endsect] + + + +[section:get_io_service windows::stream_handle_service::get_io_service] + + +['Inherited from io_service.] + +Get the io_service object that owns the service. + + boost::asio::io_service & get_io_service(); + + + +[endsect] + + + +[section:id windows::stream_handle_service::id] + +The unique service identifier. + + static boost::asio::io_service::id id; + + + +[endsect] + + + +[section:implementation_type windows::stream_handle_service::implementation_type] + +The type of a stream handle implementation. + + typedef implementation_defined implementation_type; + + + + +[endsect] + + + +[section:io_service windows::stream_handle_service::io_service] + + +['Inherited from io_service.] + +(Deprecated: use get_io_service().) Get the io_service object that owns the service. + + boost::asio::io_service & io_service(); + + + +[endsect] + + + +[section:is_open windows::stream_handle_service::is_open] + +Determine whether the handle is open. + + bool is_open( + const implementation_type & impl) const; + + + +[endsect] + + + +[section:native windows::stream_handle_service::native] + +Get the native handle implementation. + + native_type native( + implementation_type & impl); + + + +[endsect] + + + +[section:native_type windows::stream_handle_service::native_type] + +The native handle type. + + typedef implementation_defined native_type; + + + + +[endsect] + + + +[section:read_some windows::stream_handle_service::read_some] + +Read some data from the stream. + + template< + typename ``[link boost_asio.reference.MutableBufferSequence MutableBufferSequence]``> + std::size_t read_some( + implementation_type & impl, + const MutableBufferSequence & buffers, + boost::system::error_code & ec); + + + +[endsect] + + + +[section:shutdown_service windows::stream_handle_service::shutdown_service] + +Destroy all user-defined handler objects owned by the service. + + void shutdown_service(); + + + +[endsect] + + + +[section:stream_handle_service windows::stream_handle_service::stream_handle_service] + +Construct a new stream handle service for the specified io_service. + + stream_handle_service( + boost::asio::io_service & io_service); + + + +[endsect] + + + +[section:write_some windows::stream_handle_service::write_some] + +Write the given data to the stream. + + template< + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_some( + implementation_type & impl, + const ConstBufferSequence & buffers, + boost::system::error_code & ec); + + + +[endsect] + + + +[endsect] + [section:write write] Write all of the supplied data to a stream before returning. @@ -39000,7 +59893,7 @@ The number of bytes written. If an error occurs, returns the total number of byt [section:overload4 write (4 of 6 overloads)] -Write a certain amount of data to a stream before returning. +Write all of the supplied data to a stream before returning. template< typename ``[link boost_asio.reference.SyncWriteStream SyncWriteStream]``, @@ -39185,6 +60078,493 @@ The number of bytes written. If an error occurs, returns the total number of byt +[endsect] + + +[endsect] + +[section:write_at write_at] + +Write all of the supplied data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t ``[link boost_asio.reference.write_at.overload1 write_at]``( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename CompletionCondition> + std::size_t ``[link boost_asio.reference.write_at.overload2 write_at]``( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + CompletionCondition completion_condition); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename CompletionCondition> + std::size_t ``[link boost_asio.reference.write_at.overload3 write_at]``( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + CompletionCondition completion_condition, + boost::system::error_code & ec); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename Allocator> + std::size_t ``[link boost_asio.reference.write_at.overload4 write_at]``( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename Allocator, + typename CompletionCondition> + std::size_t ``[link boost_asio.reference.write_at.overload5 write_at]``( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition); + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename Allocator, + typename CompletionCondition> + std::size_t ``[link boost_asio.reference.write_at.overload6 write_at]``( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition, + boost::system::error_code & ec); + + +[section:overload1 write_at (1 of 6 overloads)] + +Write all of the supplied data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``> + std::size_t write_at( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers); + + +This function is used to write a certain number of bytes of data to a random access device at a specified offset. The call will block until one of the following conditions is true: + + +* All of the data in the supplied buffers has been written. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* An error occurred. + +This operation is implemented in terms of one or more calls to the device's write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the SyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[buffers][One or more buffers containing the data to be written. The sum of the buffer sizes indicates the maximum number of bytes to write to the device.]] + +] + +[heading Return Value] + +The number of bytes transferred. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::write_at(d, 42, boost::asio::buffer(data, size)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + +[heading Remarks] + +This overload is equivalent to calling: + + boost::asio::write_at( + d, offset, buffers, + boost::asio::transfer_all()); + + + + + + +[endsect] + + + +[section:overload2 write_at (2 of 6 overloads)] + +Write a certain amount of data at a specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename CompletionCondition> + std::size_t write_at( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + CompletionCondition completion_condition); + + +This function is used to write a certain number of bytes of data to a random access device at a specified offset. The call will block until one of the following conditions is true: + + +* All of the data in the supplied buffers has been written. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the SyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[buffers][One or more buffers containing the data to be written. The sum of the buffer sizes indicates the maximum number of bytes to write to the device.]] + +[[completion_condition][The function object to be called to determine whether the write operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest write_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the write operation is complete. False indicates that further calls to the device's write\_some\_at function are required.]] + +] + +[heading Return Value] + +The number of bytes transferred. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Example] + +To write a single data buffer use the +[link boost_asio.reference.buffer buffer] function as follows: + + boost::asio::write_at(d, 42, boost::asio::buffer(data, size), + boost::asio::transfer_at_least(32)); + + +See the +[link boost_asio.reference.buffer buffer] documentation for information on writing multiple buffers in one go, and how to use it with arrays, boost::array or std::vector. + + + +[endsect] + + + +[section:overload3 write_at (3 of 6 overloads)] + +Write a certain amount of data at a specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename ``[link boost_asio.reference.ConstBufferSequence ConstBufferSequence]``, + typename CompletionCondition> + std::size_t write_at( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + const ConstBufferSequence & buffers, + CompletionCondition completion_condition, + boost::system::error_code & ec); + + +This function is used to write a certain number of bytes of data to a random access device at a specified offset. The call will block until one of the following conditions is true: + + +* All of the data in the supplied buffers has been written. That is, the bytes transferred is equal to the sum of the buffer sizes. + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the SyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[buffers][One or more buffers containing the data to be written. The sum of the buffer sizes indicates the maximum number of bytes to write to the device.]] + +[[completion_condition][The function object to be called to determine whether the write operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest write_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the write operation is complete. False indicates that further calls to the device's write\_some\_at function are required.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes written. If an error occurs, returns the total number of bytes successfully transferred prior to the error. + + + +[endsect] + + + +[section:overload4 write_at (4 of 6 overloads)] + +Write all of the supplied data at the specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename Allocator> + std::size_t write_at( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b); + + +This function is used to write a certain number of bytes of data to a random access device at a specified offset. The call will block until one of the following conditions is true: + + +* All of the data in the supplied basic_streambuf has been written. + +* An error occurred. + +This operation is implemented in terms of one or more calls to the device's write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the SyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[b][The basic\_streambuf object from which data will be written.]] + +] + +[heading Return Value] + +The number of bytes transferred. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure.]] + +] + +[heading Remarks] + +This overload is equivalent to calling: + + boost::asio::write_at( + d, 42, b, + boost::asio::transfer_all()); + + + + + + +[endsect] + + + +[section:overload5 write_at (5 of 6 overloads)] + +Write a certain amount of data at a specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename Allocator, + typename CompletionCondition> + std::size_t write_at( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition); + + +This function is used to write a certain number of bytes of data to a random access device at a specified offset. The call will block until one of the following conditions is true: + + +* All of the data in the supplied basic_streambuf has been written. + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the SyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[b][The basic\_streambuf object from which data will be written.]] + +[[completion_condition][The function object to be called to determine whether the write operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest write_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the write operation is complete. False indicates that further calls to the device's write\_some\_at function are required.]] + +] + +[heading Return Value] + +The number of bytes transferred. + +[heading Exceptions] + + +[variablelist + +[[boost::system::system_error][Thrown on failure. ]] + +] + + + +[endsect] + + + +[section:overload6 write_at (6 of 6 overloads)] + +Write a certain amount of data at a specified offset before returning. + + template< + typename ``[link boost_asio.reference.SyncRandomAccessWriteDevice SyncRandomAccessWriteDevice]``, + typename Allocator, + typename CompletionCondition> + std::size_t write_at( + SyncRandomAccessWriteDevice & d, + boost::uint64_t offset, + basic_streambuf< Allocator > & b, + CompletionCondition completion_condition, + boost::system::error_code & ec); + + +This function is used to write a certain number of bytes of data to a random access device at a specified offset. The call will block until one of the following conditions is true: + + +* All of the data in the supplied basic_streambuf has been written. + +* The completion_condition function object returns true. + +This operation is implemented in terms of one or more calls to the device's write\_some\_at function. + + +[heading Parameters] + + +[variablelist + +[[d][The device to which the data is to be written. The type must support the SyncRandomAccessWriteDevice concept.]] + +[[offset][The offset at which the data will be written.]] + +[[b][The basic\_streambuf object from which data will be written.]] + +[[completion_condition][The function object to be called to determine whether the write operation is complete. The signature of the function object must be: +`` + bool completion_condition( + // Result of latest write_some_at operation. + const boost::system::error_code& error, + + // Number of bytes transferred so far. + std::size_t bytes_transferred + ); + +`` +A return value of true indicates that the write operation is complete. False indicates that further calls to the device's write\_some\_at function are required.]] + +[[ec][Set to indicate what error occurred, if any.]] + +] + +[heading Return Value] + +The number of bytes written. If an error occurs, returns the total number of bytes successfully transferred prior to the error. + + + [endsect] diff --git a/doc/reference.xsl b/doc/reference.xsl index addc8ea2..f7c904d8 100644 --- a/doc/reference.xsl +++ b/doc/reference.xsl @@ -45,9 +45,11 @@ [include requirements/ConvertibleToConstBuffer.qbk] [include requirements/ConvertibleToMutableBuffer.qbk] [include requirements/DatagramSocketService.qbk] +[include requirements/DescriptorService.qbk] [include requirements/Endpoint.qbk] [include requirements/GettableSocketOption.qbk] [include requirements/Handler.qbk] +[include requirements/HandleService.qbk] [include requirements/InternetProtocol.qbk] [include requirements/IoControlCommand.qbk] [include requirements/IoObjectService.qbk] @@ -60,6 +62,8 @@ [include requirements/SettableSocketOption.qbk] [include requirements/SocketAcceptorService.qbk] [include requirements/SocketService.qbk] +[include requirements/StreamDescriptorService.qbk] +[include requirements/StreamHandleService.qbk] [include requirements/StreamSocketService.qbk] [include requirements/SyncReadStream.qbk] [include requirements/SyncWriteStream.qbk] @@ -85,7 +89,9 @@ - + @@ -191,6 +197,12 @@ select="concat(substring-before($name, '>'), '_gt_', substring-after($name, '>'))"/> + + + + + - -[heading Friends] + +[heading Protected Member Functions] [table [[Name][Description]] - + @@ -665,13 +677,99 @@ ] + + +[heading Protected Data Members] +[table + [[Name][Description]] + + + [ + [[link boost_asio.reference.. + [*]]] + [] + ] + +] + + + +[heading Friends] +[table + [[Name][Description]] + + + + + + + + + + + + + + + + + + + + + + [ + [[link boost_asio.reference.. + [*]]] + [] + ] + + +] + + + +[heading Related Functions] +[table + [[Name][Description]] + + + + + + + + + + + + + + + + + + + + + + [ + [[link boost_asio.reference.. + [*]]] + [] + ] + + +] + + - + @@ -818,8 +916,8 @@ - enum - + enum + [heading Values] [variablelist @@ -829,6 +927,7 @@ ] ] + diff --git a/doc/requirements/DescriptorService.qbk b/doc/requirements/DescriptorService.qbk new file mode 100644 index 00000000..aa314b86 --- /dev/null +++ b/doc/requirements/DescriptorService.qbk @@ -0,0 +1,120 @@ +[/ + / Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:DescriptorService Descriptor service requirements] + +A descriptor service must meet the requirements for an [link +boost_asio.reference.IoObjectService I/O object service], as well as the +additional requirements listed below. + +In the table below, `X` denotes a descriptor service class, `a` denotes a value +of type `X`, `b` denotes a value of type `X::implementation_type`, `n` denotes +a value of type `X::native_type`, `ec` denotes a value of type `error_code`, +`i` denotes a value meeting [link boost_asio.reference.IoControlCommand +`IoControlCommand`] requirements, and `u` and `v` denote identifiers. + +[table DescriptorService requirements + [[expression] [return type] [assertion/note\npre/post-condition]] + [ + [`X::native_type`] + [] + [ + The implementation-defined native representation of a descriptor. Must + satisfy the requirements of `CopyConstructible` types (C++ Std, 20.1.3), + and the requirements of `Assignable` types (C++ Std, 23.1). + ] + ] + [ + [`a.construct(b);`] + [] + [ + From [link boost_asio.reference.IoObjectService IoObjectService] + requirements.\n + post: `!a.is_open(b)`. + ] + ] + [ + [`a.destroy(b);`] + [] + [ + From [link boost_asio.reference.IoObjectService IoObjectService] + requirements. Implicitly cancels asynchronous operations, as if by calling + `a.close(b, ec)`. + ] + ] + [ + [`` + a.assign(b, n, ec); + ``] + [`error_code`] + [ + pre: `!a.is_open(b)`.\n + post: `!!ec || a.is_open(b)`. + ] + ] + [ + [`` + a.is_open(b); + ``] + [`bool`] + [ + ] + ] + [ + [`` + const X& u = a; + const X::implementation_type& v = b; + u.is_open(v); + ``] + [`bool`] + [ + ] + ] + [ + [`` + a.close(b, ec); + ``] + [`error_code`] + [ + If `a.is_open()` is true, causes any outstanding asynchronous operations + to complete as soon as possible. Handlers for cancelled operations shall + be passed the error code `error::operation_aborted`.\n + post: `!a.is_open(b)`. + ] + ] + [ + [`` + a.native(b); + ``] + [`X::native_type`] + [ + ] + ] + [ + [`` + a.cancel(b, ec); + ``] + [`error_code`] + [ + pre: `a.is_open(b)`.\n + Causes any outstanding asynchronous operations to complete as soon as + possible. Handlers for cancelled operations shall be passed the error + code `error::operation_aborted`. + ] + ] + [ + [`` + a.io_control(b, i, ec); + ``] + [`error_code`] + [ + pre: `a.is_open(b)`. + ] + ] +] + +[endsect] diff --git a/doc/requirements/HandleService.qbk b/doc/requirements/HandleService.qbk new file mode 100644 index 00000000..914c714c --- /dev/null +++ b/doc/requirements/HandleService.qbk @@ -0,0 +1,110 @@ +[/ + / Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:HandleService Handle service requirements] + +A handle service must meet the requirements for an [link +boost_asio.reference.IoObjectService I/O object service], as well as the +additional requirements listed below. + +In the table below, `X` denotes a handle service class, `a` denotes a value of +type `X`, `b` denotes a value of type `X::implementation_type`, `n` denotes a +value of type `X::native_type`, `ec` denotes a value of type `error_code`, and +`u` and `v` denote identifiers. + +[table HandleService requirements + [[expression] [return type] [assertion/note\npre/post-condition]] + [ + [`X::native_type`] + [] + [ + The implementation-defined native representation of a handle. Must + satisfy the requirements of `CopyConstructible` types (C++ Std, 20.1.3), + and the requirements of `Assignable` types (C++ Std, 23.1). + ] + ] + [ + [`a.construct(b);`] + [] + [ + From [link boost_asio.reference.IoObjectService IoObjectService] + requirements.\n + post: `!a.is_open(b)`. + ] + ] + [ + [`a.destroy(b);`] + [] + [ + From [link boost_asio.reference.IoObjectService IoObjectService] + requirements. Implicitly cancels asynchronous operations, as if by calling + `a.close(b, ec)`. + ] + ] + [ + [`` + a.assign(b, n, ec); + ``] + [`error_code`] + [ + pre: `!a.is_open(b)`.\n + post: `!!ec || a.is_open(b)`. + ] + ] + [ + [`` + a.is_open(b); + ``] + [`bool`] + [ + ] + ] + [ + [`` + const X& u = a; + const X::implementation_type& v = b; + u.is_open(v); + ``] + [`bool`] + [ + ] + ] + [ + [`` + a.close(b, ec); + ``] + [`error_code`] + [ + If `a.is_open()` is true, causes any outstanding asynchronous operations + to complete as soon as possible. Handlers for cancelled operations shall + be passed the error code `error::operation_aborted`.\n + post: `!a.is_open(b)`. + ] + ] + [ + [`` + a.native(b); + ``] + [`X::native_type`] + [ + ] + ] + [ + [`` + a.cancel(b, ec); + ``] + [`error_code`] + [ + pre: `a.is_open(b)`.\n + Causes any outstanding asynchronous operations to complete as soon as + possible. Handlers for cancelled operations shall be passed the error + code `error::operation_aborted`. + ] + ] +] + +[endsect] diff --git a/doc/requirements/StreamDescriptorService.qbk b/doc/requirements/StreamDescriptorService.qbk new file mode 100644 index 00000000..796ead23 --- /dev/null +++ b/doc/requirements/StreamDescriptorService.qbk @@ -0,0 +1,138 @@ +[/ + / Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:StreamDescriptorService Stream descriptor service requirements] + +A stream descriptor service must meet the requirements for a [link +boost_asio.reference.DescriptorService descriptor service], as well as the additional +requirements listed below. + +In the table below, `X` denotes a stream descriptor service class, `a` denotes +a value of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` +denotes a value of type `error_code`, `mb` denotes a value satisfying [link +boost_asio.reference.MutableBufferSequence mutable buffer sequence] requirements, +`rh` denotes a value meeting [link boost_asio.reference.ReadHandler `ReadHandler`] +requirements, `cb` denotes a value satisfying [link +boost_asio.reference.ConstBufferSequence constant buffer sequence] requirements, and +`wh` denotes a value meeting [link boost_asio.reference.WriteHandler `WriteHandler`] +requirements. + +[table StreamDescriptorService requirements + [[expression] [return type] [assertion/note\npre/post-condition]] + [ + [`a.read_some(b, mb, ec);`] + [`size_t`] + [ + pre: `a.is_open(b)`.\n + \n + Reads one or more bytes of data from a decsriptor `b`.\n + \n + The mutable buffer sequence `mb` specifies memory where the data should + be placed. The operation shall always fill a buffer in the sequence + completely before proceeding to the next.\n + \n + If successful, returns the number of bytes read. Otherwise returns `0`. + If the total size of all buffers in the sequence `mb` is `0`, the + function shall return `0` immediately.\n + \n + If the operation completes due to graceful connection closure by the + peer, the operation shall fail with `error::eof`. + ] + ] + [ + [`a.async_read_some(b, mb, rh);`] + [`void`] + [ + pre: `a.is_open(b)`.\n + \n + Initiates an asynchronous operation to read one or more bytes of data + from a descriptor `b`. The operation is performed via the + `io_service` object `a.io_service()` and behaves according to [link + boost_asio.reference.asynchronous_operations asynchronous operation] + requirements.\n + \n + The mutable buffer sequence `mb` specifies memory where the data should + be placed. The operation shall always fill a buffer in the sequence + completely before proceeding to the next.\n + \n + The implementation shall maintain one or more copies of `mb` until such + time as the read operation no longer requires access to the memory + specified by the buffers in the sequence. The program must ensure the + memory is valid until:\n + \n + [mdash] the last copy of `mb` is destroyed, or\n + \n + [mdash] the handler for the asynchronous operation is invoked,\n + \n + whichever comes first. If the total size of all buffers in the sequence + `mb` is `0`, the asynchronous read operation shall complete immediately + and pass `0` as the argument to the handler that specifies the number of + bytes read.\n + \n + If the operation completes due to graceful connection closure by the + peer, the operation shall fail with `error::eof`.\n + \n + If the operation completes successfully, the `ReadHandler` object + `rh` is invoked with the number of bytes transferred. Otherwise it is + invoked with `0`. + ] + ] + [ + [`a.write_some(b, cb, ec);`] + [`size_t`] + [ + pre: `a.is_open(b)`.\n + \n + Writes one or more bytes of data to a descriptor `b`.\n + \n + The constant buffer sequence `cb` specifies memory where the data to be + written is located. The operation shall always write a buffer in the + sequence completely before proceeding to the next.\n + \n + If successful, returns the number of bytes written. Otherwise returns `0`. + If the total size of all buffers in the sequence `cb` is `0`, the + function shall return `0` immediately. + ] + ] + [ + [`a.async_write_some(b, cb, wh);`] + [`void`] + [ + pre: `a.is_open(b)`.\n + \n + Initiates an asynchronous operation to write one or more bytes of data to + a decsriptor `b`. The operation is performed via the `io_service` + object `a.io_service()` and behaves according to [link + boost_asio.reference.asynchronous_operations asynchronous operation] + requirements.\n + \n + The constant buffer sequence `cb` specifies memory where the data to be + written is located. The operation shall always write a buffer in the + sequence completely before proceeding to the next.\n + \n + The implementation shall maintain one or more copies of `cb` until such + time as the write operation no longer requires access to the memory + specified by the buffers in the sequence. The program must ensure the + memory is valid until:\n + \n + [mdash] the last copy of `cb` is destroyed, or\n + \n + [mdash] the handler for the asynchronous operation is invoked,\n + \n + whichever comes first. If the total size of all buffers in the sequence + `cb` is `0`, the asynchronous operation shall complete immediately and + pass `0` as the argument to the handler that specifies the number of + bytes read.\n + \n + If the operation completes successfully, the `WriteHandler` object `wh` + is invoked with the number of bytes transferred. Otherwise it is invoked + with `0`. + ] + ] +] + +[endsect] diff --git a/doc/requirements/StreamHandleService.qbk b/doc/requirements/StreamHandleService.qbk new file mode 100644 index 00000000..b3653743 --- /dev/null +++ b/doc/requirements/StreamHandleService.qbk @@ -0,0 +1,138 @@ +[/ + / Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:StreamHandleService Stream handle service requirements] + +A stream handle service must meet the requirements for a [link +boost_asio.reference.HandleService handle service], as well as the additional +requirements listed below. + +In the table below, `X` denotes a stream handle service class, `a` denotes +a value of type `X`, `b` denotes a value of type `X::implementation_type`, `ec` +denotes a value of type `error_code`, `mb` denotes a value satisfying [link +boost_asio.reference.MutableBufferSequence mutable buffer sequence] requirements, +`rh` denotes a value meeting [link boost_asio.reference.ReadHandler `ReadHandler`] +requirements, `cb` denotes a value satisfying [link +boost_asio.reference.ConstBufferSequence constant buffer sequence] requirements, and +`wh` denotes a value meeting [link boost_asio.reference.WriteHandler `WriteHandler`] +requirements. + +[table StreamHandleService requirements + [[expression] [return type] [assertion/note\npre/post-condition]] + [ + [`a.read_some(b, mb, ec);`] + [`size_t`] + [ + pre: `a.is_open(b)`.\n + \n + Reads one or more bytes of data from a decsriptor `b`.\n + \n + The mutable buffer sequence `mb` specifies memory where the data should + be placed. The operation shall always fill a buffer in the sequence + completely before proceeding to the next.\n + \n + If successful, returns the number of bytes read. Otherwise returns `0`. + If the total size of all buffers in the sequence `mb` is `0`, the + function shall return `0` immediately.\n + \n + If the operation completes due to graceful connection closure by the + peer, the operation shall fail with `error::eof`. + ] + ] + [ + [`a.async_read_some(b, mb, rh);`] + [`void`] + [ + pre: `a.is_open(b)`.\n + \n + Initiates an asynchronous operation to read one or more bytes of data + from a handle `b`. The operation is performed via the + `io_service` object `a.io_service()` and behaves according to [link + boost_asio.reference.asynchronous_operations asynchronous operation] + requirements.\n + \n + The mutable buffer sequence `mb` specifies memory where the data should + be placed. The operation shall always fill a buffer in the sequence + completely before proceeding to the next.\n + \n + The implementation shall maintain one or more copies of `mb` until such + time as the read operation no longer requires access to the memory + specified by the buffers in the sequence. The program must ensure the + memory is valid until:\n + \n + [mdash] the last copy of `mb` is destroyed, or\n + \n + [mdash] the handler for the asynchronous operation is invoked,\n + \n + whichever comes first. If the total size of all buffers in the sequence + `mb` is `0`, the asynchronous read operation shall complete immediately + and pass `0` as the argument to the handler that specifies the number of + bytes read.\n + \n + If the operation completes due to graceful connection closure by the + peer, the operation shall fail with `error::eof`.\n + \n + If the operation completes successfully, the `ReadHandler` object + `rh` is invoked with the number of bytes transferred. Otherwise it is + invoked with `0`. + ] + ] + [ + [`a.write_some(b, cb, ec);`] + [`size_t`] + [ + pre: `a.is_open(b)`.\n + \n + Writes one or more bytes of data to a handle `b`.\n + \n + The constant buffer sequence `cb` specifies memory where the data to be + written is located. The operation shall always write a buffer in the + sequence completely before proceeding to the next.\n + \n + If successful, returns the number of bytes written. Otherwise returns `0`. + If the total size of all buffers in the sequence `cb` is `0`, the + function shall return `0` immediately. + ] + ] + [ + [`a.async_write_some(b, cb, wh);`] + [`void`] + [ + pre: `a.is_open(b)`.\n + \n + Initiates an asynchronous operation to write one or more bytes of data to + a decsriptor `b`. The operation is performed via the `io_service` + object `a.io_service()` and behaves according to [link + boost_asio.reference.asynchronous_operations asynchronous operation] + requirements.\n + \n + The constant buffer sequence `cb` specifies memory where the data to be + written is located. The operation shall always write a buffer in the + sequence completely before proceeding to the next.\n + \n + The implementation shall maintain one or more copies of `cb` until such + time as the write operation no longer requires access to the memory + specified by the buffers in the sequence. The program must ensure the + memory is valid until:\n + \n + [mdash] the last copy of `cb` is destroyed, or\n + \n + [mdash] the handler for the asynchronous operation is invoked,\n + \n + whichever comes first. If the total size of all buffers in the sequence + `cb` is `0`, the asynchronous operation shall complete immediately and + pass `0` as the argument to the handler that specifies the number of + bytes read.\n + \n + If the operation completes successfully, the `WriteHandler` object `wh` + is invoked with the number of bytes transferred. Otherwise it is invoked + with `0`. + ] + ] +] + +[endsect] diff --git a/doc/using.qbk b/doc/using.qbk index 4f9374e1..8266df4f 100644 --- a/doc/using.qbk +++ b/doc/using.qbk @@ -255,6 +255,13 @@ Boost.Asio. cancel the outstanding operations and close the socket. ] ] + [ + [`BOOST_ASIO_NO_TYPEID`] + [ + Disables uses of the `typeid` operator in Boost.Asio. Defined + automatically if `BOOST_NO_TYPEID` is defined. + ] + ] ] [endsect] diff --git a/example/invocation/prioritised_handlers.cpp b/example/invocation/prioritised_handlers.cpp index 657eb5f6..82dc4a3e 100644 --- a/example/invocation/prioritised_handlers.cpp +++ b/example/invocation/prioritised_handlers.cpp @@ -13,6 +13,8 @@ #include #include +using boost::asio::ip::tcp; + class handler_priority_queue { public: @@ -108,12 +110,12 @@ void asio_handler_invoke(Function f, //---------------------------------------------------------------------- -void high_priority_handler() +void high_priority_handler(const boost::system::error_code& /*ec*/) { std::cout << "High priority handler\n"; } -void middle_priority_handler() +void middle_priority_handler(const boost::system::error_code& /*ec*/) { std::cout << "Middle priority handler\n"; } @@ -129,9 +131,22 @@ int main() handler_priority_queue pri_queue; + // Post a completion handler to be run immediately. io_service.post(pri_queue.wrap(0, low_priority_handler)); - io_service.post(pri_queue.wrap(100, high_priority_handler)); - io_service.post(pri_queue.wrap(42, middle_priority_handler)); + + // Start an asynchronous accept that will complete immediately. + tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 0); + tcp::acceptor acceptor(io_service, endpoint); + tcp::socket server_socket(io_service); + acceptor.async_accept(server_socket, + pri_queue.wrap(100, high_priority_handler)); + tcp::socket client_socket(io_service); + client_socket.connect(acceptor.local_endpoint()); + + // Set a deadline timer to expire immediately. + boost::asio::deadline_timer timer(io_service); + timer.expires_at(boost::posix_time::neg_infin); + timer.async_wait(pri_queue.wrap(42, middle_priority_handler)); while (io_service.run_one()) { diff --git a/example/nonblocking/Jamfile b/example/nonblocking/Jamfile new file mode 100644 index 00000000..094566c5 --- /dev/null +++ b/example/nonblocking/Jamfile @@ -0,0 +1,33 @@ +# +# Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# + +subproject libs/asio/example/nonblocking ; + +project boost : $(BOOST_ROOT) ; + +if $(UNIX) +{ + switch $(JAMUNAME) + { + case SunOS* : + { + SOCKET_LIBS = socket nsl ; + } + } +} + +exe third_party_lib + : @boost/libs/system/build/boost_system + third_party_lib.cpp + : $(BOOST_ROOT) + ../../../.. + BOOST_ALL_NO_LIB=1 + multi + <*>ws2_32 + <*>mswsock + $(SOCKET_LIBS) + ; diff --git a/example/nonblocking/Jamfile.v2 b/example/nonblocking/Jamfile.v2 new file mode 100644 index 00000000..30aedf67 --- /dev/null +++ b/example/nonblocking/Jamfile.v2 @@ -0,0 +1,38 @@ +# +# Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# + +import os ; + +if [ os.name ] = SOLARIS +{ + lib socket ; + lib nsl ; +} +else if [ os.name ] = NT +{ + lib ws2_32 ; + lib mswsock ; +} +else if [ os.name ] = HPUX +{ + lib ipv6 ; +} + +exe third_party_lib + : third_party_lib.cpp + /boost/system//boost_system + : BOOST_ALL_NO_LIB=1 + multi + SOLARIS:socket + SOLARIS:nsl + NT:_WIN32_WINNT=0x0501 + NT,gcc:ws2_32 + NT,gcc:mswsock + NT,gcc-cygwin:__USE_W32_SOCKETS + HPUX,gcc:_XOPEN_SOURCE_EXTENDED + HPUX:ipv6 + ; diff --git a/example/nonblocking/third_party_lib.cpp b/example/nonblocking/third_party_lib.cpp new file mode 100644 index 00000000..7576d4d2 --- /dev/null +++ b/example/nonblocking/third_party_lib.cpp @@ -0,0 +1,241 @@ +// +// third_party_lib.cpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include +#include + +using boost::asio::ip::tcp; + +namespace third_party_lib { + +// Simulation of a third party library that wants to perform read and write +// operations directly on a socket. It needs to be polled to determine whether +// it requires a read or write operation, and notified when the socket is ready +// for reading or writing. +class session +{ +public: + session(tcp::socket& socket) + : socket_(socket), + state_(reading) + { + } + + // Returns true if the third party library wants to be notified when the + // socket is ready for reading. + bool want_read() const + { + return state_ == reading; + } + + // Notify that third party library that it should perform its read operation. + void do_read(boost::system::error_code& ec) + { + if (std::size_t len = socket_.read_some(boost::asio::buffer(data_), ec)) + { + write_buffer_ = boost::asio::buffer(data_, len); + state_ = writing; + } + } + + // Returns true if the third party library wants to be notified when the + // socket is ready for writing. + bool want_write() const + { + return state_ == writing; + } + + // Notify that third party library that it should perform its write operation. + void do_write(boost::system::error_code& ec) + { + if (std::size_t len = socket_.write_some( + boost::asio::buffer(write_buffer_), ec)) + { + write_buffer_ = write_buffer_ + len; + state_ = boost::asio::buffer_size(write_buffer_) > 0 ? writing : reading; + } + } + +private: + tcp::socket& socket_; + enum { reading, writing } state_; + boost::array data_; + boost::asio::const_buffer write_buffer_; +}; + +} // namespace third_party_lib + +// The glue between asio's sockets and the third party library. +class connection + : public boost::enable_shared_from_this +{ +public: + typedef boost::shared_ptr pointer; + + static pointer create(boost::asio::io_service& io_service) + { + return pointer(new connection(io_service)); + } + + tcp::socket& socket() + { + return socket_; + } + + void start() + { + // Put the socket into non-blocking mode. + tcp::socket::non_blocking_io non_blocking_io(true); + socket_.io_control(non_blocking_io); + + start_operations(); + } + +private: + connection(boost::asio::io_service& io_service) + : socket_(io_service), + session_impl_(socket_), + read_in_progress_(false), + write_in_progress_(false) + { + } + + void start_operations() + { + // Start a read operation if the third party library wants one. + if (session_impl_.want_read() && !read_in_progress_) + { + read_in_progress_ = true; + socket_.async_read_some( + boost::asio::null_buffers(), + boost::bind(&connection::handle_read, + shared_from_this(), + boost::asio::placeholders::error)); + } + + // Start a write operation if the third party library wants one. + if (session_impl_.want_write() && !write_in_progress_) + { + write_in_progress_ = true; + socket_.async_write_some( + boost::asio::null_buffers(), + boost::bind(&connection::handle_write, + shared_from_this(), + boost::asio::placeholders::error)); + } + } + + void handle_read(boost::system::error_code ec) + { + read_in_progress_ = false; + + // Notify third party library that it can perform a read. + if (!ec) + session_impl_.do_read(ec); + + // The third party library successfully performed a read on the socket. + // Start new read or write operations based on what it now wants. + if (!ec || ec == boost::asio::error::would_block) + start_operations(); + + // Otherwise, an error occurred. Closing the socket cancels any outstanding + // asynchronous read or write operations. The connection object will be + // destroyed once automatically once those outstanding operations complete. + else + socket_.close(); + } + + void handle_write(boost::system::error_code ec) + { + write_in_progress_ = false; + + // Notify third party library that it can perform a write. + if (!ec) + session_impl_.do_write(ec); + + // The third party library successfully performed a write on the socket. + // Start new read or write operations based on what it now wants. + if (!ec || ec == boost::asio::error::would_block) + start_operations(); + + // Otherwise, an error occurred. Closing the socket cancels any outstanding + // asynchronous read or write operations. The connection object will be + // destroyed once automatically once those outstanding operations complete. + else + socket_.close(); + } + +private: + tcp::socket socket_; + third_party_lib::session session_impl_; + bool read_in_progress_; + bool write_in_progress_; +}; + +class server +{ +public: + server(boost::asio::io_service& io_service, unsigned short port) + : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) + { + start_accept(); + } + +private: + void start_accept() + { + connection::pointer new_connection = + connection::create(acceptor_.io_service()); + + acceptor_.async_accept(new_connection->socket(), + boost::bind(&server::handle_accept, this, new_connection, + boost::asio::placeholders::error)); + } + + void handle_accept(connection::pointer new_connection, + const boost::system::error_code& error) + { + if (!error) + { + new_connection->start(); + start_accept(); + } + } + + tcp::acceptor acceptor_; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: third_party_lib \n"; + return 1; + } + + boost::asio::io_service io_service; + + using namespace std; // For atoi. + server s(io_service, atoi(argv[1])); + + io_service.run(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/example/porthopper/Jamfile b/example/porthopper/Jamfile new file mode 100644 index 00000000..50340903 --- /dev/null +++ b/example/porthopper/Jamfile @@ -0,0 +1,45 @@ +# +# Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# + +subproject libs/asio/example/porthopper ; + +project boost : $(BOOST_ROOT) ; + +if $(UNIX) +{ + switch $(JAMUNAME) + { + case SunOS* : + { + SOCKET_LIBS = socket nsl ; + } + } +} + +exe client + : @boost/libs/system/build/boost_system + client.cpp + : $(BOOST_ROOT) + ../../../.. + BOOST_ALL_NO_LIB=1 + multi + <*>ws2_32 + <*>mswsock + $(SOCKET_LIBS) + ; + +exe server + : @boost/libs/system/build/boost_system + server.cpp + : $(BOOST_ROOT) + ../../../.. + BOOST_ALL_NO_LIB=1 + multi + <*>ws2_32 + <*>mswsock + $(SOCKET_LIBS) + ; diff --git a/example/porthopper/Jamfile.v2 b/example/porthopper/Jamfile.v2 new file mode 100644 index 00000000..3a050cc8 --- /dev/null +++ b/example/porthopper/Jamfile.v2 @@ -0,0 +1,41 @@ +# +# Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# + +import os ; + +if [ os.name ] = SOLARIS +{ + lib socket ; + lib nsl ; +} +else if [ os.name ] = NT +{ + lib ws2_32 ; + lib mswsock ; +} +else if [ os.name ] = HPUX +{ + lib ipv6 ; +} + +project + : requirements + /boost/system//boost_system + BOOST_ALL_NO_LIB=1 + multi + SOLARIS:socket + SOLARIS:nsl + NT:_WIN32_WINNT=0x0501 + NT,gcc:ws2_32 + NT,gcc:mswsock + NT,gcc-cygwin:__USE_W32_SOCKETS + HPUX,gcc:_XOPEN_SOURCE_EXTENDED + HPUX:ipv6 + ; + +exe client : client.cpp ; +exe server : server.cpp ; diff --git a/example/porthopper/client.cpp b/example/porthopper/client.cpp new file mode 100644 index 00000000..53709695 --- /dev/null +++ b/example/porthopper/client.cpp @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "protocol.hpp" + +using namespace boost; +using boost::asio::ip::tcp; +using boost::asio::ip::udp; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cerr << "Usage: client \n"; + return 1; + } + using namespace std; // For atoi. + std::string host_name = argv[1]; + std::string port = argv[2]; + + boost::asio::io_service io_service; + + // Determine the location of the server. + tcp::resolver resolver(io_service); + tcp::resolver::query query(host_name, port); + tcp::endpoint remote_endpoint = *resolver.resolve(query); + + // Establish the control connection to the server. + tcp::socket control_socket(io_service); + control_socket.connect(remote_endpoint); + + // Create a datagram socket to receive data from the server. + shared_ptr data_socket( + new udp::socket(io_service, udp::endpoint(udp::v4(), 0))); + + // Determine what port we will receive data on. + udp::endpoint data_endpoint = data_socket->local_endpoint(); + + // Ask the server to start sending us data. + control_request start = control_request::start(data_endpoint.port()); + boost::asio::write(control_socket, start.to_buffers()); + + unsigned long last_frame_number = 0; + for (;;) + { + // Receive 50 messages on the current data socket. + for (int i = 0; i < 50; ++i) + { + // Receive a frame from the server. + frame f; + data_socket->receive(f.to_buffers(), 0); + if (f.number() > last_frame_number) + { + last_frame_number = f.number(); + std::cout << "\n" << f.payload(); + } + } + + // Time to switch to a new socket. To ensure seamless handover we will + // continue to receive packets using the old socket until data arrives on + // the new one. + std::cout << " Starting renegotiation"; + + // Create the new data socket. + shared_ptr new_data_socket( + new udp::socket(io_service, udp::endpoint(udp::v4(), 0))); + + // Determine the new port we will use to receive data. + udp::endpoint new_data_endpoint = new_data_socket->local_endpoint(); + + // Ask the server to switch over to the new port. + control_request change = control_request::change( + data_endpoint.port(), new_data_endpoint.port()); + boost::system::error_code control_result; + boost::asio::async_write(control_socket, change.to_buffers(), + lambda::unlambda(( + lambda::var(control_result) = lambda::_1 + ))); + + // Try to receive a frame from the server on the new data socket. If we + // successfully receive a frame on this new data socket we can consider + // the renegotation complete. In that case we will close the old data + // socket, which will cause any outstanding receive operation on it to be + // cancelled. + frame f1; + boost::system::error_code new_data_socket_result; + new_data_socket->async_receive(f1.to_buffers(), + lambda::unlambda(( + // Note: lambda::_1 is the first argument to the callback handler, + // which in this case is the error code for the operation. + lambda::var(new_data_socket_result) = lambda::_1, + lambda::if_(!lambda::_1) + [ + // We have successfully received a frame on the new data socket, + // so we can close the old data socket. This will cancel any + // outstanding receive operation on the old data socket. + lambda::var(data_socket) = shared_ptr() + ] + ))); + + // This loop will continue until we have successfully completed the + // renegotiation (i.e. received a frame on the new data socket), or some + // unrecoverable error occurs. + bool done = false; + while (!done) + { + // Even though we're performing a renegotation, we want to continue + // receiving data as smoothly as possible. Therefore we will continue to + // try to receive a frame from the server on the old data socket. If we + // receive a frame on this socket we will interrupt the io_service, + // print the frame, and resume waiting for the other operations to + // complete. + frame f2; + done = true; // Let's be optimistic. + if (data_socket) // Might have been closed by new_data_socket's handler. + { + data_socket->async_receive(f2.to_buffers(), 0, + lambda::unlambda(( + lambda::if_(!lambda::_1) + [ + // We have successfully received a frame on the old data + // socket. Stop the io_service so that we can print it. + lambda::bind(&boost::asio::io_service::stop, &io_service), + lambda::var(done) = false + ] + ))); + } + + // Run the operations in parallel. This will block until all operations + // have finished, or until the io_service is interrupted. (No threads!) + io_service.reset(); + io_service.run(); + + // If the io_service.run() was interrupted then we have received a frame + // on the old data socket. We need to keep waiting for the renegotation + // operations to complete. + if (!done) + { + if (f2.number() > last_frame_number) + { + last_frame_number = f2.number(); + std::cout << "\n" << f2.payload(); + } + } + } + + // Since the loop has finished, we have either successfully completed + // the renegotation, or an error has occurred. First we'll check for + // errors. + if (control_result) + throw boost::system::system_error(control_result); + if (new_data_socket_result) + throw boost::system::system_error(new_data_socket_result); + + // If we get here it means we have successfully started receiving data on + // the new data socket. This new data socket will be used from now on + // (until the next time we renegotiate). + std::cout << " Renegotiation complete"; + data_socket = new_data_socket; + data_endpoint = new_data_endpoint; + if (f1.number() > last_frame_number) + { + last_frame_number = f1.number(); + std::cout << "\n" << f1.payload(); + } + } + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; +} diff --git a/example/porthopper/protocol.hpp b/example/porthopper/protocol.hpp new file mode 100644 index 00000000..954c06b4 --- /dev/null +++ b/example/porthopper/protocol.hpp @@ -0,0 +1,145 @@ +#ifndef PORTHOPPER_PROTOCOL_HPP +#define PORTHOPPER_PROTOCOL_HPP + +#include +#include +#include +#include +#include +#include + +// This request is sent by the client to the server over a TCP connection. +// The client uses it to perform three functions: +// - To request that data start being sent to a given port. +// - To request that data is no longer sent to a given port. +// - To change the target port to another. +class control_request +{ +public: + // Construct an empty request. Used when receiving. + control_request() + { + } + + // Create a request to start sending data to a given port. + static const control_request start(unsigned short port) + { + return control_request(0, port); + } + + // Create a request to stop sending data to a given port. + static const control_request stop(unsigned short port) + { + return control_request(port, 0); + } + + // Create a request to change the port that data is sent to. + static const control_request change( + unsigned short old_port, unsigned short new_port) + { + return control_request(old_port, new_port); + } + + // Get the old port. Returns 0 for start requests. + unsigned short old_port() const + { + std::istrstream is(data_, encoded_port_size); + unsigned short port = 0; + is >> std::setw(encoded_port_size) >> std::hex >> port; + return port; + } + + // Get the new port. Returns 0 for stop requests. + unsigned short new_port() const + { + std::istrstream is(data_ + encoded_port_size, encoded_port_size); + unsigned short port = 0; + is >> std::setw(encoded_port_size) >> std::hex >> port; + return port; + } + + // Obtain buffers for reading from or writing to a socket. + boost::array to_buffers() + { + boost::array buffers + = { { boost::asio::buffer(data_) } }; + return buffers; + } + +private: + // Construct with specified old and new ports. + control_request(unsigned short old_port, unsigned short new_port) + { + std::ostrstream os(data_, control_request_size); + os << std::setw(encoded_port_size) << std::hex << old_port; + os << std::setw(encoded_port_size) << std::hex << new_port; + } + + // The length in bytes of a control_request and its components. + enum + { + encoded_port_size = 4, // 16-bit port in hex. + control_request_size = encoded_port_size * 2 + }; + + // The encoded request data. + char data_[control_request_size]; +}; + +// This frame is sent from the server to subscribed clients over UDP. +class frame +{ +public: + // The maximum allowable length of the payload. + enum { payload_size = 32 }; + + // Construct an empty frame. Used when receiving. + frame() + { + } + + // Construct a frame with specified frame number and payload. + frame(unsigned long number, const std::string& payload) + { + std::ostrstream os(data_, frame_size); + os << std::setw(encoded_number_size) << std::hex << number; + os << std::setw(payload_size) + << std::setfill(' ') << payload.substr(0, payload_size); + } + + // Get the frame number. + unsigned long number() const + { + std::istrstream is(data_, encoded_number_size); + unsigned long number = 0; + is >> std::setw(encoded_number_size) >> std::hex >> number; + return number; + } + + // Get the payload data. + const std::string payload() const + { + return std::string(data_ + encoded_number_size, payload_size); + } + + // Obtain buffers for reading from or writing to a socket. + boost::array to_buffers() + { + boost::array buffers + = { { boost::asio::buffer(data_) } }; + return buffers; + } + +private: + // The length in bytes of a frame and its components. + enum + { + encoded_number_size = 8, // Frame number in hex. + frame_size = encoded_number_size + payload_size + }; + + // The encoded frame data. + char data_[frame_size]; +}; + +#endif // PORTHOPPER_PROTOCOL_HPP diff --git a/example/porthopper/server.cpp b/example/porthopper/server.cpp new file mode 100644 index 00000000..cda029c4 --- /dev/null +++ b/example/porthopper/server.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "protocol.hpp" + +using boost::asio::ip::tcp; +using boost::asio::ip::udp; + +typedef boost::shared_ptr tcp_socket_ptr; +typedef boost::shared_ptr timer_ptr; +typedef boost::shared_ptr control_request_ptr; + +class server +{ +public: + // Construct the server to wait for incoming control connections. + server(boost::asio::io_service& io_service, unsigned short port) + : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), + timer_(io_service), + udp_socket_(io_service, udp::endpoint(udp::v4(), 0)), + next_frame_number_(1) + { + // Start waiting for a new control connection. + tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_io_service())); + acceptor_.async_accept(*new_socket, + boost::bind(&server::handle_accept, this, + boost::asio::placeholders::error, new_socket)); + + // Start the timer used to generate outgoing frames. + timer_.expires_from_now(boost::posix_time::milliseconds(100)); + timer_.async_wait(boost::bind(&server::handle_timer, this)); + } + + // Handle a new control connection. + void handle_accept(const boost::system::error_code& ec, tcp_socket_ptr socket) + { + if (!ec) + { + // Start receiving control requests on the connection. + control_request_ptr request(new control_request); + boost::asio::async_read(*socket, request->to_buffers(), + boost::bind(&server::handle_control_request, this, + boost::asio::placeholders::error, socket, request)); + + // Start waiting for a new control connection. + tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_io_service())); + acceptor_.async_accept(*new_socket, + boost::bind(&server::handle_accept, this, + boost::asio::placeholders::error, new_socket)); + } + } + + // Handle a new control request. + void handle_control_request(const boost::system::error_code& ec, + tcp_socket_ptr socket, control_request_ptr request) + { + if (!ec) + { + // Delay handling of the control request to simulate network latency. + timer_ptr delay_timer( + new boost::asio::deadline_timer(acceptor_.get_io_service())); + delay_timer->expires_from_now(boost::posix_time::seconds(2)); + delay_timer->async_wait( + boost::bind(&server::handle_control_request_timer, this, + socket, request, delay_timer)); + } + } + + void handle_control_request_timer(tcp_socket_ptr socket, + control_request_ptr request, timer_ptr delay_timer) + { + // Determine what address this client is connected from, since + // subscriptions must be stored on the server as a complete endpoint, not + // just a port. We use the non-throwing overload of remote_endpoint() since + // it may fail if the socket is no longer connected. + boost::system::error_code ec; + tcp::endpoint remote_endpoint = socket->remote_endpoint(ec); + if (!ec) + { + // Remove old port subscription, if any. + if (unsigned short old_port = request->old_port()) + { + udp::endpoint old_endpoint(remote_endpoint.address(), old_port); + subscribers_.erase(old_endpoint); + std::cout << "Removing subscription " << old_endpoint << std::endl; + } + + // Add new port subscription, if any. + if (unsigned short new_port = request->new_port()) + { + udp::endpoint new_endpoint(remote_endpoint.address(), new_port); + subscribers_.insert(new_endpoint); + std::cout << "Adding subscription " << new_endpoint << std::endl; + } + } + + // Wait for next control request on this connection. + boost::asio::async_read(*socket, request->to_buffers(), + boost::bind(&server::handle_control_request, this, + boost::asio::placeholders::error, socket, request)); + } + + // Every time the timer fires we will generate a new frame and send it to all + // subscribers. + void handle_timer() + { + // Generate payload. + double x = next_frame_number_ * 0.2; + double y = std::sin(x); + int char_index = static_cast((y + 1.0) * (frame::payload_size / 2)); + std::string payload; + for (int i = 0; i < frame::payload_size; ++i) + payload += (i == char_index ? '*' : '.'); + + // Create the frame to be sent to all subscribers. + frame f(next_frame_number_++, payload); + + // Send frame to all subscribers. We can use synchronous calls here since + // UDP send operations typically do not block. + std::set::iterator j; + for (j = subscribers_.begin(); j != subscribers_.end(); ++j) + { + boost::system::error_code ec; + udp_socket_.send_to(f.to_buffers(), *j, 0, ec); + } + + // Wait for next timeout. + timer_.expires_from_now(boost::posix_time::milliseconds(100)); + timer_.async_wait(boost::bind(&server::handle_timer, this)); + } + +private: + // The acceptor used to accept incoming control connections. + tcp::acceptor acceptor_; + + // The timer used for generating data. + boost::asio::deadline_timer timer_; + + // The socket used to send data to subscribers. + udp::socket udp_socket_; + + // The next frame number. + unsigned long next_frame_number_; + + // The set of endpoints that are subscribed. + std::set subscribers_; +}; + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: server \n"; + return 1; + } + + boost::asio::io_service io_service; + + using namespace std; // For atoi. + server s(io_service, atoi(argv[1])); + + io_service.run(); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; +} diff --git a/include/boost/asio.hpp b/include/boost/asio.hpp index a6da3314..632b1442 100644 --- a/include/boost/asio.hpp +++ b/include/boost/asio.hpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -32,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -58,9 +62,23 @@ #include #include #include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include +#include #include +#include +#include +#include #include #include #include @@ -68,6 +86,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include +#include #endif // BOOST_ASIO_HPP diff --git a/include/boost/asio/basic_io_object.hpp b/include/boost/asio/basic_io_object.hpp index 339b59c7..1cbf9bb3 100644 --- a/include/boost/asio/basic_io_object.hpp +++ b/include/boost/asio/basic_io_object.hpp @@ -64,6 +64,10 @@ public: protected: /// Construct a basic_io_object. + /** + * Performs: + * @code service.construct(implementation); @endcode + */ explicit basic_io_object(boost::asio::io_service& io_service) : service(boost::asio::use_service(io_service)) { @@ -71,15 +75,19 @@ protected: } /// Protected destructor to prevent deletion through this type. + /** + * Performs: + * @code service.destroy(implementation); @endcode + */ ~basic_io_object() { service.destroy(implementation); } - // The backend service implementation. + /// The service associated with the I/O object. service_type& service; - // The underlying native implementation. + /// The underlying implementation of the I/O object. implementation_type implementation; }; diff --git a/include/boost/asio/basic_raw_socket.hpp b/include/boost/asio/basic_raw_socket.hpp new file mode 100644 index 00000000..1ba55587 --- /dev/null +++ b/include/boost/asio/basic_raw_socket.hpp @@ -0,0 +1,800 @@ +// +// basic_raw_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_RAW_SOCKET_HPP +#define BOOST_ASIO_BASIC_RAW_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Provides raw-oriented socket functionality. +/** + * The basic_raw_socket class template provides asynchronous and blocking + * raw-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template > +class basic_raw_socket + : public basic_socket +{ +public: + /// The native representation of a socket. + typedef typename RawSocketService::native_type native_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_raw_socket without opening it. + /** + * This constructor creates a raw socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + */ + explicit basic_raw_socket(boost::asio::io_service& io_service) + : basic_socket(io_service) + { + } + + /// Construct and open a basic_raw_socket. + /** + * This constructor creates and opens a raw socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket(io_service, protocol) + { + } + + /// Construct a basic_raw_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a raw socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param endpoint An endpoint on the local machine to which the raw + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket(io_service, endpoint) + { + } + + /// Construct a basic_raw_socket on an existing native socket. + /** + * This constructor creates a raw socket object to hold an existing + * native socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_type& native_socket) + : basic_socket( + io_service, protocol, native_socket) + { + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code socket.send(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.send(this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.send( + this->implementation, buffers, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->service.send(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected raw + * socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send(const ConstBufferSequence& buffers, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected raw + * socket. + */ + template + void async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, flags, handler); + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.send_to(boost::asio::buffer(data, size), destination); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination) + { + boost::system::error_code ec; + std::size_t s = this->service.send_to( + this->implementation, buffers, destination, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.send_to( + this->implementation, buffers, destination, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->service.send_to(this->implementation, + buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send raw data to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_send_to( + * boost::asio::buffer(data, size), destination, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, WriteHandler handler) + { + this->service.async_send_to(this->implementation, buffers, destination, 0, + handler); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send raw data to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template + void async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + WriteHandler handler) + { + this->service.async_send_to(this->implementation, buffers, destination, + flags, handler); + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.receive(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->service.receive(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the raw + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * raw socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the raw + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * raw socket. + */ + template + void async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, flags, handler); + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * boost::asio::ip::udp::endpoint sender_endpoint; + * socket.receive_from( + * boost::asio::buffer(data, size), sender_endpoint); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint) + { + boost::system::error_code ec; + std::size_t s = this->service.receive_from( + this->implementation, buffers, sender_endpoint, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.receive_from( + this->implementation, buffers, sender_endpoint, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->service.receive_from(this->implementation, buffers, + sender_endpoint, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive raw data. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.async_receive_from( + * boost::asio::buffer(data, size), 0, sender_endpoint, handler); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, ReadHandler handler) + { + this->service.async_receive_from(this->implementation, buffers, + sender_endpoint, 0, handler); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive raw data. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template + void async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + ReadHandler handler) + { + this->service.async_receive_from(this->implementation, buffers, + sender_endpoint, flags, handler); + } +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_RAW_SOCKET_HPP diff --git a/include/boost/asio/basic_serial_port.hpp b/include/boost/asio/basic_serial_port.hpp new file mode 100644 index 00000000..a94e9872 --- /dev/null +++ b/include/boost/asio/basic_serial_port.hpp @@ -0,0 +1,610 @@ +// +// basic_serial_port.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SERIAL_PORT_HPP +#define BOOST_ASIO_BASIC_SERIAL_PORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { + +/// Provides serial port functionality. +/** + * The basic_serial_port class template provides functionality that is common + * to all serial ports. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_serial_port + : public basic_io_object, + public serial_port_base +{ +public: + /// The native representation of a serial port. + typedef typename SerialPortService::native_type native_type; + + /// A basic_serial_port is always the lowest layer. + typedef basic_serial_port lowest_layer_type; + + /// Construct a basic_serial_port without opening it. + /** + * This constructor creates a serial port without opening it. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param device The platform-specific device name for this serial + * port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service, + const char* device) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.open(this->implementation, device, ec); + boost::asio::detail::throw_error(ec); + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param device The platform-specific device name for this serial + * port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service, + const std::string& device) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.open(this->implementation, device, ec); + boost::asio::detail::throw_error(ec); + } + + /// Construct a basic_serial_port on an existing native serial port. + /** + * This constructor creates a serial port object to hold an existing native + * serial port. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param native_serial_port A native serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_serial_port(boost::asio::io_service& io_service, + const native_type& native_serial_port) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_serial_port, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_serial_port cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Open the serial port using the specified device name. + /** + * This function opens the serial port for the specified device name. + * + * @param device The platform-specific device name. + * + * @throws boost::system::system_error Thrown on failure. + */ + void open(const std::string& device) + { + boost::system::error_code ec; + this->service.open(this->implementation, device, ec); + boost::asio::detail::throw_error(ec); + } + + /// Open the serial port using the specified device name. + /** + * This function opens the serial port using the given platform-specific + * device name. + * + * @param device The platform-specific device name. + * + * @param ec Set the indicate what error occurred, if any. + */ + boost::system::error_code open(const std::string& device, + boost::system::error_code& ec) + { + return this->service.open(this->implementation, device, ec); + } + + /// Assign an existing native serial port to the serial port. + /* + * This function opens the serial port to hold an existing native serial port. + * + * @param native_serial_port A native serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_type& native_serial_port) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_serial_port, ec); + boost::asio::detail::throw_error(ec); + } + + /// Assign an existing native serial port to the serial port. + /* + * This function opens the serial port to hold an existing native serial port. + * + * @param native_serial_port A native serial port. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const native_type& native_serial_port, + boost::system::error_code& ec) + { + return this->service.assign(this->implementation, native_serial_port, ec); + } + + /// Determine whether the serial port is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the serial port. + /** + * This function is used to close the serial port. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->service.close(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Close the serial port. + /** + * This function is used to close the serial port. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native serial port representation. + /** + * This function may be used to obtain the underlying representation of the + * serial port. This is intended to allow access to native serial port + * functionality that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the serial port. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the serial port. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Send a break sequence to the serial port. + /** + * This function causes a break sequence of platform-specific duration to be + * sent out the serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + void send_break() + { + boost::system::error_code ec; + this->service.send_break(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Send a break sequence to the serial port. + /** + * This function causes a break sequence of platform-specific duration to be + * sent out the serial port. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code send_break(boost::system::error_code& ec) + { + return this->service.send_break(this->implementation, ec); + } + + /// Set an option on the serial port. + /** + * This function is used to set an option on the serial port. + * + * @param option The option value to be set on the serial port. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template + void set_option(const SettableSerialPortOption& option) + { + boost::system::error_code ec; + this->service.set_option(this->implementation, option, ec); + boost::asio::detail::throw_error(ec); + } + + /// Set an option on the serial port. + /** + * This function is used to set an option on the serial port. + * + * @param option The option value to be set on the serial port. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template + boost::system::error_code set_option(const SettableSerialPortOption& option, + boost::system::error_code& ec) + { + return this->service.set_option(this->implementation, option, ec); + } + + /// Get an option from the serial port. + /** + * This function is used to get the current value of an option on the serial + * port. + * + * @param option The option value to be obtained from the serial port. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template + void get_option(GettableSerialPortOption& option) + { + boost::system::error_code ec; + this->service.get_option(this->implementation, option, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get an option from the serial port. + /** + * This function is used to get the current value of an option on the serial + * port. + * + * @param option The option value to be obtained from the serial port. + * + * @param ec Set to indicate what error occured, if any. + * + * @sa GettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template + boost::system::error_code get_option(GettableSerialPortOption& option, + boost::system::error_code& ec) + { + return this->service.get_option(this->implementation, option, ec); + } + + /// Write some data to the serial port. + /** + * This function is used to write data to the serial port. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the serial port. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the serial port. + /** + * This function is used to write data to the serial port. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the serial port. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the serial port. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the serial port. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the serial port. + /** + * This function is used to read data from the serial port. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the serial port. + /** + * This function is used to read data from the serial port. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the serial port. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP diff --git a/include/boost/asio/basic_streambuf.hpp b/include/boost/asio/basic_streambuf.hpp index 5e10cd93..e9eafa81 100644 --- a/include/boost/asio/basic_streambuf.hpp +++ b/include/boost/asio/basic_streambuf.hpp @@ -101,11 +101,9 @@ public: /// Move the start of the get area by the specified number of characters. void consume(std::size_t n) { - while (n > 0) - { - sbumpc(); - --n; - } + if (gptr() + n > pptr()) + n = pptr() - gptr(); + gbump(static_cast(n)); } protected: diff --git a/include/boost/asio/buffer.hpp b/include/boost/asio/buffer.hpp index 02b9a9f8..fdbc2b38 100644 --- a/include/boost/asio/buffer.hpp +++ b/include/boost/asio/buffer.hpp @@ -379,6 +379,33 @@ public: } }; +/// An implementation of both the ConstBufferSequence and MutableBufferSequence +/// concepts to represent a null buffer sequence. +class null_buffers +{ +public: + /// The type for each element in the list of buffers. + typedef mutable_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const mutable_buffer* const_iterator; + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return &buf_; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return &buf_; + } + +private: + mutable_buffer buf_; +}; + #if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) namespace detail { diff --git a/include/boost/asio/buffers_iterator.hpp b/include/boost/asio/buffers_iterator.hpp new file mode 100644 index 00000000..2a88d38b --- /dev/null +++ b/include/boost/asio/buffers_iterator.hpp @@ -0,0 +1,320 @@ +// +// buffers_iterator.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERS_ITERATOR_HPP +#define BOOST_ASIO_BUFFERS_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { + +namespace detail +{ + template + struct buffers_iterator_types_helper; + + template <> + struct buffers_iterator_types_helper + { + typedef const_buffer buffer_type; + template + struct byte_type + { + typedef typename boost::add_const::type type; + }; + }; + + template <> + struct buffers_iterator_types_helper + { + typedef mutable_buffer buffer_type; + template + struct byte_type + { + typedef ByteType type; + }; + }; + + template + struct buffers_iterator_types + { + enum + { + is_mutable = boost::is_convertible< + typename BufferSequence::value_type, mutable_buffer>::value + }; + typedef buffers_iterator_types_helper helper; + typedef typename helper::buffer_type buffer_type; + typedef typename helper::template byte_type::type byte_type; + }; +} + +/// A random access iterator over the bytes in a buffer sequence. +template +class buffers_iterator + : public boost::iterator_facade< + buffers_iterator, + typename detail::buffers_iterator_types< + BufferSequence, ByteType>::byte_type, + boost::random_access_traversal_tag> +{ +private: + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::buffer_type buffer_type; + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::byte_type byte_type; + +public: + /// Default constructor. Creates an iterator in an undefined state. + buffers_iterator() + : current_buffer_(), + current_buffer_position_(0), + begin_(), + current_(), + end_(), + position_(0) + { + } + + /// Construct an iterator representing the beginning of the buffers' data. + static buffers_iterator begin(const BufferSequence& buffers) + { + buffers_iterator new_iter; + new_iter.begin_ = buffers.begin(); + new_iter.current_ = buffers.begin(); + new_iter.end_ = buffers.end(); + while (new_iter.current_ != new_iter.end_) + { + new_iter.current_buffer_ = *new_iter.current_; + if (boost::asio::buffer_size(new_iter.current_buffer_) > 0) + break; + ++new_iter.current_; + } + return new_iter; + } + + /// Construct an iterator representing the end of the buffers' data. + static buffers_iterator end(const BufferSequence& buffers) + { + buffers_iterator new_iter; + new_iter.begin_ = buffers.begin(); + new_iter.current_ = buffers.begin(); + new_iter.end_ = buffers.end(); + while (new_iter.current_ != new_iter.end_) + { + buffer_type buffer = *new_iter.current_; + new_iter.position_ += boost::asio::buffer_size(buffer); + ++new_iter.current_; + } + return new_iter; + } + +private: + friend class boost::iterator_core_access; + + // Dereference the iterator. + byte_type& dereference() const + { + return buffer_cast(current_buffer_)[current_buffer_position_]; + } + + // Compare two iterators for equality. + bool equal(const buffers_iterator& other) const + { + return position_ == other.position_; + } + + // Increment the iterator. + void increment() + { + BOOST_ASSERT(current_ != end_ && "iterator out of bounds"); + ++position_; + + // Check if the increment can be satisfied by the current buffer. + ++current_buffer_position_; + if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_)) + return; + + // Find the next non-empty buffer. + ++current_; + current_buffer_position_ = 0; + while (current_ != end_) + { + current_buffer_ = *current_; + if (boost::asio::buffer_size(current_buffer_) > 0) + return; + ++current_; + } + } + + // Decrement the iterator. + void decrement() + { + BOOST_ASSERT(position_ > 0 && "iterator out of bounds"); + --position_; + + // Check if the decrement can be satisfied by the current buffer. + if (current_buffer_position_ != 0) + { + --current_buffer_position_; + return; + } + + // Find the previous non-empty buffer. + typename BufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + buffer_type buffer = *iter; + std::size_t buffer_size = boost::asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size - 1; + return; + } + } + } + + // Advance the iterator by the specified distance. + void advance(std::ptrdiff_t n) + { + if (n > 0) + { + BOOST_ASSERT(current_ != end_ && "iterator out of bounds"); + for (;;) + { + std::ptrdiff_t current_buffer_balance + = boost::asio::buffer_size(current_buffer_) + - current_buffer_position_; + + // Check if the advance can be satisfied by the current buffer. + if (current_buffer_balance > n) + { + position_ += n; + current_buffer_position_ += n; + return; + } + + // Update position. + n -= current_buffer_balance; + position_ += current_buffer_balance; + + // Move to next buffer. If it is empty then it will be skipped on the + // next iteration of this loop. + if (++current_ == end_) + { + BOOST_ASSERT(n == 0 && "iterator out of bounds"); + current_buffer_ = buffer_type(); + current_buffer_position_ = 0; + return; + } + current_buffer_ = *current_; + current_buffer_position_ = 0; + } + } + else if (n < 0) + { + std::size_t abs_n = -n; + BOOST_ASSERT(position_ >= abs_n && "iterator out of bounds"); + for (;;) + { + // Check if the advance can be satisfied by the current buffer. + if (current_buffer_position_ >= abs_n) + { + position_ -= abs_n; + current_buffer_position_ -= abs_n; + return; + } + + // Update position. + abs_n -= current_buffer_position_; + position_ -= current_buffer_position_; + + // Check if we've reached the beginning of the buffers. + if (current_ == begin_) + { + BOOST_ASSERT(abs_n == 0 && "iterator out of bounds"); + current_buffer_position_ = 0; + return; + } + + // Find the previous non-empty buffer. + typename BufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + buffer_type buffer = *iter; + std::size_t buffer_size = boost::asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size; + break; + } + } + } + } + } + + // Determine the distance between two iterators. + std::ptrdiff_t distance_to(const buffers_iterator& other) const + { + return other.position_ - position_; + } + + buffer_type current_buffer_; + std::size_t current_buffer_position_; + typename BufferSequence::const_iterator begin_; + typename BufferSequence::const_iterator current_; + typename BufferSequence::const_iterator end_; + std::size_t position_; +}; + +/// Construct an iterator representing the beginning of the buffers' data. +template +inline buffers_iterator buffers_begin( + const BufferSequence& buffers) +{ + return buffers_iterator::begin(buffers); +} + +/// Construct an iterator representing the end of the buffers' data. +template +inline buffers_iterator buffers_end( + const BufferSequence& buffers) +{ + return buffers_iterator::end(buffers); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFERS_ITERATOR_HPP diff --git a/include/boost/asio/detail/consuming_buffers.hpp b/include/boost/asio/detail/consuming_buffers.hpp index de03e6dc..f078df2d 100644 --- a/include/boost/asio/detail/consuming_buffers.hpp +++ b/include/boost/asio/detail/consuming_buffers.hpp @@ -24,6 +24,8 @@ #include #include +#include + namespace boost { namespace asio { namespace detail { @@ -198,6 +200,24 @@ private: typename Buffers::const_iterator begin_remainder_; }; +// Specialisation for null_buffers to ensure that the null_buffers type is +// always passed through to the underlying read or write operation. +template +class consuming_buffers + : public boost::asio::null_buffers +{ +public: + consuming_buffers(const boost::asio::null_buffers&) + { + // No-op. + } + + void consume(std::size_t) + { + // No-op. + } +}; + } // namespace detail } // namespace asio } // namespace boost diff --git a/include/boost/asio/detail/deadline_timer_service.hpp b/include/boost/asio/detail/deadline_timer_service.hpp index 64b4809c..76fd2d0f 100644 --- a/include/boost/asio/detail/deadline_timer_service.hpp +++ b/include/boost/asio/detail/deadline_timer_service.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -154,25 +155,25 @@ public: } template - class wait_handler + class wait_handler : + public handler_base_from_member { public: wait_handler(boost::asio::io_service& io_service, Handler handler) - : io_service_(io_service), - work_(io_service), - handler_(handler) + : handler_base_from_member(handler), + io_service_(io_service), + work_(io_service) { } void operator()(const boost::system::error_code& result) { - io_service_.post(detail::bind_handler(handler_, result)); + io_service_.post(detail::bind_handler(this->handler_, result)); } private: boost::asio::io_service& io_service_; boost::asio::io_service::work work_; - Handler handler_; }; // Start an asynchronous wait on the timer. diff --git a/include/boost/asio/detail/descriptor_ops.hpp b/include/boost/asio/detail/descriptor_ops.hpp new file mode 100644 index 00000000..4880d4fb --- /dev/null +++ b/include/boost/asio/detail/descriptor_ops.hpp @@ -0,0 +1,140 @@ +// +// descriptor_ops.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP +#define BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace boost { +namespace asio { +namespace detail { +namespace descriptor_ops { + +inline void clear_error(boost::system::error_code& ec) +{ + errno = 0; + ec = boost::system::error_code(); +} + +template +inline ReturnType error_wrapper(ReturnType return_value, + boost::system::error_code& ec) +{ + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); + return return_value; +} + +inline int open(const char* path, int flags, boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::open(path, flags), ec); +} + +inline int close(int d, boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::close(d), ec); +} + +typedef iovec buf; + +inline void init_buf(buf& b, void* data, size_t size) +{ + b.iov_base = data; + b.iov_len = size; +} + +inline void init_buf(buf& b, const void* data, size_t size) +{ + b.iov_base = const_cast(data); + b.iov_len = size; +} + +inline int scatter_read(int d, buf* bufs, size_t count, + boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::readv(d, bufs, static_cast(count)), ec); +} + +inline int gather_write(int d, const buf* bufs, size_t count, + boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::writev(d, bufs, static_cast(count)), ec); +} + +inline int ioctl(int d, long cmd, ioctl_arg_type* arg, + boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::ioctl(d, cmd, arg), ec); +} + +inline int fcntl(int d, long cmd, boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::fcntl(d, cmd), ec); +} + +inline int fcntl(int d, long cmd, long arg, boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::fcntl(d, cmd, arg), ec); +} + +inline int poll_read(int d, boost::system::error_code& ec) +{ + clear_error(ec); + pollfd fds; + fds.fd = d; + fds.events = POLLIN; + fds.revents = 0; + clear_error(ec); + return error_wrapper(::poll(&fds, 1, -1), ec); +} + +inline int poll_write(int d, boost::system::error_code& ec) +{ + clear_error(ec); + pollfd fds; + fds.fd = d; + fds.events = POLLOUT; + fds.revents = 0; + clear_error(ec); + return error_wrapper(::poll(&fds, 1, -1), ec); +} + +} // namespace descriptor_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP diff --git a/include/boost/asio/detail/dev_poll_reactor.hpp b/include/boost/asio/detail/dev_poll_reactor.hpp index 81b8a565..aa863d8b 100644 --- a/include/boost/asio/detail/dev_poll_reactor.hpp +++ b/include/boost/asio/detail/dev_poll_reactor.hpp @@ -54,6 +54,11 @@ class dev_poll_reactor : public boost::asio::detail::service_base > { public: + // Per-descriptor data. + struct per_descriptor_data + { + }; + // Constructor. dev_poll_reactor(boost::asio::io_service& io_service) : boost::asio::detail::service_base< @@ -116,11 +121,11 @@ public: for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->destroy_timers(); timer_queues_.clear(); - } + } // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type descriptor) + int register_descriptor(socket_type, per_descriptor_data&) { return 0; } @@ -128,16 +133,27 @@ public: // Start a new read operation. The handler object will be invoked when the // given descriptor is ready to be read, or an error has occurred. template - void start_read_op(socket_type descriptor, Handler handler) + void start_read_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool allow_speculative_read = true) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!read_op_queue_.has_operation(descriptor)) - if (handler(boost::system::error_code())) - return; + if (allow_speculative_read) + { + if (!read_op_queue_.has_operation(descriptor)) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + } if (read_op_queue_.enqueue_operation(descriptor, handler)) { @@ -154,16 +170,27 @@ public: // Start a new write operation. The handler object will be invoked when the // given descriptor is ready to be written, or an error has occurred. template - void start_write_op(socket_type descriptor, Handler handler) + void start_write_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool allow_speculative_write = true) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!write_op_queue_.has_operation(descriptor)) - if (handler(boost::system::error_code())) - return; + if (allow_speculative_write) + { + if (!write_op_queue_.has_operation(descriptor)) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + } if (write_op_queue_.enqueue_operation(descriptor, handler)) { @@ -180,7 +207,8 @@ public: // Start a new exception operation. The handler object will be invoked when // the given descriptor has exception information, or an error has occurred. template - void start_except_op(socket_type descriptor, Handler handler) + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { boost::asio::detail::mutex::scoped_lock lock(mutex_); @@ -199,26 +227,25 @@ public: } } - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception + // Start a new write operation. The handler object will be invoked when the // information available, or an error has occurred. template - void start_write_and_except_ops(socket_type descriptor, Handler handler) + void start_connect_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - bool need_mod = write_op_queue_.enqueue_operation(descriptor, handler); - need_mod = except_op_queue_.enqueue_operation(descriptor, handler) - && need_mod; - if (need_mod) + if (write_op_queue_.enqueue_operation(descriptor, handler)) { ::pollfd& ev = add_pending_event_change(descriptor); - ev.events = POLLOUT | POLLPRI | POLLERR | POLLHUP; + ev.events = POLLOUT | POLLERR | POLLHUP; if (read_op_queue_.has_operation(descriptor)) ev.events |= POLLIN; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= POLLPRI; interrupter_.interrupt(); } } @@ -226,25 +253,15 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor) + void cancel_ops(socket_type descriptor, per_descriptor_data&) { boost::asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); } - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // dev_poll_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor) + void close_descriptor(socket_type descriptor, per_descriptor_data&) { boost::asio::detail::mutex::scoped_lock lock(mutex_); @@ -314,16 +331,16 @@ private: // Dispatch any operation cancellations that were made while the select // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->dispatch_cancellations(); // Check if the thread is supposed to stop. if (stop_thread_) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -332,7 +349,7 @@ private: if (!block && read_op_queue_.empty() && write_op_queue_.empty() && except_op_queue_.empty() && all_timer_queues_are_empty()) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -348,9 +365,9 @@ private: int descriptor = pending_event_changes_[i].fd; boost::system::error_code ec = boost::system::error_code( errno, boost::asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } pending_event_changes_.clear(); @@ -371,7 +388,7 @@ private: lock.lock(); wait_in_progress_ = false; - // Block signals while dispatching operations. + // Block signals while performing operations. boost::asio::detail::signal_blocker sb; // Dispatch the waiting events. @@ -392,17 +409,17 @@ private: // Exception operations must be processed first to ensure that any // out-of-band data is read before normal data. if (events[i].events & (POLLPRI | POLLERR | POLLHUP)) - more_except = except_op_queue_.dispatch_operation(descriptor, ec); + more_except = except_op_queue_.perform_operation(descriptor, ec); else more_except = except_op_queue_.has_operation(descriptor); if (events[i].events & (POLLIN | POLLERR | POLLHUP)) - more_reads = read_op_queue_.dispatch_operation(descriptor, ec); + more_reads = read_op_queue_.perform_operation(descriptor, ec); else more_reads = read_op_queue_.has_operation(descriptor); if (events[i].events & (POLLOUT | POLLERR | POLLHUP)) - more_writes = write_op_queue_.dispatch_operation(descriptor, ec); + more_writes = write_op_queue_.perform_operation(descriptor, ec); else more_writes = write_op_queue_.has_operation(descriptor); @@ -437,16 +454,16 @@ private: { ec = boost::system::error_code(errno, boost::asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } } } - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) { timer_queues_[i]->dispatch_timers(); @@ -458,7 +475,7 @@ private: cancel_ops_unlocked(pending_cancellations_[i]); pending_cancellations_.clear(); - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); } // Run the select loop in the thread. @@ -558,16 +575,16 @@ private: // destructors may make calls back into this reactor. We make a copy of the // vector of timer queues since the original may be modified while the lock // is not held. - void cleanup_operations_and_timers( + void complete_operations_and_timers( boost::asio::detail::mutex::scoped_lock& lock) { timer_queues_for_cleanup_ = timer_queues_; lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->cleanup_timers(); + timer_queues_for_cleanup_[i]->complete_timers(); } // Add a pending event entry for the given descriptor. diff --git a/include/boost/asio/detail/epoll_reactor.hpp b/include/boost/asio/detail/epoll_reactor.hpp index 3edd599c..04609aff 100644 --- a/include/boost/asio/detail/epoll_reactor.hpp +++ b/include/boost/asio/detail/epoll_reactor.hpp @@ -54,6 +54,13 @@ class epoll_reactor : public boost::asio::detail::service_base > { public: + // Per-descriptor data. + struct per_descriptor_data + { + bool allow_speculative_read; + bool allow_speculative_write; + }; + // Constructor. epoll_reactor(boost::asio::io_service& io_service) : boost::asio::detail::service_base >(io_service), @@ -119,10 +126,14 @@ public: // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type descriptor) + int register_descriptor(socket_type descriptor, + per_descriptor_data& descriptor_data) { // No need to lock according to epoll documentation. + descriptor_data.allow_speculative_read = true; + descriptor_data.allow_speculative_write = true; + epoll_event ev = { 0, { 0 } }; ev.events = 0; ev.data.fd = descriptor; @@ -135,16 +146,47 @@ public: // Start a new read operation. The handler object will be invoked when the // given descriptor is ready to be read, or an error has occurred. template - void start_read_op(socket_type descriptor, Handler handler) + void start_read_op(socket_type descriptor, + per_descriptor_data& descriptor_data, + Handler handler, bool allow_speculative_read = true) { + if (allow_speculative_read && descriptor_data.allow_speculative_read) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative read in this function. + allow_speculative_read = false; + } + boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!read_op_queue_.has_operation(descriptor)) - if (handler(boost::system::error_code())) + if (!allow_speculative_read) + need_epoll_wait_ = true; + else if (!read_op_queue_.has_operation(descriptor)) + { + // Speculative reads are ok as there are no queued read operations. + descriptor_data.allow_speculative_read = true; + + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); return; + } + } + + // Speculative reads are not ok as there will be queued read operations. + descriptor_data.allow_speculative_read = false; if (read_op_queue_.enqueue_operation(descriptor, handler)) { @@ -163,7 +205,7 @@ public: { boost::system::error_code ec(errno, boost::asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -171,16 +213,47 @@ public: // Start a new write operation. The handler object will be invoked when the // given descriptor is ready to be written, or an error has occurred. template - void start_write_op(socket_type descriptor, Handler handler) + void start_write_op(socket_type descriptor, + per_descriptor_data& descriptor_data, + Handler handler, bool allow_speculative_write = true) { + if (allow_speculative_write && descriptor_data.allow_speculative_write) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative write in this function. + allow_speculative_write = false; + } + boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!write_op_queue_.has_operation(descriptor)) - if (handler(boost::system::error_code())) + if (!allow_speculative_write) + need_epoll_wait_ = true; + else if (!write_op_queue_.has_operation(descriptor)) + { + // Speculative writes are ok as there are no queued write operations. + descriptor_data.allow_speculative_write = true; + + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); return; + } + } + + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; if (write_op_queue_.enqueue_operation(descriptor, handler)) { @@ -199,7 +272,7 @@ public: { boost::system::error_code ec(errno, boost::asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -207,7 +280,8 @@ public: // Start a new exception operation. The handler object will be invoked when // the given descriptor has exception information, or an error has occurred. template - void start_except_op(socket_type descriptor, Handler handler) + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { boost::asio::detail::mutex::scoped_lock lock(mutex_); @@ -231,31 +305,34 @@ public: { boost::system::error_code ec(errno, boost::asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } } - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready for writing or an error has occurred. Speculative + // writes are not allowed. template - void start_write_and_except_ops(socket_type descriptor, Handler handler) + void start_connect_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - bool need_mod = write_op_queue_.enqueue_operation(descriptor, handler); - need_mod = except_op_queue_.enqueue_operation(descriptor, handler) - && need_mod; - if (need_mod) + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; + + if (write_op_queue_.enqueue_operation(descriptor, handler)) { epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLOUT | EPOLLPRI | EPOLLERR | EPOLLHUP; + ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; if (read_op_queue_.has_operation(descriptor)) ev.events |= EPOLLIN; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLPRI; ev.data.fd = descriptor; int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); @@ -265,8 +342,7 @@ public: { boost::system::error_code ec(errno, boost::asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -274,25 +350,15 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor) + void cancel_ops(socket_type descriptor, per_descriptor_data&) { boost::asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); } - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // epoll_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor) + void close_descriptor(socket_type descriptor, per_descriptor_data&) { boost::asio::detail::mutex::scoped_lock lock(mutex_); @@ -361,16 +427,16 @@ private: // Dispatch any operation cancellations that were made while the select // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->dispatch_cancellations(); // Check if the thread is supposed to stop. if (stop_thread_) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -379,7 +445,7 @@ private: if (!block && read_op_queue_.empty() && write_op_queue_.empty() && except_op_queue_.empty() && all_timer_queues_are_empty()) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -396,7 +462,7 @@ private: lock.lock(); wait_in_progress_ = false; - // Block signals while dispatching operations. + // Block signals while performing operations. boost::asio::detail::signal_blocker sb; // Dispatch the waiting events. @@ -417,17 +483,17 @@ private: // Exception operations must be processed first to ensure that any // out-of-band data is read before normal data. if (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)) - more_except = except_op_queue_.dispatch_operation(descriptor, ec); + more_except = except_op_queue_.perform_operation(descriptor, ec); else more_except = except_op_queue_.has_operation(descriptor); if (events[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) - more_reads = read_op_queue_.dispatch_operation(descriptor, ec); + more_reads = read_op_queue_.perform_operation(descriptor, ec); else more_reads = read_op_queue_.has_operation(descriptor); if (events[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) - more_writes = write_op_queue_.dispatch_operation(descriptor, ec); + more_writes = write_op_queue_.perform_operation(descriptor, ec); else more_writes = write_op_queue_.has_operation(descriptor); @@ -461,16 +527,16 @@ private: { ec = boost::system::error_code(errno, boost::asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } } } - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) { timer_queues_[i]->dispatch_timers(); @@ -486,7 +552,7 @@ private: need_epoll_wait_ = !read_op_queue_.empty() || !write_op_queue_.empty() || !except_op_queue_.empty(); - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); } // Run the select loop in the thread. @@ -589,16 +655,16 @@ private: // destructors may make calls back into this reactor. We make a copy of the // vector of timer queues since the original may be modified while the lock // is not held. - void cleanup_operations_and_timers( + void complete_operations_and_timers( boost::asio::detail::mutex::scoped_lock& lock) { timer_queues_for_cleanup_ = timer_queues_; lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->cleanup_timers(); + timer_queues_for_cleanup_[i]->complete_timers(); } // Mutex to protect access to internal data. diff --git a/include/boost/asio/detail/handler_base_from_member.hpp b/include/boost/asio/detail/handler_base_from_member.hpp new file mode 100644 index 00000000..4bd95ed2 --- /dev/null +++ b/include/boost/asio/detail/handler_base_from_member.hpp @@ -0,0 +1,78 @@ +// +// handler_base_from_member.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP +#define BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Base class for classes that need a handler data member. Forwards the custom +// allocation and invocation hooks to the contained handler. +template +class handler_base_from_member +{ +public: + handler_base_from_member(Handler handler) + : handler_(handler) + { + } + +//protected: + Handler handler_; + +protected: + // Protected destructor to prevent deletion through this type. + ~handler_base_from_member() + { + } +}; + +template +inline void* asio_handler_allocate(std::size_t size, + handler_base_from_member* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + handler_base_from_member* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + handler_base_from_member* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP diff --git a/include/boost/asio/detail/handler_queue.hpp b/include/boost/asio/detail/handler_queue.hpp index fc1b6a5b..ccc1b0c0 100644 --- a/include/boost/asio/detail/handler_queue.hpp +++ b/include/boost/asio/detail/handler_queue.hpp @@ -199,6 +199,16 @@ private: this_type* h(static_cast(base)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } private: diff --git a/include/boost/asio/detail/hash_map.hpp b/include/boost/asio/detail/hash_map.hpp index 9cb7c581..e8a0334d 100644 --- a/include/boost/asio/detail/hash_map.hpp +++ b/include/boost/asio/detail/hash_map.hpp @@ -44,6 +44,7 @@ inline std::size_t calculate_hash_value(SOCKET s) } #endif // defined(_WIN64) +// Note: assumes K and V are POD types. template class hash_map : private noncopyable @@ -140,7 +141,7 @@ public: if (it == values_.end()) { buckets_[bucket].first = buckets_[bucket].last = - values_.insert(values_.end(), v); + values_insert(values_.end(), v); return std::pair(buckets_[bucket].last, true); } iterator end = buckets_[bucket].last; @@ -151,7 +152,7 @@ public: return std::pair(it, false); ++it; } - buckets_[bucket].last = values_.insert(end, v); + buckets_[bucket].last = values_insert(end, v); return std::pair(buckets_[bucket].last, true); } @@ -170,7 +171,7 @@ public: else if (is_last) --buckets_[bucket].last; - values_.erase(it); + values_erase(it); } // Remove all entries from the map. @@ -185,9 +186,36 @@ public: } private: + // Insert an element into the values list by splicing from the spares list, + // if a spare is available, and otherwise by inserting a new element. + iterator values_insert(iterator it, const value_type& v) + { + if (spares_.empty()) + { + return values_.insert(it, v); + } + else + { + spares_.front() = v; + values_.splice(it, spares_, spares_.begin()); + return --it; + } + } + + // Erase an element from the values list by splicing it to the spares list. + void values_erase(iterator it) + { + *it = value_type(); + spares_.splice(spares_.begin(), values_, it); + } + // The list of all values in the hash map. std::list values_; + // The list of spare nodes waiting to be recycled. Assumes that POD types only + // are stored in the hash map. + std::list spares_; + // The type for a bucket in the hash table. struct bucket_type { diff --git a/include/boost/asio/detail/indirect_handler_queue.hpp b/include/boost/asio/detail/indirect_handler_queue.hpp new file mode 100644 index 00000000..2775078e --- /dev/null +++ b/include/boost/asio/detail/indirect_handler_queue.hpp @@ -0,0 +1,293 @@ +// +// indirect_handler_queue.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP +#define BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if defined(_MSC_VER) && (_MSC_VER >= 1310) +extern "C" void _ReadWriteBarrier(); +# pragma intrinsic(_ReadWriteBarrier) +#endif // defined(_MSC_VER) && (_MSC_VER >= 1310) + +namespace boost { +namespace asio { +namespace detail { + +class indirect_handler_queue + : private noncopyable +{ +public: + class handler; + + // Element for a node in the queue. + class node + { + public: + node() + : version_(0), + handler_(0), + next_(0) + { + } + + private: + friend class indirect_handler_queue; + unsigned long version_; + handler* handler_; + node* next_; + }; + + // Base class for handlers in the queue. + class handler + : private noncopyable + { + public: + void invoke() + { + invoke_func_(this); + } + + void destroy() + { + destroy_func_(this); + } + + protected: + typedef void (*invoke_func_type)(handler*); + typedef void (*destroy_func_type)(handler*); + + handler(invoke_func_type invoke_func, + destroy_func_type destroy_func) + : node_(new node), + invoke_func_(invoke_func), + destroy_func_(destroy_func) + { + } + + ~handler() + { + if (node_) + delete node_; + } + + private: + friend class indirect_handler_queue; + node* node_; + invoke_func_type invoke_func_; + destroy_func_type destroy_func_; + }; + + // Smart point to manager handler lifetimes. + class scoped_ptr + : private noncopyable + { + public: + explicit scoped_ptr(handler* h) + : handler_(h) + { + } + + ~scoped_ptr() + { + if (handler_) + handler_->destroy(); + } + + handler* get() const + { + return handler_; + } + + handler* release() + { + handler* tmp = handler_; + handler_ = 0; + return tmp; + } + + private: + handler* handler_; + }; + + // Constructor. + indirect_handler_queue() + : front_(new node), + back_(front_), + next_version_(1) + { + } + + // Destructor. + ~indirect_handler_queue() + { + while (front_) + { + node* tmp = front_; + front_ = front_->next_; + delete tmp; + } + } + + // Wrap a handler to be pushed into the queue. + template + static handler* wrap(Handler h) + { + // Allocate and construct an object to wrap the handler. + typedef handler_wrapper value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(h); + handler_ptr ptr(raw_ptr, h); + return ptr.release(); + } + + // Determine whether the queue has something ready to pop. + bool poppable() + { + return front_->next_ != 0; + } + + // The version number at the front of the queue. + unsigned long front_version() + { + return front_->version_; + } + + // The version number at the back of the queue. + unsigned long back_version() + { + return back_->version_; + } + + // Pop a handler from the front of the queue. + handler* pop() + { + node* n = front_; + node* new_front = n->next_; + if (new_front) + { + handler* h = new_front->handler_; + h->node_ = n; + new_front->handler_ = 0; + front_ = new_front; + return h; + } + return 0; + } + + // Push a handler on to the back of the queue. + void push(handler* h) + { + node* n = h->node_; + h->node_ = 0; + n->version_ = next_version_; + next_version_ += 2; + n->handler_ = h; + n->next_ = 0; + memory_barrier(); + back_->next_ = n; + back_ = n; + } + +private: + // Template wrapper for handlers. + template + class handler_wrapper + : public handler + { + public: + handler_wrapper(Handler h) + : handler( + &handler_wrapper::do_call, + &handler_wrapper::do_destroy), + handler_(h) + { + } + + static void do_call(handler* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(h->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Make the upcall. + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + } + + static void do_destroy(handler* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + private: + Handler handler_; + }; + + // Helper function to create a memory barrier. + static void memory_barrier() + { +#if defined(_GLIBCXX_WRITE_MEM_BARRIER) + _GLIBCXX_WRITE_MEM_BARRIER; +#elif defined(_MSC_VER) && (_MSC_VER >= 1310) + _ReadWriteBarrier(); +#else +# error memory barrier required +#endif + } + + // The front of the queue. + node* front_; + + // The back of the queue. + node* back_; + + // The next version counter to be assigned to a node. + unsigned long next_version_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP diff --git a/include/boost/asio/detail/kqueue_reactor.hpp b/include/boost/asio/detail/kqueue_reactor.hpp index 1a1034b0..a6a671a3 100644 --- a/include/boost/asio/detail/kqueue_reactor.hpp +++ b/include/boost/asio/detail/kqueue_reactor.hpp @@ -61,6 +61,13 @@ class kqueue_reactor : public boost::asio::detail::service_base > { public: + // Per-descriptor data. + struct per_descriptor_data + { + bool allow_speculative_read; + bool allow_speculative_write; + }; + // Constructor. kqueue_reactor(boost::asio::io_service& io_service) : boost::asio::detail::service_base< @@ -127,24 +134,58 @@ public: // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type) + int register_descriptor(socket_type, per_descriptor_data& descriptor_data) { + descriptor_data.allow_speculative_read = true; + descriptor_data.allow_speculative_write = true; + return 0; } // Start a new read operation. The handler object will be invoked when the // given descriptor is ready to be read, or an error has occurred. template - void start_read_op(socket_type descriptor, Handler handler) + void start_read_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler, + bool allow_speculative_read = true) { + if (allow_speculative_read && descriptor_data.allow_speculative_read) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative read in this function. + allow_speculative_read = false; + } + boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!read_op_queue_.has_operation(descriptor)) - if (handler(boost::system::error_code())) + if (!allow_speculative_read) + need_kqueue_wait_ = true; + else if (!read_op_queue_.has_operation(descriptor)) + { + // Speculative reads are ok as there are no queued read operations. + descriptor_data.allow_speculative_read = true; + + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); return; + } + } + + // Speculative reads are not ok as there will be queued read operations. + descriptor_data.allow_speculative_read = false; if (read_op_queue_.enqueue_operation(descriptor, handler)) { @@ -154,7 +195,7 @@ public: { boost::system::error_code ec(errno, boost::asio::error::get_system_category()); - read_op_queue_.dispatch_all_operations(descriptor, ec); + read_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -162,16 +203,47 @@ public: // Start a new write operation. The handler object will be invoked when the // given descriptor is ready to be written, or an error has occurred. template - void start_write_op(socket_type descriptor, Handler handler) + void start_write_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler, + bool allow_speculative_write = true) { + if (allow_speculative_write && descriptor_data.allow_speculative_write) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative write in this function. + allow_speculative_write = false; + } + boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; - if (!write_op_queue_.has_operation(descriptor)) - if (handler(boost::system::error_code())) + if (!allow_speculative_write) + need_kqueue_wait_ = true; + else if (!write_op_queue_.has_operation(descriptor)) + { + // Speculative writes are ok as there are no queued write operations. + descriptor_data.allow_speculative_write = true; + + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); return; + } + } + + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; if (write_op_queue_.enqueue_operation(descriptor, handler)) { @@ -181,7 +253,7 @@ public: { boost::system::error_code ec(errno, boost::asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -189,7 +261,8 @@ public: // Start a new exception operation. The handler object will be invoked when // the given descriptor has exception information, or an error has occurred. template - void start_except_op(socket_type descriptor, Handler handler) + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { boost::asio::detail::mutex::scoped_lock lock(mutex_); @@ -207,22 +280,25 @@ public: { boost::system::error_code ec(errno, boost::asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); } } } - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready to be written, or an error has occurred. template - void start_write_and_except_ops(socket_type descriptor, Handler handler) + void start_connect_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) return; + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; + if (write_op_queue_.enqueue_operation(descriptor, handler)) { struct kevent event; @@ -231,23 +307,7 @@ public: { boost::system::error_code ec(errno, boost::asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - - if (except_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - if (read_op_queue_.has_operation(descriptor)) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - boost::system::error_code ec(errno, - boost::asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); } } } @@ -255,25 +315,15 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor) + void cancel_ops(socket_type descriptor, per_descriptor_data&) { boost::asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); } - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // kqueue_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor) + void close_descriptor(socket_type descriptor, per_descriptor_data&) { boost::asio::detail::mutex::scoped_lock lock(mutex_); @@ -344,16 +394,16 @@ private: // Dispatch any operation cancellations that were made while the select // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->dispatch_cancellations(); // Check if the thread is supposed to stop. if (stop_thread_) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -362,7 +412,7 @@ private: if (!block && read_op_queue_.empty() && write_op_queue_.empty() && except_op_queue_.empty() && all_timer_queues_are_empty()) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -382,7 +432,7 @@ private: lock.lock(); wait_in_progress_ = false; - // Block signals while dispatching operations. + // Block signals while performing operations. boost::asio::detail::signal_blocker sb; // Dispatch the waiting events. @@ -402,22 +452,22 @@ private: { boost::system::error_code error( events[i].data, boost::asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, error); - read_op_queue_.dispatch_all_operations(descriptor, error); + except_op_queue_.perform_all_operations(descriptor, error); + read_op_queue_.perform_all_operations(descriptor, error); } else if (events[i].flags & EV_OOBAND) { boost::system::error_code error; - more_except = except_op_queue_.dispatch_operation(descriptor, error); + more_except = except_op_queue_.perform_operation(descriptor, error); if (events[i].data > 0) - more_reads = read_op_queue_.dispatch_operation(descriptor, error); + more_reads = read_op_queue_.perform_operation(descriptor, error); else more_reads = read_op_queue_.has_operation(descriptor); } else { boost::system::error_code error; - more_reads = read_op_queue_.dispatch_operation(descriptor, error); + more_reads = read_op_queue_.perform_operation(descriptor, error); more_except = except_op_queue_.has_operation(descriptor); } @@ -433,8 +483,8 @@ private: { boost::system::error_code error(errno, boost::asio::error::get_system_category()); - except_op_queue_.dispatch_all_operations(descriptor, error); - read_op_queue_.dispatch_all_operations(descriptor, error); + except_op_queue_.perform_all_operations(descriptor, error); + read_op_queue_.perform_all_operations(descriptor, error); } } else if (events[i].filter == EVFILT_WRITE) @@ -445,12 +495,12 @@ private: { boost::system::error_code error( events[i].data, boost::asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, error); + write_op_queue_.perform_all_operations(descriptor, error); } else { boost::system::error_code error; - more_writes = write_op_queue_.dispatch_operation(descriptor, error); + more_writes = write_op_queue_.perform_operation(descriptor, error); } // Update the descriptor in the kqueue. @@ -463,14 +513,14 @@ private: { boost::system::error_code error(errno, boost::asio::error::get_system_category()); - write_op_queue_.dispatch_all_operations(descriptor, error); + write_op_queue_.perform_all_operations(descriptor, error); } } } - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) { timer_queues_[i]->dispatch_timers(); @@ -486,7 +536,7 @@ private: need_kqueue_wait_ = !read_op_queue_.empty() || !write_op_queue_.empty() || !except_op_queue_.empty(); - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); } // Run the select loop in the thread. @@ -587,16 +637,16 @@ private: // destructors may make calls back into this reactor. We make a copy of the // vector of timer queues since the original may be modified while the lock // is not held. - void cleanup_operations_and_timers( + void complete_operations_and_timers( boost::asio::detail::mutex::scoped_lock& lock) { timer_queues_for_cleanup_ = timer_queues_; lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->cleanup_timers(); + timer_queues_for_cleanup_[i]->complete_timers(); } // Mutex to protect access to internal data. diff --git a/include/boost/asio/detail/null_thread.hpp b/include/boost/asio/detail/null_thread.hpp index 5aed2112..507904ba 100644 --- a/include/boost/asio/detail/null_thread.hpp +++ b/include/boost/asio/detail/null_thread.hpp @@ -39,9 +39,12 @@ class null_thread : private noncopyable { public: + // The purpose of the thread. + enum purpose { internal, external }; + // Constructor. template - null_thread(Function f) + null_thread(Function f, purpose = internal) { boost::system::system_error e( boost::asio::error::operation_not_supported, "thread"); diff --git a/include/boost/asio/detail/old_win_sdk_compat.hpp b/include/boost/asio/detail/old_win_sdk_compat.hpp index 35c673a4..5f0aba1d 100644 --- a/include/boost/asio/detail/old_win_sdk_compat.hpp +++ b/include/boost/asio/detail/old_win_sdk_compat.hpp @@ -330,6 +330,11 @@ inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a) # define IPV6_V6ONLY 27 #endif +// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6. +#if !defined(IPPROTO_ICMPV6) +# define IPPROTO_ICMPV6 58 +#endif + #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #include diff --git a/include/boost/asio/detail/posix_thread.hpp b/include/boost/asio/detail/posix_thread.hpp index 1e386184..6dbc3b8f 100644 --- a/include/boost/asio/detail/posix_thread.hpp +++ b/include/boost/asio/detail/posix_thread.hpp @@ -43,9 +43,12 @@ class posix_thread : private noncopyable { public: + // The purpose of the thread. + enum purpose { internal, external }; + // Constructor. template - posix_thread(Function f) + posix_thread(Function f, purpose = internal) : joined_(false) { std::auto_ptr arg(new func(f)); diff --git a/include/boost/asio/detail/push_options.hpp b/include/boost/asio/detail/push_options.hpp index 4e0524dc..47524b25 100644 --- a/include/boost/asio/detail/push_options.hpp +++ b/include/boost/asio/detail/push_options.hpp @@ -87,8 +87,10 @@ # pragma warning (disable:4103) # pragma warning (push) +# pragma warning (disable:4127) # pragma warning (disable:4244) # pragma warning (disable:4355) +# pragma warning (disable:4512) # pragma warning (disable:4675) # if defined(_M_IX86) && defined(_Wp64) // The /Wp64 option is broken. If you want to check 64 bit portability, use a diff --git a/include/boost/asio/detail/reactive_descriptor_service.hpp b/include/boost/asio/detail/reactive_descriptor_service.hpp new file mode 100644 index 00000000..5334f21b --- /dev/null +++ b/include/boost/asio/detail/reactive_descriptor_service.hpp @@ -0,0 +1,711 @@ +// +// reactive_descriptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_descriptor_service + : public boost::asio::detail::service_base< + reactive_descriptor_service > +{ +public: + // The native type of a descriptor. + typedef int native_type; + + // The implementation type of the descriptor. + class implementation_type + : private boost::asio::detail::noncopyable + { + public: + // Default constructor. + implementation_type() + : descriptor_(-1), + flags_(0) + { + } + + private: + // Only this service will have access to the internal values. + friend class reactive_descriptor_service; + + // The native descriptor representation. + int descriptor_; + + enum + { + user_set_non_blocking = 1, // The user wants a non-blocking descriptor. + internal_non_blocking = 2 // The descriptor has been set non-blocking. + }; + + // Flags indicating the current state of the descriptor. + unsigned char flags_; + + // Per-descriptor data used by the reactor. + typename Reactor::per_descriptor_data reactor_data_; + }; + + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + + // Constructor. + reactive_descriptor_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + reactive_descriptor_service >(io_service), + reactor_(boost::asio::use_service(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new descriptor implementation. + void construct(implementation_type& impl) + { + impl.descriptor_ = -1; + impl.flags_ = 0; + } + + // Destroy a descriptor implementation. + void destroy(implementation_type& impl) + { + if (impl.descriptor_ != -1) + { + reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_); + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + ioctl_arg_type non_blocking = 0; + boost::system::error_code ignored_ec; + descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ignored_ec); + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + boost::system::error_code ignored_ec; + descriptor_ops::close(impl.descriptor_, ignored_ec); + + impl.descriptor_ = -1; + } + } + + // Assign a native descriptor to a descriptor implementation. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_descriptor, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_descriptor, impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.descriptor_ = native_descriptor; + impl.flags_ = 0; + ec = boost::system::error_code(); + return ec; + } + + // Determine whether the descriptor is open. + bool is_open(const implementation_type& impl) const + { + return impl.descriptor_ != -1; + } + + // Destroy a descriptor implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_); + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + ioctl_arg_type non_blocking = 0; + boost::system::error_code ignored_ec; + descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ignored_ec); + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + if (descriptor_ops::close(impl.descriptor_, ec) == -1) + return ec; + + impl.descriptor_ = -1; + } + + ec = boost::system::error_code(); + return ec; + } + + // Get the native descriptor representation. + native_type native(const implementation_type& impl) const + { + return impl.descriptor_; + } + + // Cancel all operations associated with the descriptor. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_); + ec = boost::system::error_code(); + return ec; + } + + // Perform an IO control command on the descriptor. + template + boost::system::error_code io_control(implementation_type& impl, + IO_Control_Command& command, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + if (command.name() == static_cast(FIONBIO)) + { + if (command.get()) + impl.flags_ |= implementation_type::user_set_non_blocking; + else + impl.flags_ &= ~implementation_type::user_set_non_blocking; + ec = boost::system::error_code(); + } + else + { + descriptor_ops::ioctl(impl.descriptor_, command.name(), + static_cast(command.data()), ec); + } + return ec; + } + + // Write some data to the descriptor. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + ec = boost::system::error_code(); + return 0; + } + + // Make descriptor non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Send the data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_sent = descriptor_ops::gather_write( + impl.descriptor_, bufs, i, ec); + + // Check if operation succeeded. + if (bytes_sent >= 0) + return bytes_sent; + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_write(impl.descriptor_, ec) < 0) + return 0; + } + } + + // Wait until data can be written without blocking. + size_t write_some(implementation_type& impl, + const null_buffers&, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for descriptor to become ready. + descriptor_ops::poll_write(impl.descriptor_, ec); + + return 0; + } + + template + class write_operation : + public handler_base_from_member + { + public: + write_operation(int descriptor, boost::asio::io_service& io_service, + const ConstBufferSequence& buffers, Handler handler) + : handler_base_from_member(handler), + descriptor_(descriptor), + io_service_(io_service), + work_(io_service), + buffers_(buffers) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers_.begin(); + typename ConstBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Write the data. + int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec); + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + int descriptor_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + ConstBufferSequence buffers_; + }; + + // Start an asynchronous write. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Determine total size of buffers. + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + this->get_io_service().post(bind_handler(handler, + boost::system::error_code(), 0)); + return; + } + + // Make descriptor non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, + write_operation( + impl.descriptor_, this->get_io_service(), buffers, handler)); + } + } + + template + class null_buffers_operation : + public handler_base_from_member + { + public: + null_buffers_operation(boost::asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + work_(io_service) + { + } + + bool perform(boost::system::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + this->handler_, ec, bytes_transferred)); + } + + private: + boost::asio::io_service::work work_; + }; + + // Start an asynchronous wait until data can be written without blocking. + template + void async_write_some(implementation_type& impl, + const null_buffers&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + + // Read some data from the stream. Returns the number of bytes read. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + ec = boost::system::error_code(); + return 0; + } + + // Make descriptor non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_read = descriptor_ops::scatter_read( + impl.descriptor_, bufs, i, ec); + + // Check if operation succeeded. + if (bytes_read > 0) + return bytes_read; + + // Check for EOF. + if (bytes_read == 0) + { + ec = boost::asio::error::eof; + return 0; + } + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_read(impl.descriptor_, ec) < 0) + return 0; + } + } + + // Wait until data can be read without blocking. + size_t read_some(implementation_type& impl, + const null_buffers&, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for descriptor to become ready. + descriptor_ops::poll_read(impl.descriptor_, ec); + + return 0; + } + + template + class read_operation : + public handler_base_from_member + { + public: + read_operation(int descriptor, boost::asio::io_service& io_service, + const MutableBufferSequence& buffers, Handler handler) + : handler_base_from_member(handler), + descriptor_(descriptor), + io_service_(io_service), + work_(io_service), + buffers_(buffers) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers_.begin(); + typename MutableBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Read some data. + int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec); + if (bytes == 0) + ec = boost::asio::error::eof; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + int descriptor_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + MutableBufferSequence buffers_; + }; + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Determine total size of buffers. + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + this->get_io_service().post(bind_handler(handler, + boost::system::error_code(), 0)); + return; + } + + // Make descriptor non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, + read_operation( + impl.descriptor_, this->get_io_service(), buffers, handler)); + } + } + + // Wait until data can be read without blocking. + template + void async_read_some(implementation_type& impl, + const null_buffers&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + +private: + // The selector that performs event demultiplexing for the service. + Reactor& reactor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP diff --git a/include/boost/asio/detail/reactive_serial_port_service.hpp b/include/boost/asio/detail/reactive_serial_port_service.hpp new file mode 100644 index 00000000..c6d719be --- /dev/null +++ b/include/boost/asio/detail/reactive_serial_port_service.hpp @@ -0,0 +1,269 @@ +// +// reactive_serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Extend reactive_descriptor_service to provide serial port support. +template +class reactive_serial_port_service + : public boost::asio::detail::service_base< + reactive_serial_port_service > +{ +public: + // The native type of a stream handle. + typedef typename reactive_descriptor_service::native_type + native_type; + + // The implementation type of the stream handle. + typedef typename reactive_descriptor_service::implementation_type + implementation_type; + + reactive_serial_port_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + reactive_serial_port_service>(io_service), + descriptor_service_(boost::asio::use_service< + reactive_descriptor_service >(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + descriptor_service_.construct(impl); + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + descriptor_service_.destroy(impl); + } + + // Open the serial port using the specified device name. + boost::system::error_code open(implementation_type& impl, + const std::string& device, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + int fd = descriptor_ops::open(device.c_str(), + O_RDWR | O_NONBLOCK | O_NOCTTY, ec); + if (fd < 0) + return ec; + + int s = descriptor_ops::fcntl(fd, F_GETFL, ec); + if (s >= 0) + s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec); + if (s < 0) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + return ec; + } + + // Set up default serial port options. + termios ios; + descriptor_ops::clear_error(ec); + s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec); + if (s >= 0) + { +#if defined(_BSD_SOURCE) + ::cfmakeraw(&ios); +#else + ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK + | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + ios.c_oflag &= ~OPOST; + ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + ios.c_cflag &= ~(CSIZE | PARENB); + ios.c_cflag |= CS8; +#endif + ios.c_iflag |= IGNPAR; + descriptor_ops::clear_error(ec); + s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec); + } + if (s < 0) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + return ec; + } + + // We're done. Take ownership of the serial port descriptor. + if (descriptor_service_.assign(impl, fd, ec)) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + } + + return ec; + } + + // Assign a native handle to a handle implementation. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_descriptor, boost::system::error_code& ec) + { + return descriptor_service_.assign(impl, native_descriptor, ec); + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return descriptor_service_.is_open(impl); + } + + // Destroy a handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return descriptor_service_.close(impl, ec); + } + + // Get the native handle representation. + native_type native(implementation_type& impl) + { + return descriptor_service_.native(impl); + } + + // Cancel all operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return descriptor_service_.cancel(impl, ec); + } + + // Set an option on the serial port. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, boost::system::error_code& ec) + { + termios ios; + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcgetattr( + descriptor_service_.native(impl), &ios), ec); + if (ec) + return ec; + + if (option.store(ios, ec)) + return ec; + + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcsetattr( + descriptor_service_.native(impl), TCSANOW, &ios), ec); + return ec; + } + + // Get an option from the serial port. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, boost::system::error_code& ec) const + { + termios ios; + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcgetattr( + descriptor_service_.native(impl), &ios), ec); + if (ec) + return ec; + + return option.load(ios, ec); + } + + // Send a break sequence to the serial port. + boost::system::error_code send_break(implementation_type& impl, + boost::system::error_code& ec) + { + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcsendbreak( + descriptor_service_.native(impl), 0), ec); + return ec; + } + + // Write the given data. Returns the number of bytes sent. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return descriptor_service_.write_some(impl, buffers, ec); + } + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + descriptor_service_.async_write_some(impl, buffers, handler); + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return descriptor_service_.read_some(impl, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + descriptor_service_.async_read_some(impl, buffers, handler); + } + +private: + // The handle service used for initiating asynchronous operations. + reactive_descriptor_service& descriptor_service_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP diff --git a/include/boost/asio/detail/reactive_socket_service.hpp b/include/boost/asio/detail/reactive_socket_service.hpp index 7fc725cc..d474ae79 100644 --- a/include/boost/asio/detail/reactive_socket_service.hpp +++ b/include/boost/asio/detail/reactive_socket_service.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,9 @@ public: // The protocol associated with the socket. protocol_type protocol_; + + // Per-descriptor data used by the reactor. + typename Reactor::per_descriptor_data reactor_data_; }; // The maximum number of buffers to support in a single operation. @@ -114,7 +118,7 @@ public: { if (impl.socket_ != invalid_socket) { - reactor_.close_descriptor(impl.socket_); + reactor_.close_descriptor(impl.socket_, impl.reactor_data_); if (impl.flags_ & implementation_type::internal_non_blocking) { @@ -156,7 +160,7 @@ public: if (sock.get() == invalid_socket) return ec; - if (int err = reactor_.register_descriptor(sock.get())) + if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) { ec = boost::system::error_code(err, boost::asio::error::get_system_category()); @@ -181,7 +185,8 @@ public: return ec; } - if (int err = reactor_.register_descriptor(native_socket)) + if (int err = reactor_.register_descriptor( + native_socket, impl.reactor_data_)) { ec = boost::system::error_code(err, boost::asio::error::get_system_category()); @@ -207,7 +212,7 @@ public: { if (is_open(impl)) { - reactor_.close_descriptor(impl.socket_); + reactor_.close_descriptor(impl.socket_, impl.reactor_data_); if (impl.flags_ & implementation_type::internal_non_blocking) { @@ -243,7 +248,7 @@ public: return ec; } - reactor_.cancel_ops(impl.socket_); + reactor_.cancel_ops(impl.socket_, impl.reactor_data_); ec = boost::system::error_code(); return ec; } @@ -559,28 +564,46 @@ public: } } + // Wait until data can be sent without blocking. + size_t send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + template - class send_handler + class send_operation : + public handler_base_from_member { public: - send_handler(socket_type socket, boost::asio::io_service& io_service, + send_operation(socket_type socket, boost::asio::io_service& io_service, const ConstBufferSequence& buffers, socket_base::message_flags flags, Handler handler) - : socket_(socket), + : handler_base_from_member(handler), + socket_(socket), io_service_(io_service), work_(io_service), buffers_(buffers), - flags_(flags), - handler_(handler) + flags_(flags) { } - bool operator()(const boost::system::error_code& result) + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) { // Check whether the operation was successful. - if (result) + if (ec) { - io_service_.post(bind_handler(handler_, result, 0)); + bytes_transferred = 0; return true; } @@ -598,7 +621,6 @@ public: } // Send the data. - boost::system::error_code ec; int bytes = socket_ops::send(socket_, bufs, i, flags_, ec); // Check if we need to run the operation again. @@ -606,17 +628,22 @@ public: || ec == boost::asio::error::try_again) return false; - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); + bytes_transferred = (bytes < 0 ? 0 : bytes); return true; } + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + private: socket_type socket_; boost::asio::io_service& io_service_; boost::asio::io_service::work work_; ConstBufferSequence buffers_; socket_base::message_flags flags_; - Handler handler_; }; // Start an asynchronous send. The data being sent must be valid for the @@ -667,12 +694,59 @@ public: impl.flags_ |= implementation_type::internal_non_blocking; } - reactor_.start_write_op(impl.socket_, - send_handler( + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + send_operation( impl.socket_, this->get_io_service(), buffers, flags, handler)); } } + template + class null_buffers_operation : + public handler_base_from_member + { + public: + null_buffers_operation(boost::asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + work_(io_service) + { + } + + bool perform(boost::system::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + this->handler_, ec, bytes_transferred)); + } + + private: + boost::asio::io_service::work work_; + }; + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Send a datagram to the specified endpoint. Returns the number of bytes // sent. template @@ -734,29 +808,48 @@ public: } } + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + template - class send_to_handler + class send_to_operation : + public handler_base_from_member { public: - send_to_handler(socket_type socket, boost::asio::io_service& io_service, + send_to_operation(socket_type socket, boost::asio::io_service& io_service, const ConstBufferSequence& buffers, const endpoint_type& endpoint, socket_base::message_flags flags, Handler handler) - : socket_(socket), + : handler_base_from_member(handler), + socket_(socket), io_service_(io_service), work_(io_service), buffers_(buffers), destination_(endpoint), - flags_(flags), - handler_(handler) + flags_(flags) { } - bool operator()(const boost::system::error_code& result) + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) { // Check whether the operation was successful. - if (result) + if (ec) { - io_service_.post(bind_handler(handler_, result, 0)); + bytes_transferred = 0; return true; } @@ -774,7 +867,6 @@ public: } // Send the data. - boost::system::error_code ec; int bytes = socket_ops::sendto(socket_, bufs, i, flags_, destination_.data(), destination_.size(), ec); @@ -783,10 +875,16 @@ public: || ec == boost::asio::error::try_again) return false; - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); + bytes_transferred = (bytes < 0 ? 0 : bytes); return true; } + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + private: socket_type socket_; boost::asio::io_service& io_service_; @@ -794,7 +892,6 @@ public: ConstBufferSequence buffers_; endpoint_type destination_; socket_base::message_flags flags_; - Handler handler_; }; // Start an asynchronous send. The data being sent must be valid for the @@ -825,13 +922,31 @@ public: impl.flags_ |= implementation_type::internal_non_blocking; } - reactor_.start_write_op(impl.socket_, - send_to_handler( + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + send_to_operation( impl.socket_, this->get_io_service(), buffers, destination, flags, handler)); } } + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Receive some data from the peer. Returns the number of bytes received. template size_t receive(implementation_type& impl, @@ -889,7 +1004,7 @@ public: return bytes_recvd; // Check for EOF. - if (bytes_recvd == 0) + if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM) { ec = boost::asio::error::eof; return 0; @@ -907,28 +1022,48 @@ public: } } + // Wait until data can be received without blocking. + size_t receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + return 0; + } + template - class receive_handler + class receive_operation : + public handler_base_from_member { public: - receive_handler(socket_type socket, boost::asio::io_service& io_service, - const MutableBufferSequence& buffers, socket_base::message_flags flags, - Handler handler) - : socket_(socket), + receive_operation(socket_type socket, int protocol_type, + boost::asio::io_service& io_service, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, Handler handler) + : handler_base_from_member(handler), + socket_(socket), + protocol_type_(protocol_type), io_service_(io_service), work_(io_service), buffers_(buffers), - flags_(flags), - handler_(handler) + flags_(flags) { } - bool operator()(const boost::system::error_code& result) + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) { // Check whether the operation was successful. - if (result) + if (ec) { - io_service_.post(bind_handler(handler_, result, 0)); + bytes_transferred = 0; return true; } @@ -946,9 +1081,8 @@ public: } // Receive some data. - boost::system::error_code ec; int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec); - if (bytes == 0) + if (bytes == 0 && protocol_type_ == SOCK_STREAM) ec = boost::asio::error::eof; // Check if we need to run the operation again. @@ -956,17 +1090,23 @@ public: || ec == boost::asio::error::try_again) return false; - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); + bytes_transferred = (bytes < 0 ? 0 : bytes); return true; } + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + private: socket_type socket_; + int protocol_type_; boost::asio::io_service& io_service_; boost::asio::io_service::work work_; MutableBufferSequence buffers_; socket_base::message_flags flags_; - Handler handler_; }; // Start an asynchronous receive. The buffer for the data being received @@ -1020,19 +1160,44 @@ public: if (flags & socket_base::message_out_of_band) { - reactor_.start_except_op(impl.socket_, - receive_handler( - impl.socket_, this->get_io_service(), buffers, flags, handler)); + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + receive_operation( + impl.socket_, impl.protocol_.type(), + this->get_io_service(), buffers, flags, handler)); } else { - reactor_.start_read_op(impl.socket_, - receive_handler( - impl.socket_, this->get_io_service(), buffers, flags, handler)); + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + receive_operation( + impl.socket_, impl.protocol_.type(), + this->get_io_service(), buffers, flags, handler)); } } } + // Wait until data can be received without blocking. + template + void async_receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else if (flags & socket_base::message_out_of_band) + { + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Receive a datagram with the endpoint of the sender. Returns the number of // bytes received. template @@ -1088,7 +1253,7 @@ public: } // Check for EOF. - if (bytes_recvd == 0) + if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM) { ec = boost::asio::error::eof; return 0; @@ -1106,30 +1271,53 @@ public: } } + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + template - class receive_from_handler + class receive_from_operation : + public handler_base_from_member { public: - receive_from_handler(socket_type socket, + receive_from_operation(socket_type socket, int protocol_type, boost::asio::io_service& io_service, const MutableBufferSequence& buffers, endpoint_type& endpoint, socket_base::message_flags flags, Handler handler) - : socket_(socket), + : handler_base_from_member(handler), + socket_(socket), + protocol_type_(protocol_type), io_service_(io_service), work_(io_service), buffers_(buffers), sender_endpoint_(endpoint), - flags_(flags), - handler_(handler) + flags_(flags) { } - bool operator()(const boost::system::error_code& result) + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) { // Check whether the operation was successful. - if (result) + if (ec) { - io_service_.post(bind_handler(handler_, result, 0)); + bytes_transferred = 0; return true; } @@ -1148,10 +1336,9 @@ public: // Receive some data. std::size_t addr_len = sender_endpoint_.capacity(); - boost::system::error_code ec; int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_, sender_endpoint_.data(), &addr_len, ec); - if (bytes == 0) + if (bytes == 0 && protocol_type_ == SOCK_STREAM) ec = boost::asio::error::eof; // Check if we need to run the operation again. @@ -1160,18 +1347,24 @@ public: return false; sender_endpoint_.resize(addr_len); - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); + bytes_transferred = (bytes < 0 ? 0 : bytes); return true; } + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + private: socket_type socket_; + int protocol_type_; boost::asio::io_service& io_service_; boost::asio::io_service::work work_; MutableBufferSequence buffers_; endpoint_type& sender_endpoint_; socket_base::message_flags flags_; - Handler handler_; }; // Start an asynchronous receive. The buffer for the data being received and @@ -1202,10 +1395,40 @@ public: impl.flags_ |= implementation_type::internal_non_blocking; } - reactor_.start_read_op(impl.socket_, - receive_from_handler( - impl.socket_, this->get_io_service(), buffers, - sender_endpoint, flags, handler)); + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + receive_from_operation( + impl.socket_, impl.protocol_.type(), this->get_io_service(), + buffers, sender_endpoint, flags, handler)); + } + } + + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + if (flags & socket_base::message_out_of_band) + { + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } } } @@ -1300,35 +1523,32 @@ public: } template - class accept_handler + class accept_operation : + public handler_base_from_member { public: - accept_handler(socket_type socket, boost::asio::io_service& io_service, + accept_operation(socket_type socket, boost::asio::io_service& io_service, Socket& peer, const protocol_type& protocol, endpoint_type* peer_endpoint, bool enable_connection_aborted, Handler handler) - : socket_(socket), + : handler_base_from_member(handler), + socket_(socket), io_service_(io_service), work_(io_service), peer_(peer), protocol_(protocol), peer_endpoint_(peer_endpoint), - enable_connection_aborted_(enable_connection_aborted), - handler_(handler) + enable_connection_aborted_(enable_connection_aborted) { } - bool operator()(const boost::system::error_code& result) + bool perform(boost::system::error_code& ec, std::size_t&) { // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); + if (ec) return true; - } // Accept the waiting connection. - boost::system::error_code ec; socket_holder new_socket; std::size_t addr_len = 0; if (peer_endpoint_) @@ -1364,10 +1584,14 @@ public: new_socket.release(); } - io_service_.post(bind_handler(handler_, ec)); return true; } + void complete(const boost::system::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(this->handler_, ec)); + } + private: socket_type socket_; boost::asio::io_service& io_service_; @@ -1376,7 +1600,6 @@ public: protocol_type protocol_; endpoint_type* peer_endpoint_; bool enable_connection_aborted_; - Handler handler_; }; // Start an asynchronous accept. The peer and peer_endpoint objects @@ -1410,8 +1633,8 @@ public: impl.flags_ |= implementation_type::internal_non_blocking; } - reactor_.start_read_op(impl.socket_, - accept_handler( + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + accept_operation( impl.socket_, this->get_io_service(), peer, impl.protocol_, peer_endpoint, (impl.flags_ & implementation_type::enable_connection_aborted) != 0, @@ -1445,70 +1668,52 @@ public: } template - class connect_handler + class connect_operation : + public handler_base_from_member { public: - connect_handler(socket_type socket, boost::shared_ptr completed, - boost::asio::io_service& io_service, Reactor& reactor, Handler handler) - : socket_(socket), - completed_(completed), + connect_operation(socket_type socket, + boost::asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + socket_(socket), io_service_(io_service), - work_(io_service), - reactor_(reactor), - handler_(handler) + work_(io_service) { } - bool operator()(const boost::system::error_code& result) + bool perform(boost::system::error_code& ec, std::size_t&) { - // Check whether a handler has already been called for the connection. - // If it has, then we don't want to do anything in this handler. - if (*completed_) - return true; - - // Cancel the other reactor operation for the connection. - *completed_ = true; - reactor_.enqueue_cancel_ops_unlocked(socket_); - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); + if (ec) return true; - } // Get the error code from the connect operation. int connect_error = 0; size_t connect_error_len = sizeof(connect_error); - boost::system::error_code ec; if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec) == socket_error_retval) - { - io_service_.post(bind_handler(handler_, ec)); return true; - } - // If connection failed then post the handler with the error code. + // The connection failed so the handler will be posted with an error code. if (connect_error) { ec = boost::system::error_code(connect_error, boost::asio::error::get_system_category()); - io_service_.post(bind_handler(handler_, ec)); return true; } - // Post the result of the successful connection operation. - io_service_.post(bind_handler(handler_, ec)); return true; } + void complete(const boost::system::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(this->handler_, ec)); + } + private: socket_type socket_; - boost::shared_ptr completed_; boost::asio::io_service& io_service_; boost::asio::io_service::work work_; - Reactor& reactor_; - Handler handler_; }; // Start an asynchronous connect. @@ -1552,10 +1757,9 @@ public: { // The connection is happening in the background, and we need to wait // until the socket becomes writeable. - boost::shared_ptr completed(new bool(false)); - reactor_.start_write_and_except_ops(impl.socket_, - connect_handler(impl.socket_, completed, - this->get_io_service(), reactor_, handler)); + reactor_.start_connect_op(impl.socket_, impl.reactor_data_, + connect_operation(impl.socket_, + this->get_io_service(), handler)); } else { diff --git a/include/boost/asio/detail/reactor_op_queue.hpp b/include/boost/asio/detail/reactor_op_queue.hpp index 48a1ebe6..0fbbf236 100644 --- a/include/boost/asio/detail/reactor_op_queue.hpp +++ b/include/boost/asio/detail/reactor_op_queue.hpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -38,36 +39,42 @@ public: reactor_op_queue() : operations_(), cancelled_operations_(0), - cleanup_operations_(0) + complete_operations_(0) { } // Add a new operation to the queue. Returns true if this is the only // operation for the given descriptor, in which case the reactor's event // demultiplexing function call may need to be interrupted and restarted. - template - bool enqueue_operation(Descriptor descriptor, Handler handler) + template + bool enqueue_operation(Descriptor descriptor, Operation operation) { - op_base* new_op = new op(descriptor, handler); + // Allocate and construct an object to wrap the handler. + typedef handler_alloc_traits > alloc_traits; + raw_handler_ptr raw_ptr(operation); + handler_ptr ptr(raw_ptr, descriptor, operation); typedef typename operation_map::iterator iterator; typedef typename operation_map::value_type value_type; std::pair entry = - operations_.insert(value_type(descriptor, new_op)); + operations_.insert(value_type(descriptor, ptr.get())); if (entry.second) + { + ptr.release(); return true; + } op_base* current_op = entry.first->second; while (current_op->next_) current_op = current_op->next_; - current_op->next_ = new_op; + current_op->next_ = ptr.release(); return false; } // Cancel all operations associated with the descriptor. Any operations // pending for the descriptor will be notified that they have been cancelled - // next time dispatch_cancellations is called. Returns true if any operations + // next time perform_cancellations is called. Returns true if any operations // were cancelled, in which case the reactor's event demultiplexing function // may need to be interrupted and restarted. bool cancel_operations(Descriptor descriptor) @@ -99,9 +106,9 @@ public: return operations_.find(descriptor) != operations_.end(); } - // Dispatch the first operation corresponding to the descriptor. Returns true + // Perform the first operation corresponding to the descriptor. Returns true // if there are more operations queued for the descriptor. - bool dispatch_operation(Descriptor descriptor, + bool perform_operation(Descriptor descriptor, const boost::system::error_code& result) { typename operation_map::iterator i = operations_.find(descriptor); @@ -109,9 +116,9 @@ public: { op_base* this_op = i->second; i->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); if (done) { // Operation has finished. @@ -128,8 +135,8 @@ public: else { // Operation wants to be called again. Leave it at the front of the - // queue for this descriptor, and remove from the cleanup list. - cleanup_operations_ = this_op->next_; + // queue for this descriptor, and remove from the completed list. + complete_operations_ = this_op->next_; this_op->next_ = i->second; i->second = this_op; return true; @@ -138,8 +145,8 @@ public: return false; } - // Dispatch all operations corresponding to the descriptor. - void dispatch_all_operations(Descriptor descriptor, + // Perform all operations corresponding to the descriptor. + void perform_all_operations(Descriptor descriptor, const boost::system::error_code& result) { typename operation_map::iterator i = operations_.find(descriptor); @@ -149,14 +156,14 @@ public: { op_base* this_op = i->second; i->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); if (!done) { // Operation has not finished yet, so leave at front of queue, and - // remove from the cleanup list. - cleanup_operations_ = this_op->next_; + // remove from the completed list. + complete_operations_ = this_op->next_; this_op->next_ = i->second; i->second = this_op; return; @@ -179,15 +186,15 @@ public: if (!descriptors.set(descriptor)) { boost::system::error_code ec(error::fd_set_failure); - dispatch_all_operations(descriptor, ec); + perform_all_operations(descriptor, ec); } } } - // Dispatch the operations corresponding to the ready file descriptors + // Perform the operations corresponding to the ready file descriptors // contained in the given descriptor set. template - void dispatch_descriptors(const Descriptor_Set& descriptors, + void perform_operations_for_descriptors(const Descriptor_Set& descriptors, const boost::system::error_code& result) { typename operation_map::iterator i = operations_.begin(); @@ -198,9 +205,9 @@ public: { op_base* this_op = op_iter->second; op_iter->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); if (done) { if (!op_iter->second) @@ -209,8 +216,8 @@ public: else { // Operation has not finished yet, so leave at front of queue, and - // remove from the cleanup list. - cleanup_operations_ = this_op->next_; + // remove from the completed list. + complete_operations_ = this_op->next_; this_op->next_ = op_iter->second; op_iter->second = this_op; } @@ -218,28 +225,28 @@ public: } } - // Dispatch any pending cancels for operations. - void dispatch_cancellations() + // Perform any pending cancels for operations. + void perform_cancellations() { while (cancelled_operations_) { op_base* this_op = cancelled_operations_; cancelled_operations_ = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - this_op->invoke(boost::asio::error::operation_aborted); + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + this_op->perform(boost::asio::error::operation_aborted); } } - // Destroy operations that are waiting to be cleaned up. - void cleanup_operations() + // Complete all operations that are waiting to be completed. + void complete_operations() { - while (cleanup_operations_) + while (complete_operations_) { - op_base* next_op = cleanup_operations_->next_; - cleanup_operations_->next_ = 0; - cleanup_operations_->destroy(); - cleanup_operations_ = next_op; + op_base* next_op = complete_operations_->next_; + complete_operations_->next_ = 0; + complete_operations_->complete(); + complete_operations_ = next_op; } } @@ -254,12 +261,12 @@ public: cancelled_operations_ = next_op; } - while (cleanup_operations_) + while (complete_operations_) { - op_base* next_op = cleanup_operations_->next_; - cleanup_operations_->next_ = 0; - cleanup_operations_->destroy(); - cleanup_operations_ = next_op; + op_base* next_op = complete_operations_->next_; + complete_operations_->next_ = 0; + complete_operations_->destroy(); + complete_operations_ = next_op; } typename operation_map::iterator i = operations_.begin(); @@ -291,28 +298,40 @@ private: } // Perform the operation. - bool invoke(const boost::system::error_code& result) + bool perform(const boost::system::error_code& result) { - return invoke_func_(this, result); + result_ = result; + return perform_func_(this, result_, bytes_transferred_); + } + + // Destroy the operation and post the handler. + void complete() + { + complete_func_(this, result_, bytes_transferred_); } // Destroy the operation. void destroy() { - return destroy_func_(this); + destroy_func_(this); } protected: - typedef bool (*invoke_func_type)(op_base*, - const boost::system::error_code&); + typedef bool (*perform_func_type)(op_base*, + boost::system::error_code&, std::size_t&); + typedef void (*complete_func_type)(op_base*, + const boost::system::error_code&, std::size_t); typedef void (*destroy_func_type)(op_base*); // Construct an operation for the given descriptor. - op_base(invoke_func_type invoke_func, + op_base(perform_func_type perform_func, complete_func_type complete_func, destroy_func_type destroy_func, Descriptor descriptor) - : invoke_func_(invoke_func), + : perform_func_(perform_func), + complete_func_(complete_func), destroy_func_(destroy_func), descriptor_(descriptor), + result_(), + bytes_transferred_(0), next_(0) { } @@ -325,48 +344,94 @@ private: private: friend class reactor_op_queue; - // The function to be called to dispatch the handler. - invoke_func_type invoke_func_; + // The function to be called to perform the operation. + perform_func_type perform_func_; - // The function to be called to delete the handler. + // The function to be called to delete the operation and post the handler. + complete_func_type complete_func_; + + // The function to be called to delete the operation. destroy_func_type destroy_func_; // The descriptor associated with the operation. Descriptor descriptor_; + // The result of the operation. + boost::system::error_code result_; + + // The number of bytes transferred in the operation. + std::size_t bytes_transferred_; + // The next operation for the same file descriptor. op_base* next_; }; - // Adaptor class template for using handlers in operations. - template + // Adaptor class template for operations. + template class op : public op_base { public: // Constructor. - op(Descriptor descriptor, Handler handler) - : op_base(&op::invoke_handler, - &op::destroy_handler, descriptor), - handler_(handler) + op(Descriptor descriptor, Operation operation) + : op_base(&op::do_perform, &op::do_complete, + &op::do_destroy, descriptor), + operation_(operation) { } - // Invoke the handler. - static bool invoke_handler(op_base* base, - const boost::system::error_code& result) + // Perform the operation. + static bool do_perform(op_base* base, + boost::system::error_code& result, std::size_t& bytes_transferred) { - return static_cast*>(base)->handler_(result); + return static_cast*>(base)->operation_.perform( + result, bytes_transferred); } - // Delete the handler. - static void destroy_handler(op_base* base) + // Destroy the operation and post the handler. + static void do_complete(op_base* base, + const boost::system::error_code& result, std::size_t bytes_transferred) { - delete static_cast*>(base); + // Take ownership of the operation object. + typedef op this_type; + this_type* this_op(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_op->operation_, this_op); + + // Make a copy of the error_code and the operation so that the memory can + // be deallocated before the upcall is made. + boost::system::error_code ec(result); + Operation operation(this_op->operation_); + + // Free the memory associated with the operation. + ptr.reset(); + + // Make the upcall. + operation.complete(ec, bytes_transferred); + } + + // Destroy the operation. + static void do_destroy(op_base* base) + { + // Take ownership of the operation object. + typedef op this_type; + this_type* this_op(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_op->operation_, this_op); + + // A sub-object of the operation may be the true owner of the memory + // associated with the operation. Consequently, a local copy of the + // operation is required to ensure that any owning sub-object remains + // valid until after we have deallocated the memory here. + Operation operation(this_op->operation_); + (void)operation; + + // Free the memory associated with the operation. + ptr.reset(); } private: - Handler handler_; + Operation operation_; }; // The type for a map of operations. @@ -378,8 +443,8 @@ private: // The list of operations that have been cancelled. op_base* cancelled_operations_; - // The list of operations to be destroyed. - op_base* cleanup_operations_; + // The list of operations waiting to be completed. + op_base* complete_operations_; }; } // namespace detail diff --git a/include/boost/asio/detail/select_reactor.hpp b/include/boost/asio/detail/select_reactor.hpp index 948f3503..83787535 100644 --- a/include/boost/asio/detail/select_reactor.hpp +++ b/include/boost/asio/detail/select_reactor.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,11 @@ class select_reactor : public boost::asio::detail::service_base > { public: + // Per-descriptor data. + struct per_descriptor_data + { + }; + // Constructor. select_reactor(boost::asio::io_service& io_service) : boost::asio::detail::service_base< @@ -107,7 +113,7 @@ public: // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type descriptor) + int register_descriptor(socket_type, per_descriptor_data&) { return 0; } @@ -115,7 +121,8 @@ public: // Start a new read operation. The handler object will be invoked when the // given descriptor is ready to be read, or an error has occurred. template - void start_read_op(socket_type descriptor, Handler handler) + void start_read_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool /*allow_speculative_read*/ = true) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (!shutdown_) @@ -126,7 +133,8 @@ public: // Start a new write operation. The handler object will be invoked when the // given descriptor is ready to be written, or an error has occurred. template - void start_write_op(socket_type descriptor, Handler handler) + void start_write_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool /*allow_speculative_write*/ = true) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (!shutdown_) @@ -137,7 +145,8 @@ public: // Start a new exception operation. The handler object will be invoked when // the given descriptor has exception information, or an error has occurred. template - void start_except_op(socket_type descriptor, Handler handler) + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (!shutdown_) @@ -145,18 +154,74 @@ public: interrupter_.interrupt(); } + // Wrapper for connect handlers to enable the handler object to be placed + // in both the write and the except operation queues, but ensure that only + // one of the handlers is called. + template + class connect_handler_wrapper + { + public: + connect_handler_wrapper(socket_type descriptor, + boost::shared_ptr completed, + select_reactor& reactor, Handler handler) + : descriptor_(descriptor), + completed_(completed), + reactor_(reactor), + handler_(handler) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether one of the handlers has already been called. If it has, + // then we don't want to do anything in this handler. + if (*completed_) + { + completed_.reset(); // Indicate that this handler should not complete. + return true; + } + + // Cancel the other reactor operation for the connection. + *completed_ = true; + reactor_.enqueue_cancel_ops_unlocked(descriptor_); + + // Call the contained handler. + return handler_.perform(ec, bytes_transferred); + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + if (completed_.get()) + handler_.complete(ec, bytes_transferred); + } + + private: + socket_type descriptor_; + boost::shared_ptr completed_; + select_reactor& reactor_; + Handler handler_; + }; + // Start new write and exception operations. The handler object will be // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. + // information available, or an error has occurred. The handler will be called + // only once. template - void start_write_and_except_ops(socket_type descriptor, Handler handler) + void start_connect_op(socket_type descriptor, + per_descriptor_data&, Handler handler) { boost::asio::detail::mutex::scoped_lock lock(mutex_); if (!shutdown_) { - bool interrupt = write_op_queue_.enqueue_operation(descriptor, handler); - interrupt = except_op_queue_.enqueue_operation(descriptor, handler) - || interrupt; + boost::shared_ptr completed(new bool(false)); + connect_handler_wrapper wrapped_handler( + descriptor, completed, *this, handler); + bool interrupt = write_op_queue_.enqueue_operation( + descriptor, wrapped_handler); + interrupt = except_op_queue_.enqueue_operation( + descriptor, wrapped_handler) || interrupt; if (interrupt) interrupter_.interrupt(); } @@ -165,7 +230,7 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor) + void cancel_ops(socket_type descriptor, per_descriptor_data&) { boost::asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); @@ -174,8 +239,8 @@ public: // Enqueue cancellation of all operations associated with the given // descriptor. The handlers associated with the descriptor will be invoked // with the operation_aborted error. This function does not acquire the - // select_reactor's mutex, and so should only be used from within a reactor - // handler. + // select_reactor's mutex, and so should only be used when the reactor lock is + // already held. void enqueue_cancel_ops_unlocked(socket_type descriptor) { pending_cancellations_.push_back(descriptor); @@ -183,7 +248,7 @@ public: // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor) + void close_descriptor(socket_type descriptor, per_descriptor_data&) { boost::asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor); @@ -246,16 +311,16 @@ private: // Dispatch any operation cancellations that were made while the select // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); for (std::size_t i = 0; i < timer_queues_.size(); ++i) timer_queues_[i]->dispatch_cancellations(); // Check if the thread is supposed to stop. if (stop_thread_) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -264,7 +329,7 @@ private: if (!block && read_op_queue_.empty() && write_op_queue_.empty() && except_op_queue_.empty() && all_timer_queues_are_empty()) { - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); return; } @@ -306,15 +371,15 @@ private: { // Exception operations must be processed first to ensure that any // out-of-band data is read before normal data. - except_op_queue_.dispatch_descriptors(except_fds, - boost::system::error_code()); - read_op_queue_.dispatch_descriptors(read_fds, - boost::system::error_code()); - write_op_queue_.dispatch_descriptors(write_fds, - boost::system::error_code()); - except_op_queue_.dispatch_cancellations(); - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); + except_op_queue_.perform_operations_for_descriptors( + except_fds, boost::system::error_code()); + read_op_queue_.perform_operations_for_descriptors( + read_fds, boost::system::error_code()); + write_op_queue_.perform_operations_for_descriptors( + write_fds, boost::system::error_code()); + except_op_queue_.perform_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); } for (std::size_t i = 0; i < timer_queues_.size(); ++i) { @@ -327,7 +392,7 @@ private: cancel_ops_unlocked(pending_cancellations_[i]); pending_cancellations_.clear(); - cleanup_operations_and_timers(lock); + complete_operations_and_timers(lock); } // Run the select loop in the thread. @@ -412,16 +477,16 @@ private: // destructors may make calls back into this reactor. We make a copy of the // vector of timer queues since the original may be modified while the lock // is not held. - void cleanup_operations_and_timers( + void complete_operations_and_timers( boost::asio::detail::mutex::scoped_lock& lock) { timer_queues_for_cleanup_ = timer_queues_; lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) - timer_queues_for_cleanup_[i]->cleanup_timers(); + timer_queues_for_cleanup_[i]->complete_timers(); } // Mutex to protect access to internal data. diff --git a/include/boost/asio/detail/service_registry.hpp b/include/boost/asio/detail/service_registry.hpp index 7feec283..d1b1c04e 100644 --- a/include/boost/asio/detail/service_registry.hpp +++ b/include/boost/asio/detail/service_registry.hpp @@ -27,6 +27,12 @@ #include #include +#if defined(BOOST_NO_TYPEID) +# if !defined(BOOST_ASIO_NO_TYPEID) +# define BOOST_ASIO_NO_TYPEID +# endif // !defined(BOOST_ASIO_NO_TYPEID) +#endif // defined(BOOST_NO_TYPEID) + namespace boost { namespace asio { namespace detail { @@ -157,6 +163,7 @@ private: service.id_ = &id; } +#if !defined(BOOST_ASIO_NO_TYPEID) // Set a service's id. template void init_service_id(boost::asio::io_service::service& service, @@ -165,6 +172,7 @@ private: service.type_info_ = &typeid(Service); service.id_ = 0; } +#endif // !defined(BOOST_ASIO_NO_TYPEID) // Check if a service matches the given id. static bool service_id_matches( @@ -174,6 +182,7 @@ private: return service.id_ == &id; } +#if !defined(BOOST_ASIO_NO_TYPEID) // Check if a service matches the given id. template static bool service_id_matches( @@ -182,6 +191,7 @@ private: { return service.type_info_ != 0 && *service.type_info_ == typeid(Service); } +#endif // !defined(BOOST_ASIO_NO_TYPEID) // Mutex to protect access to internal data. mutable boost::asio::detail::mutex mutex_; diff --git a/include/boost/asio/detail/socket_ops.hpp b/include/boost/asio/detail/socket_ops.hpp index fc231890..f912e536 100644 --- a/include/boost/asio/detail/socket_ops.hpp +++ b/include/boost/asio/detail/socket_ops.hpp @@ -176,6 +176,22 @@ inline int connect(socket_type s, const socket_addr_type* addr, return result; } +inline int socketpair(int af, int type, int protocol, + socket_type sv[2], boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + (void)(af); + (void)(type); + (void)(protocol); + (void)(sv); + ec = boost::asio::error::operation_not_supported; + return -1; +#else + clear_error(ec); + return error_wrapper(::socketpair(af, type, protocol, sv), ec); +#endif +} + inline int listen(socket_type s, int backlog, boost::system::error_code& ec) { clear_error(ec); diff --git a/include/boost/asio/detail/socket_types.hpp b/include/boost/asio/detail/socket_types.hpp index 82e5af28..70a6696e 100644 --- a/include/boost/asio/detail/socket_types.hpp +++ b/include/boost/asio/detail/socket_types.hpp @@ -99,6 +99,7 @@ # endif # include # include +# include # include # include # include @@ -176,6 +177,7 @@ typedef in6_addr in6_addr_type; typedef ipv6_mreq in6_mreq_type; typedef sockaddr_in6 sockaddr_in6_type; typedef sockaddr_storage sockaddr_storage_type; +typedef sockaddr_un sockaddr_un_type; typedef addrinfo addrinfo_type; typedef int ioctl_arg_type; typedef uint32_t u_long_type; diff --git a/include/boost/asio/detail/strand_service.hpp b/include/boost/asio/detail/strand_service.hpp index 166b8dfc..2c89a610 100644 --- a/include/boost/asio/detail/strand_service.hpp +++ b/include/boost/asio/detail/strand_service.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -55,19 +56,13 @@ public: #endif void add_ref() { - boost::asio::detail::mutex::scoped_lock lock(mutex_); ++ref_count_; } void release() { - boost::asio::detail::mutex::scoped_lock lock(mutex_); - --ref_count_; - if (ref_count_ == 0) - { - lock.unlock(); + if (--ref_count_ == 0) delete this; - } } private: @@ -148,7 +143,7 @@ public: strand_impl* prev_; // The reference count on the strand implementation. - size_t ref_count_; + boost::detail::atomic_count ref_count_; #if !defined(__BORLANDC__) friend void intrusive_ptr_add_ref(strand_impl* p) @@ -346,6 +341,16 @@ public: this_type* h(static_cast(base)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } private: diff --git a/include/boost/asio/detail/task_io_service.hpp b/include/boost/asio/detail/task_io_service.hpp index aa5a63e2..546a6b21 100644 --- a/include/boost/asio/detail/task_io_service.hpp +++ b/include/boost/asio/detail/task_io_service.hpp @@ -15,6 +15,10 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#if defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) +#include +#else // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) + #include #include @@ -418,4 +422,6 @@ private: #include #include +#endif // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) + #endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP diff --git a/include/boost/asio/detail/task_io_service_2lock.hpp b/include/boost/asio/detail/task_io_service_2lock.hpp new file mode 100644 index 00000000..6082b4f4 --- /dev/null +++ b/include/boost/asio/detail/task_io_service_2lock.hpp @@ -0,0 +1,464 @@ +// +// task_io_service_2lock.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP +#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// An alternative task_io_service implementation based on a two-lock queue. + +template +class task_io_service + : public boost::asio::detail::service_base > +{ +public: + typedef indirect_handler_queue handler_queue; + + // Constructor. + task_io_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base >(io_service), + front_mutex_(), + back_mutex_(), + task_(use_service(io_service)), + outstanding_work_(0), + front_stopped_(false), + back_stopped_(false), + back_shutdown_(false), + back_first_idle_thread_(0), + back_task_thread_(0) + { + handler_queue_.push(&task_handler_); + } + + void init(size_t /*concurrency_hint*/) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_shutdown_ = true; + back_lock.unlock(); + + // Destroy handler objects. + while (handler_queue::handler* h = handler_queue_.pop()) + if (h != &task_handler_) + h->destroy(); + + // Reset handler queue to initial state. + handler_queue_.push(&task_handler_); + } + + // Run the event loop until interrupted or no more work. + size_t run(boost::system::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = boost::system::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + idle_thread_info this_idle_thread; + this_idle_thread.next = 0; + + size_t n = 0; + while (do_one(&this_idle_thread, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Run until interrupted or one operation is performed. + size_t run_one(boost::system::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = boost::system::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + idle_thread_info this_idle_thread; + this_idle_thread.next = 0; + + return do_one(&this_idle_thread, ec); + } + + // Poll for operations without blocking. + size_t poll(boost::system::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = boost::system::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + size_t n = 0; + while (do_one(0, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Poll for one operation without blocking. + size_t poll_one(boost::system::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = boost::system::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + return do_one(0, ec); + } + + // Interrupt the event processing loop. + void stop() + { + boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); + front_stopped_ = true; + front_lock.unlock(); + + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_stopped_ = true; + interrupt_all_idle_threads(back_lock); + } + + // Reset in preparation for a subsequent run invocation. + void reset() + { + boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); + front_stopped_ = false; + front_lock.unlock(); + + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_stopped_ = false; + } + + // Notify that some work has started. + void work_started() + { + ++outstanding_work_; + } + + // Notify that some work has finished. + void work_finished() + { + if (--outstanding_work_ == 0) + stop(); + } + + // Request invocation of the given handler. + template + void dispatch(Handler handler) + { + if (call_stack::contains(this)) + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + else + post(handler); + } + + // Request invocation of the given handler and return immediately. + template + void post(Handler handler) + { + // Allocate and construct an operation to wrap the handler. + handler_queue::scoped_ptr ptr(handler_queue::wrap(handler)); + + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + + // If the service has been shut down we silently discard the handler. + if (back_shutdown_) + return; + + // Add the handler to the end of the queue. + handler_queue_.push(ptr.get()); + ptr.release(); + + // An undelivered handler is treated as unfinished work. + ++outstanding_work_; + + // Wake up a thread to execute the handler. + interrupt_one_idle_thread(back_lock); + } + +private: + struct idle_thread_info; + + size_t do_one(idle_thread_info* this_idle_thread, + boost::system::error_code& ec) + { + bool task_has_run = false; + for (;;) + { + // The front lock must be held before we can pop items from the queue. + boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); + if (front_stopped_) + { + ec = boost::system::error_code(); + return 0; + } + + if (handler_queue::handler* h = handler_queue_.pop()) + { + if (h == &task_handler_) + { + bool more_handlers = handler_queue_.poppable(); + unsigned long front_version = handler_queue_.front_version(); + front_lock.unlock(); + + // The task is always added to the back of the queue when we exit + // this block. + task_cleanup c(*this); + + // If we're polling and the task has already run then we're done. + bool polling = !this_idle_thread; + if (task_has_run && polling) + { + ec = boost::system::error_code(); + return 0; + } + + // If we're considering going idle we need to check whether the queue + // is still empty. If it is, add the thread to the list of idle + // threads. + if (!more_handlers && !polling) + { + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + if (back_stopped_) + { + ec = boost::system::error_code(); + return 0; + } + else if (front_version == handler_queue_.back_version()) + { + back_task_thread_ = this_idle_thread; + } + else + { + more_handlers = true; + } + } + + // Run the task. May throw an exception. Only block if the handler + // queue is empty and we're not polling, otherwise we want to return + // as soon as possible. + task_has_run = true; + task_.run(!more_handlers && !polling); + } + else + { + front_lock.unlock(); + handler_cleanup c(*this); + + // Invoke the handler. May throw an exception. + h->invoke(); // invoke() deletes the handler object + + ec = boost::system::error_code(); + return 1; + } + } + else if (this_idle_thread) + { + unsigned long front_version = handler_queue_.front_version(); + front_lock.unlock(); + + // If we're considering going idle we need to check whether the queue + // is still empty. If it is, add the thread to the list of idle + // threads. + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + if (back_stopped_) + { + ec = boost::system::error_code(); + return 0; + } + else if (front_version == handler_queue_.back_version()) + { + this_idle_thread->next = back_first_idle_thread_; + back_first_idle_thread_ = this_idle_thread; + this_idle_thread->wakeup_event.clear(back_lock); + this_idle_thread->wakeup_event.wait(back_lock); + } + } + else + { + ec = boost::system::error_code(); + return 0; + } + } + } + + // Interrupt a single idle thread. + void interrupt_one_idle_thread( + boost::asio::detail::mutex::scoped_lock& back_lock) + { + if (back_first_idle_thread_) + { + idle_thread_info* idle_thread = back_first_idle_thread_; + back_first_idle_thread_ = idle_thread->next; + idle_thread->next = 0; + idle_thread->wakeup_event.signal(back_lock); + } + else if (back_task_thread_) + { + back_task_thread_ = 0; + task_.interrupt(); + } + } + + // Interrupt all idle threads. + void interrupt_all_idle_threads( + boost::asio::detail::mutex::scoped_lock& back_lock) + { + while (back_first_idle_thread_) + { + idle_thread_info* idle_thread = back_first_idle_thread_; + back_first_idle_thread_ = idle_thread->next; + idle_thread->next = 0; + idle_thread->wakeup_event.signal(back_lock); + } + + if (back_task_thread_) + { + back_task_thread_ = 0; + task_.interrupt(); + } + } + + // Helper class to perform task-related operations on block exit. + class task_cleanup; + friend class task_cleanup; + class task_cleanup + { + public: + task_cleanup(task_io_service& task_io_svc) + : task_io_service_(task_io_svc) + { + } + + ~task_cleanup() + { + // Reinsert the task at the end of the handler queue. + boost::asio::detail::mutex::scoped_lock back_lock( + task_io_service_.back_mutex_); + task_io_service_.back_task_thread_ = 0; + task_io_service_.handler_queue_.push(&task_io_service_.task_handler_); + } + + private: + task_io_service& task_io_service_; + }; + + // Helper class to perform handler-related operations on block exit. + class handler_cleanup + { + public: + handler_cleanup(task_io_service& task_io_svc) + : task_io_service_(task_io_svc) + { + } + + ~handler_cleanup() + { + task_io_service_.work_finished(); + } + + private: + task_io_service& task_io_service_; + }; + + // Mutexes to protect access to internal data. + boost::asio::detail::mutex front_mutex_; + boost::asio::detail::mutex back_mutex_; + + // The task to be run by this service. + Task& task_; + + // Handler object to represent the position of the task in the queue. + class task_handler + : public handler_queue::handler + { + public: + task_handler() + : handler_queue::handler(0, 0) + { + } + } task_handler_; + + // The count of unfinished work. + boost::detail::atomic_count outstanding_work_; + + // The queue of handlers that are ready to be delivered. + handler_queue handler_queue_; + + // Flag to indicate that the dispatcher has been stopped. + bool front_stopped_; + bool back_stopped_; + + // Flag to indicate that the dispatcher has been shut down. + bool back_shutdown_; + + // Structure containing information about an idle thread. + struct idle_thread_info + { + event wakeup_event; + idle_thread_info* next; + }; + + // The number of threads that are currently idle. + idle_thread_info* back_first_idle_thread_; + + // The thread that is currently blocked on the task. + idle_thread_info* back_task_thread_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP diff --git a/include/boost/asio/detail/timer_queue.hpp b/include/boost/asio/detail/timer_queue.hpp index b0d85405..f5370e51 100644 --- a/include/boost/asio/detail/timer_queue.hpp +++ b/include/boost/asio/detail/timer_queue.hpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -51,7 +52,7 @@ public: : timers_(), heap_(), cancelled_timers_(0), - cleanup_timers_(0) + complete_timers_(0) { } @@ -102,6 +103,8 @@ public: // Get the time for the timer that is earliest in the queue. virtual boost::posix_time::time_duration wait_duration() const { + if (heap_.empty()) + return boost::posix_time::pos_infin; return Time_Traits::to_posix_duration( Time_Traits::subtract(heap_[0]->time_, Time_Traits::now())); } @@ -114,10 +117,10 @@ public: { timer_base* t = heap_[0]; remove_timer(t); + t->result_ = boost::system::error_code(); t->prev_ = 0; - t->next_ = cleanup_timers_; - cleanup_timers_ = t; - t->invoke(boost::system::error_code()); + t->next_ = complete_timers_; + complete_timers_ = t; } } @@ -153,17 +156,23 @@ public: while (cancelled_timers_) { timer_base* this_timer = cancelled_timers_; + this_timer->result_ = boost::asio::error::operation_aborted; cancelled_timers_ = this_timer->next_; - this_timer->next_ = cleanup_timers_; - cleanup_timers_ = this_timer; - this_timer->invoke(boost::asio::error::operation_aborted); + this_timer->next_ = complete_timers_; + complete_timers_ = this_timer; } } - // Destroy timers that are waiting to be cleaned up. - virtual void cleanup_timers() + // Complete any timers that are waiting to be completed. + virtual void complete_timers() { - destroy_timer_list(cleanup_timers_); + while (complete_timers_) + { + timer_base* this_timer = complete_timers_; + complete_timers_ = this_timer->next_; + this_timer->next_ = 0; + this_timer->complete(); + } } // Destroy all timers. @@ -181,7 +190,7 @@ public: heap_.clear(); timers_.clear(); destroy_timer_list(cancelled_timers_); - destroy_timer_list(cleanup_timers_); + destroy_timer_list(complete_timers_); } private: @@ -190,27 +199,27 @@ private: class timer_base { public: - // Perform the timer operation and then destroy. - void invoke(const boost::system::error_code& result) + // Delete the timer and post the handler. + void complete() { - invoke_func_(this, result); + complete_func_(this, result_); } - // Destroy the timer operation. + // Delete the timer. void destroy() { destroy_func_(this); } protected: - typedef void (*invoke_func_type)(timer_base*, + typedef void (*complete_func_type)(timer_base*, const boost::system::error_code&); typedef void (*destroy_func_type)(timer_base*); // Constructor. - timer_base(invoke_func_type invoke_func, destroy_func_type destroy_func, + timer_base(complete_func_type complete_func, destroy_func_type destroy_func, const time_type& time, void* token) - : invoke_func_(invoke_func), + : complete_func_(complete_func), destroy_func_(destroy_func), time_(time), token_(token), @@ -229,13 +238,16 @@ private: private: friend class timer_queue; - // The function to be called to dispatch the handler. - invoke_func_type invoke_func_; + // The function to be called to delete the timer and post the handler. + complete_func_type complete_func_; - // The function to be called to destroy the handler. + // The function to be called to delete the timer. destroy_func_type destroy_func_; - // The time when the operation should fire. + // The result of the timer operation. + boost::system::error_code result_; + + // The time when the timer should fire. time_type time_; // The token associated with the timer. @@ -259,23 +271,52 @@ private: public: // Constructor. timer(const time_type& time, Handler handler, void* token) - : timer_base(&timer::invoke_handler, + : timer_base(&timer::complete_handler, &timer::destroy_handler, time, token), handler_(handler) { } - // Invoke the handler and then destroy it. - static void invoke_handler(timer_base* base, + // Delete the timer and post the handler. + static void complete_handler(timer_base* base, const boost::system::error_code& result) { - static_cast*>(base)->handler_(result); + // Take ownership of the timer object. + typedef timer this_type; + this_type* this_timer(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_timer->handler_, this_timer); + + // Make a copy of the error_code and the handler so that the memory can + // be deallocated before the upcall is made. + boost::system::error_code ec(result); + Handler handler(this_timer->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Make the upcall. + handler(ec); } - // Destroy the handler. + // Delete the timer. static void destroy_handler(timer_base* base) { - delete static_cast*>(base); + // Take ownership of the timer object. + typedef timer this_type; + this_type* this_timer(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_timer->handler_, this_timer); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(this_timer->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } private: @@ -384,8 +425,8 @@ private: // The list of timers to be cancelled. timer_base* cancelled_timers_; - // The list of timers to be destroyed. - timer_base* cleanup_timers_; + // The list of timers waiting to be completed. + timer_base* complete_timers_; }; } // namespace detail diff --git a/include/boost/asio/detail/timer_queue_base.hpp b/include/boost/asio/detail/timer_queue_base.hpp index 54def8be..1d986c08 100644 --- a/include/boost/asio/detail/timer_queue_base.hpp +++ b/include/boost/asio/detail/timer_queue_base.hpp @@ -48,8 +48,8 @@ public: // Dispatch any pending cancels for timers. virtual void dispatch_cancellations() = 0; - // Destroy timers that are waiting to be cleaned up. - virtual void cleanup_timers() = 0; + // Complete all timers that are waiting to be completed. + virtual void complete_timers() = 0; // Destroy all timers. virtual void destroy_timers() = 0; diff --git a/include/boost/asio/detail/win_iocp_handle_service.hpp b/include/boost/asio/detail/win_iocp_handle_service.hpp new file mode 100644 index 00000000..00b89329 --- /dev/null +++ b/include/boost/asio/detail/win_iocp_handle_service.hpp @@ -0,0 +1,834 @@ +// +// win_iocp_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP +#define BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_IOCP) + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_iocp_handle_service + : public boost::asio::detail::service_base +{ +public: + // Base class for all operations. + typedef win_iocp_io_service::operation operation; + + // The native type of a stream handle. + typedef HANDLE native_type; + + // The implementation type of the stream handle. + class implementation_type + { + public: + // Default constructor. + implementation_type() + : handle_(INVALID_HANDLE_VALUE), + safe_cancellation_thread_id_(0), + next_(0), + prev_(0) + { + } + + private: + // Only this service will have access to the internal values. + friend class win_iocp_handle_service; + + // The native stream handle representation. + native_type handle_; + + // The ID of the thread from which it is safe to cancel asynchronous + // operations. 0 means no asynchronous operations have been started yet. + // ~0 means asynchronous operations have been started from more than one + // thread, and cancellation is not supported for the handle. + DWORD safe_cancellation_thread_id_; + + // Pointers to adjacent handle implementations in linked list. + implementation_type* next_; + implementation_type* prev_; + }; + + win_iocp_handle_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + iocp_service_(boost::asio::use_service(io_service)), + mutex_(), + impl_list_(0) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + // Close all implementations, causing all operations to complete. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + implementation_type* impl = impl_list_; + while (impl) + { + close_for_destruction(*impl); + impl = impl->next_; + } + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + + // Insert implementation into linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + impl.next_ = impl_list_; + impl.prev_ = 0; + if (impl_list_) + impl_list_->prev_ = &impl; + impl_list_ = &impl; + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + close_for_destruction(impl); + + // Remove implementation from linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (impl_list_ == &impl) + impl_list_ = impl.next_; + if (impl.prev_) + impl.prev_->next_ = impl.next_; + if (impl.next_) + impl.next_->prev_= impl.prev_; + impl.next_ = 0; + impl.prev_ = 0; + } + + // Assign a native handle to a handle implementation. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (iocp_service_.register_handle(native_handle, ec)) + return ec; + + impl.handle_ = native_handle; + ec = boost::system::error_code(); + return ec; + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return impl.handle_ != INVALID_HANDLE_VALUE; + } + + // Destroy a handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + if (!::CloseHandle(impl.handle_)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + } + + ec = boost::system::error_code(); + return ec; + } + + // Get the native handle representation. + native_type native(const implementation_type& impl) const + { + return impl.handle_; + } + + // Cancel all operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + } + else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( + ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) + { + // The version of Windows supports cancellation from any thread. + typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); + cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr; + if (!cancel_io_ex(impl.handle_, 0)) + { + DWORD last_error = ::GetLastError(); + if (last_error == ERROR_NOT_FOUND) + { + // ERROR_NOT_FOUND means that there were no operations to be + // cancelled. We swallow this error to match the behaviour on other + // platforms. + ec = boost::system::error_code(); + } + else + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + } + else + { + ec = boost::system::error_code(); + } + } + else if (impl.safe_cancellation_thread_id_ == 0) + { + // No operations have been started, so there's nothing to cancel. + ec = boost::system::error_code(); + } + else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId()) + { + // Asynchronous operations have been started from the current thread only, + // so it is safe to try to cancel them using CancelIo. + if (!::CancelIo(impl.handle_)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + else + { + ec = boost::system::error_code(); + } + } + else + { + // Asynchronous operations have been started from more than one thread, + // so cancellation is not safe. + ec = boost::asio::error::operation_not_supported; + } + + return ec; + } + + class overlapped_wrapper + : public OVERLAPPED + { + public: + explicit overlapped_wrapper(boost::system::error_code& ec) + { + Internal = 0; + InternalHigh = 0; + Offset = 0; + OffsetHigh = 0; + + // Create a non-signalled manual-reset event, for GetOverlappedResult. + hEvent = ::CreateEvent(0, TRUE, FALSE, 0); + if (hEvent) + { + // As documented in GetQueuedCompletionStatus, setting the low order + // bit of this event prevents our synchronous writes from being treated + // as completion port events. + *reinterpret_cast(&hEvent) |= 1; + } + else + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + } + + ~overlapped_wrapper() + { + if (hEvent) + { + ::CloseHandle(hEvent); + } + } + }; + + // Write the given data. Returns the number of bytes written. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return write_some_at(impl, 0, buffers, ec); + } + + // Write the given data at the specified offset. Returns the number of bytes + // written. + template + size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Find first buffer of non-zero length. + boost::asio::const_buffer buffer; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = boost::asio::const_buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + break; + } + + // A request to write 0 bytes on a handle is a no-op. + if (boost::asio::buffer_size(buffer) == 0) + { + ec = boost::system::error_code(); + return 0; + } + + overlapped_wrapper overlapped(ec); + if (ec) + { + return 0; + } + + // Write the data. + overlapped.Offset = offset & 0xFFFFFFFF; + overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::WriteFile(impl.handle_, + boost::asio::buffer_cast(buffer), + static_cast(boost::asio::buffer_size(buffer)), 0, &overlapped); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error != ERROR_IO_PENDING) + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return 0; + } + } + + // Wait for the operation to complete. + DWORD bytes_transferred = 0; + ok = ::GetOverlappedResult(impl.handle_, + &overlapped, &bytes_transferred, TRUE); + if (!ok) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + template + class write_operation + : public operation + { + public: + write_operation(win_iocp_io_service& io_service, + const ConstBufferSequence& buffers, Handler handler) + : operation(io_service, + &write_operation::do_completion_impl, + &write_operation::destroy_impl), + work_(io_service.get_io_service()), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef write_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename ConstBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename ConstBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + boost::asio::const_buffer buffer(*iter); + boost::asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost_asio_handler_invoke_helpers::invoke( + bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef write_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + boost::asio::io_service::work work_; + ConstBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + async_write_some_at(impl, 0, buffers, handler); + } + + // Start an asynchronous write at a specified offset. The data being written + // must be valid for the lifetime of the asynchronous operation. + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + return; + } + + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); + + // Allocate and construct an operation to wrap the handler. + typedef write_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); + + // Find first buffer of non-zero length. + boost::asio::const_buffer buffer; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = boost::asio::const_buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + break; + } + + // A request to write 0 bytes on a handle is a no-op. + if (boost::asio::buffer_size(buffer) == 0) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code error; + iocp_service_.post(bind_handler(handler, error, 0)); + return; + } + + // Write the data. + DWORD bytes_transferred = 0; + ptr.get()->Offset = offset & 0xFFFFFFFF; + ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::WriteFile(impl.handle_, + boost::asio::buffer_cast(buffer), + static_cast(boost::asio::buffer_size(buffer)), + &bytes_transferred, ptr.get()); + DWORD last_error = ::GetLastError(); + + // Check if the operation completed immediately. + if (!ok && last_error != ERROR_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return read_some_at(impl, 0, buffers, ec); + } + + // Read some data at a specified offset. Returns the number of bytes received. + template + size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Find first buffer of non-zero length. + boost::asio::mutable_buffer buffer; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = boost::asio::mutable_buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + break; + } + + // A request to read 0 bytes on a stream handle is a no-op. + if (boost::asio::buffer_size(buffer) == 0) + { + ec = boost::system::error_code(); + return 0; + } + + overlapped_wrapper overlapped(ec); + if (ec) + { + return 0; + } + + // Read some data. + overlapped.Offset = offset & 0xFFFFFFFF; + overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::ReadFile(impl.handle_, + boost::asio::buffer_cast(buffer), + static_cast(boost::asio::buffer_size(buffer)), 0, &overlapped); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error != ERROR_IO_PENDING) + { + if (last_error == ERROR_HANDLE_EOF) + { + ec = boost::asio::error::eof; + } + else + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + return 0; + } + } + + // Wait for the operation to complete. + DWORD bytes_transferred = 0; + ok = ::GetOverlappedResult(impl.handle_, + &overlapped, &bytes_transferred, TRUE); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error == ERROR_HANDLE_EOF) + { + ec = boost::asio::error::eof; + } + else + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + template + class read_operation + : public operation + { + public: + read_operation(win_iocp_io_service& io_service, + const MutableBufferSequence& buffers, Handler handler) + : operation(io_service, + &read_operation< + MutableBufferSequence, Handler>::do_completion_impl, + &read_operation< + MutableBufferSequence, Handler>::destroy_impl), + work_(io_service.get_io_service()), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef read_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename MutableBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename MutableBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + boost::asio::mutable_buffer buffer(*iter); + boost::asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Check for the end-of-file condition. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF) + { + ec = boost::asio::error::eof; + } + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost_asio_handler_invoke_helpers::invoke( + bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef read_operation op_type; + op_type* handler_op(static_cast(op)); + typedef boost::asio::detail::handler_alloc_traits< + Handler, op_type> alloc_traits; + boost::asio::detail::handler_ptr ptr( + handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + boost::asio::io_service::work work_; + MutableBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + async_read_some_at(impl, 0, buffers, handler); + } + + // Start an asynchronous read at a specified offset. The buffer for the data + // being received must be valid for the lifetime of the asynchronous + // operation. + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + return; + } + + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); + + // Allocate and construct an operation to wrap the handler. + typedef read_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); + + // Find first buffer of non-zero length. + boost::asio::mutable_buffer buffer; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = boost::asio::mutable_buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + break; + } + + // A request to receive 0 bytes on a stream handle is a no-op. + if (boost::asio::buffer_size(buffer) == 0) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code error; + iocp_service_.post(bind_handler(handler, error, 0)); + return; + } + + // Read some data. + DWORD bytes_transferred = 0; + ptr.get()->Offset = offset & 0xFFFFFFFF; + ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::ReadFile(impl.handle_, + boost::asio::buffer_cast(buffer), + static_cast(boost::asio::buffer_size(buffer)), + &bytes_transferred, ptr.get()); + DWORD last_error = ::GetLastError(); + if (!ok && last_error != ERROR_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + +private: + // Prevent the use of the null_buffers type with this service. + size_t write_some(implementation_type& impl, + const null_buffers& buffers, boost::system::error_code& ec); + size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, boost::system::error_code& ec); + template + void async_write_some(implementation_type& impl, + const null_buffers& buffers, Handler handler); + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, Handler handler); + size_t read_some(implementation_type& impl, + const null_buffers& buffers, boost::system::error_code& ec); + size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, boost::system::error_code& ec); + template + void async_read_some(implementation_type& impl, + const null_buffers& buffers, Handler handler); + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, Handler handler); + + // Helper function to close a handle when the associated object is being + // destroyed. + void close_for_destruction(implementation_type& impl) + { + if (is_open(impl)) + { + ::CloseHandle(impl.handle_); + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + } + } + + // The IOCP service used for running asynchronous operations and dispatching + // handlers. + win_iocp_io_service& iocp_service_; + + // Mutex to protect access to the linked list of implementations. + boost::asio::detail::mutex mutex_; + + // The head of a linked list of all implementations. + implementation_type* impl_list_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP diff --git a/include/boost/asio/detail/win_iocp_io_service.hpp b/include/boost/asio/detail/win_iocp_io_service.hpp index 44c7788c..ab590fb0 100644 --- a/include/boost/asio/detail/win_iocp_io_service.hpp +++ b/include/boost/asio/detail/win_iocp_io_service.hpp @@ -150,9 +150,20 @@ public: } // Register a handle with the IO completion port. - void register_handle(HANDLE handle) + boost::system::error_code register_handle( + HANDLE handle, boost::system::error_code& ec) { - ::CreateIoCompletionPort(handle, iocp_.handle, 0, 0); + if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + else + { + ec = boost::system::error_code(); + } + return ec; } // Run the event loop until stopped or no more work. @@ -425,7 +436,7 @@ private: { timer_queues_copy_[i]->dispatch_timers(); timer_queues_copy_[i]->dispatch_cancellations(); - timer_queues_copy_[i]->cleanup_timers(); + timer_queues_copy_[i]->complete_timers(); } } catch (...) @@ -505,16 +516,18 @@ private: } else { + // Relinquish responsibility for dispatching timers. If the io_service + // is not being stopped then the thread will get an opportunity to + // reacquire timer responsibility on the next loop iteration. + if (dispatching_timers) + { + ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); + } + // The stopped_ flag is always checked to ensure that any leftover // interrupts from a previous run invocation are ignored. if (::InterlockedExchangeAdd(&stopped_, 0) != 0) { - // Relinquish responsibility for dispatching timers. - if (dispatching_timers) - { - ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); - } - // Wake up next thread that is blocked on GetQueuedCompletionStatus. if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) { @@ -637,6 +650,16 @@ private: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } win_iocp_io_service& io_service_; diff --git a/include/boost/asio/detail/win_iocp_serial_port_service.hpp b/include/boost/asio/detail/win_iocp_serial_port_service.hpp new file mode 100644 index 00000000..29c5a201 --- /dev/null +++ b/include/boost/asio/detail/win_iocp_serial_port_service.hpp @@ -0,0 +1,294 @@ +// +// win_iocp_serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP +#define BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include + +#if defined(BOOST_ASIO_HAS_IOCP) + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Extend win_iocp_handle_service to provide serial port support. +class win_iocp_serial_port_service + : public boost::asio::detail::service_base +{ +public: + // The native type of a stream handle. + typedef win_iocp_handle_service::native_type native_type; + + // The implementation type of the stream handle. + typedef win_iocp_handle_service::implementation_type implementation_type; + + win_iocp_serial_port_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + win_iocp_serial_port_service>(io_service), + handle_service_( + boost::asio::use_service(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + handle_service_.construct(impl); + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + handle_service_.destroy(impl); + } + + // Open the serial port using the specified device name. + boost::system::error_code open(implementation_type& impl, + const std::string& device, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + // For convenience, add a leading \\.\ sequence if not already present. + std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device; + + // Open a handle to the serial port. + ::HANDLE handle = ::CreateFileA(name.c_str(), + GENERIC_READ | GENERIC_WRITE, 0, 0, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if (handle == INVALID_HANDLE_VALUE) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + // Determine the initial serial port parameters. + using namespace std; // For memcpy. + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle, &dcb)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + // Set some default serial port parameters. This implementation does not + // support changing these, so they might as well be in a known state. + dcb.fBinary = TRUE; // Win32 only supports binary mode. + dcb.fDsrSensitivity = FALSE; + dcb.fNull = FALSE; // Do not ignore NULL characters. + dcb.fAbortOnError = FALSE; // Ignore serial framing errors. + if (!::SetCommState(handle, &dcb)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + // Set up timeouts so that the serial port will behave similarly to a + // network socket. Reads wait for at least one byte, then return with + // whatever they have. Writes return once everything is out the door. + ::COMMTIMEOUTS timeouts; + timeouts.ReadIntervalTimeout = 1; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + if (!::SetCommTimeouts(handle, &timeouts)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + // We're done. Take ownership of the serial port handle. + if (handle_service_.assign(impl, handle, ec)) + ::CloseHandle(handle); + return ec; + } + + // Assign a native handle to a handle implementation. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + return handle_service_.assign(impl, native_handle, ec); + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return handle_service_.is_open(impl); + } + + // Destroy a handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return handle_service_.close(impl, ec); + } + + // Get the native handle representation. + native_type native(implementation_type& impl) + { + return handle_service_.native(impl); + } + + // Cancel all operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return handle_service_.cancel(impl, ec); + } + + // Set an option on the serial port. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, boost::system::error_code& ec) + { + using namespace std; // For memcpy. + + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + if (option.store(dcb, ec)) + return ec; + + if (!::SetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Get an option from the serial port. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, boost::system::error_code& ec) const + { + using namespace std; // For memcpy. + + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + return option.load(dcb, ec); + } + + // Send a break sequence to the serial port. + boost::system::error_code send_break(implementation_type& impl, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Write the given data. Returns the number of bytes sent. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return handle_service_.write_some(impl, buffers, ec); + } + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + handle_service_.async_write_some(impl, buffers, handler); + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return handle_service_.read_some(impl, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + handle_service_.async_read_some(impl, buffers, handler); + } + +private: + // The handle service used for initiating asynchronous operations. + win_iocp_handle_service& handle_service_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP diff --git a/include/boost/asio/detail/win_iocp_socket_service.hpp b/include/boost/asio/detail/win_iocp_socket_service.hpp index bfef08e0..1c0ca1bc 100644 --- a/include/boost/asio/detail/win_iocp_socket_service.hpp +++ b/include/boost/asio/detail/win_iocp_socket_service.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,9 @@ public: endpoint_type remote_endpoint_; }; + // The type of the reactor used for connect operations. + typedef detail::select_reactor reactor_type; + // The implementation type of the socket. class implementation_type { @@ -156,6 +160,9 @@ public: // The protocol associated with the socket. protocol_type protocol_; + // Per-descriptor data used by the reactor. + reactor_type::per_descriptor_data reactor_data_; + #if defined(BOOST_ASIO_ENABLE_CANCELIO) // The ID of the thread from which it is safe to cancel asynchronous // operations. 0 means no asynchronous operations have been started yet. @@ -169,9 +176,6 @@ public: implementation_type* prev_; }; - // The type of the reactor used for connect operations. - typedef detail::select_reactor reactor_type; - // The maximum number of buffers to support in a single operation. enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; @@ -252,7 +256,8 @@ public: return ec; HANDLE sock_as_handle = reinterpret_cast(sock.get()); - iocp_service_.register_handle(sock_as_handle); + if (iocp_service_.register_handle(sock_as_handle, ec)) + return ec; impl.socket_ = sock.release(); impl.flags_ = 0; @@ -273,7 +278,8 @@ public: return ec; } - iocp_service_.register_handle(native_socket.as_handle()); + if (iocp_service_.register_handle(native_socket.as_handle(), ec)) + return ec; impl.socket_ = native_socket; impl.flags_ = 0; @@ -302,7 +308,7 @@ public: interlocked_compare_exchange_pointer( reinterpret_cast(&reactor_), 0, 0)); if (reactor) - reactor->close_descriptor(impl.socket_); + reactor->close_descriptor(impl.socket_, impl.reactor_data_); if (socket_ops::close(impl.socket_, ec) == socket_error_retval) return ec; @@ -332,6 +338,7 @@ public: if (!is_open(impl)) { ec = boost::asio::error::bad_descriptor; + return ec; } else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) @@ -700,6 +707,22 @@ public: return bytes_transferred; } + // Wait until data can be sent without blocking. + size_t send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + template class send_operation : public operation @@ -776,6 +799,16 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } boost::asio::io_service::work work_; @@ -858,6 +891,65 @@ public: } } + template + class null_buffers_operation + { + public: + null_buffers_operation(boost::asio::io_service& io_service, Handler handler) + : work_(io_service), + handler_(handler) + { + } + + bool perform(boost::system::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + handler_, ec, bytes_transferred)); + } + + private: + boost::asio::io_service::work work_; + Handler handler_; + }; + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + reactor->start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Send a datagram to the specified endpoint. Returns the number of bytes // sent. template @@ -902,6 +994,23 @@ public: return bytes_transferred; } + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + template class send_to_operation : public operation @@ -969,6 +1078,16 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } boost::asio::io_service::work work_; @@ -1038,6 +1157,36 @@ public: } } + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + reactor->start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + // Receive some data from the peer. Returns the number of bytes received. template size_t receive(implementation_type& impl, @@ -1087,7 +1236,7 @@ public: boost::asio::error::get_system_category()); return 0; } - if (bytes_transferred == 0) + if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM) { ec = boost::asio::error::eof; return 0; @@ -1097,12 +1246,28 @@ public: return bytes_transferred; } + // Wait until data can be received without blocking. + size_t receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + return 0; + } + template class receive_operation : public operation { public: - receive_operation(win_iocp_io_service& io_service, + receive_operation(int protocol_type, win_iocp_io_service& io_service, weak_cancel_token_type cancel_token, const MutableBufferSequence& buffers, Handler handler) : operation(io_service, @@ -1110,6 +1275,7 @@ public: MutableBufferSequence, Handler>::do_completion_impl, &receive_operation< MutableBufferSequence, Handler>::destroy_impl), + protocol_type_(protocol_type), work_(io_service.get_io_service()), cancel_token_(cancel_token), buffers_(buffers), @@ -1157,7 +1323,9 @@ public: } // Check for connection closed. - else if (!ec && bytes_transferred == 0) + else if (!ec && bytes_transferred == 0 + && handler_op->protocol_type_ == SOCK_STREAM + && !boost::is_same::value) { ec = boost::asio::error::eof; } @@ -1181,8 +1349,19 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } + int protocol_type_; boost::asio::io_service::work work_; weak_cancel_token_type cancel_token_; MutableBufferSequence buffers_; @@ -1215,8 +1394,9 @@ public: typedef receive_operation value_type; typedef handler_alloc_traits alloc_traits; raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, iocp_service_, - impl.cancel_token_, buffers, handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, impl.cancel_token_, buffers, handler); // Copy buffers into WSABUF array. ::WSABUF bufs[max_buffers]; @@ -1262,6 +1442,85 @@ public: } } + // Wait until data can be received without blocking. + template + void async_receive(implementation_type& impl, const null_buffers& buffers, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else if (impl.protocol_.type() == SOCK_STREAM) + { + // For stream sockets on Windows, we may issue a 0-byte overlapped + // WSARecv to wait until there is data available on the socket. + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Allocate and construct an operation to wrap the handler. + typedef receive_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, impl.cancel_token_, buffers, handler); + + // Issue a receive operation with an empty buffer. + ::WSABUF buf = { 0, 0 }; + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = ::WSARecv(impl.socket_, &buf, 1, + &bytes_transferred, &recv_flags, ptr.get(), 0); + DWORD last_error = ::WSAGetLastError(); + if (result != 0 && last_error != WSA_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + if (flags & socket_base::message_out_of_band) + { + reactor->start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor->start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + } + // Receive a datagram with the endpoint of the sender. Returns the number of // bytes received. template @@ -1303,7 +1562,7 @@ public: boost::asio::error::get_system_category()); return 0; } - if (bytes_transferred == 0) + if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM) { ec = boost::asio::error::eof; return 0; @@ -1315,12 +1574,32 @@ public: return bytes_transferred; } + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + template class receive_from_operation : public operation { public: - receive_from_operation(win_iocp_io_service& io_service, + receive_from_operation(int protocol_type, win_iocp_io_service& io_service, endpoint_type& endpoint, const MutableBufferSequence& buffers, Handler handler) : operation(io_service, @@ -1328,6 +1607,7 @@ public: MutableBufferSequence, Handler>::do_completion_impl, &receive_from_operation< MutableBufferSequence, Handler>::destroy_impl), + protocol_type_(protocol_type), endpoint_(endpoint), endpoint_size_(static_cast(endpoint.capacity())), work_(io_service.get_io_service()), @@ -1374,7 +1654,8 @@ public: } // Check for connection closed. - if (!ec && bytes_transferred == 0) + if (!ec && bytes_transferred == 0 + && handler_op->protocol_type_ == SOCK_STREAM) { ec = boost::asio::error::eof; } @@ -1401,8 +1682,19 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } + int protocol_type_; endpoint_type& endpoint_; int endpoint_size_; boost::asio::io_service::work work_; @@ -1437,8 +1729,9 @@ public: typedef receive_from_operation value_type; typedef handler_alloc_traits alloc_traits; raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, iocp_service_, - sender_endp, buffers, handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, sender_endp, buffers, handler); // Copy buffers into WSABUF array. ::WSABUF bufs[max_buffers]; @@ -1473,6 +1766,48 @@ public: } } + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + if (flags & socket_base::message_out_of_band) + { + reactor->start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor->start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + } + // Accept a new connection. template boost::system::error_code accept(implementation_type& impl, Socket& peer, @@ -1493,7 +1828,6 @@ public: for (;;) { - boost::system::error_code ec; socket_holder new_socket; std::size_t addr_len = 0; if (peer_endpoint) @@ -1571,8 +1905,7 @@ public: } private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) + static void do_completion_impl(operation* op, DWORD last_error, size_t) { // Take ownership of the operation object. typedef accept_operation op_type; @@ -1715,6 +2048,16 @@ public: op_type* handler_op(static_cast(op)); typedef handler_alloc_traits alloc_traits; handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); } win_iocp_io_service& io_service_; @@ -1833,58 +2176,38 @@ public: } template - class connect_handler + class connect_operation { public: - connect_handler(socket_type socket, bool user_set_non_blocking, - boost::shared_ptr completed, - boost::asio::io_service& io_service, - reactor_type& reactor, Handler handler) + connect_operation(socket_type socket, bool user_set_non_blocking, + boost::asio::io_service& io_service, Handler handler) : socket_(socket), user_set_non_blocking_(user_set_non_blocking), - completed_(completed), io_service_(io_service), - reactor_(reactor), work_(io_service), handler_(handler) { } - bool operator()(const boost::system::error_code& result) + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) { - // Check whether a handler has already been called for the connection. - // If it has, then we don't want to do anything in this handler. - if (*completed_) - return true; - - // Cancel the other reactor operation for the connection. - *completed_ = true; - reactor_.enqueue_cancel_ops_unlocked(socket_); - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); + if (ec) return true; - } // Get the error code from the connect operation. int connect_error = 0; size_t connect_error_len = sizeof(connect_error); - boost::system::error_code ec; if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec) == socket_error_retval) - { - io_service_.post(bind_handler(handler_, ec)); return true; - } // If connection failed then post the handler with the error code. if (connect_error) { ec = boost::system::error_code(connect_error, boost::asio::error::get_system_category()); - io_service_.post(bind_handler(handler_, ec)); return true; } @@ -1893,24 +2216,23 @@ public: { ioctl_arg_type non_blocking = 0; if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec)) - { - io_service_.post(bind_handler(handler_, ec)); return true; - } } // Post the result of the successful connection operation. ec = boost::system::error_code(); - io_service_.post(bind_handler(handler_, ec)); return true; } + void complete(const boost::system::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(handler_, ec)); + } + private: socket_type socket_; bool user_set_non_blocking_; - boost::shared_ptr completed_; boost::asio::io_service& io_service_; - reactor_type& reactor_; boost::asio::io_service::work work_; Handler handler_; }; @@ -1978,11 +2300,11 @@ public: // The connection is happening in the background, and we need to wait // until the socket becomes writeable. boost::shared_ptr completed(new bool(false)); - reactor->start_write_and_except_ops(impl.socket_, - connect_handler( + reactor->start_connect_op(impl.socket_, impl.reactor_data_, + connect_operation( impl.socket_, (impl.flags_ & implementation_type::user_set_non_blocking) != 0, - completed, this->get_io_service(), *reactor, handler)); + this->get_io_service(), handler)); } else { @@ -2013,7 +2335,7 @@ private: interlocked_compare_exchange_pointer( reinterpret_cast(&reactor_), 0, 0)); if (reactor) - reactor->close_descriptor(impl.socket_); + reactor->close_descriptor(impl.socket_, impl.reactor_data_); // The socket destructor must not block. If the user has changed the // linger option to block in the foreground, we will change it back to the diff --git a/include/boost/asio/detail/win_thread.hpp b/include/boost/asio/detail/win_thread.hpp index 04179ca0..123ced72 100644 --- a/include/boost/asio/detail/win_thread.hpp +++ b/include/boost/asio/detail/win_thread.hpp @@ -44,17 +44,53 @@ class win_thread : private noncopyable { public: + // The purpose of the thread. + enum purpose { internal, external }; + // Constructor. template - win_thread(Function f) + win_thread(Function f, purpose p = internal) + : exit_event_(0) { std::auto_ptr arg(new func(f)); + + ::HANDLE entry_event = 0; + if (p == internal) + { + arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0); + if (!entry_event) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "thread.entry_event"); + boost::throw_exception(e); + } + + arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0); + if (!exit_event_) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(entry_event); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "thread.exit_event"); + boost::throw_exception(e); + } + } + unsigned int thread_id = 0; thread_ = reinterpret_cast(::_beginthreadex(0, 0, win_thread_function, arg.get(), 0, &thread_id)); if (!thread_) { DWORD last_error = ::GetLastError(); + if (entry_event) + ::CloseHandle(entry_event); + if (exit_event_) + ::CloseHandle(exit_event_); boost::system::system_error e( boost::system::error_code(last_error, boost::asio::error::get_system_category()), @@ -62,18 +98,36 @@ public: boost::throw_exception(e); } arg.release(); + + if (entry_event) + { + ::WaitForSingleObject(entry_event, INFINITE); + ::CloseHandle(entry_event); + } } // Destructor. ~win_thread() { ::CloseHandle(thread_); + + // The exit_event_ handle is deliberately allowed to leak here since it + // is an error for the owner of an internal thread not to join() it. } // Wait for the thread to exit. void join() { - ::WaitForSingleObject(thread_, INFINITE); + if (exit_event_) + { + ::WaitForSingleObject(exit_event_, INFINITE); + ::CloseHandle(exit_event_); + ::TerminateThread(thread_, 0); + } + else + { + ::WaitForSingleObject(thread_, INFINITE); + } } private: @@ -84,6 +138,8 @@ private: public: virtual ~func_base() {} virtual void run() = 0; + ::HANDLE entry_event_; + ::HANDLE exit_event_; }; template @@ -106,13 +162,26 @@ private: }; ::HANDLE thread_; + ::HANDLE exit_event_; }; inline unsigned int __stdcall win_thread_function(void* arg) { std::auto_ptr func( static_cast(arg)); + + if (func->entry_event_) + ::SetEvent(func->entry_event_); + func->run(); + + if (HANDLE exit_event = func->exit_event_) + { + func.reset(); + ::SetEvent(exit_event); + ::Sleep(INFINITE); + } + return 0; } diff --git a/include/boost/asio/detail/wince_thread.hpp b/include/boost/asio/detail/wince_thread.hpp index 7b24ec25..6b624872 100644 --- a/include/boost/asio/detail/wince_thread.hpp +++ b/include/boost/asio/detail/wince_thread.hpp @@ -43,9 +43,12 @@ class wince_thread : private noncopyable { public: + // The purpose of the thread. + enum purpose { internal, external }; + // Constructor. template - wince_thread(Function f) + wince_thread(Function f, purpose = internal) { std::auto_ptr arg(new func(f)); DWORD thread_id = 0; diff --git a/include/boost/asio/detail/wrapped_handler.hpp b/include/boost/asio/detail/wrapped_handler.hpp index 8f328bd7..64fc7295 100644 --- a/include/boost/asio/detail/wrapped_handler.hpp +++ b/include/boost/asio/detail/wrapped_handler.hpp @@ -128,22 +128,6 @@ public: Handler handler_; }; -template -inline void* asio_handler_allocate(std::size_t size, - wrapped_handler* this_handler) -{ - return boost_asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - wrapped_handler* this_handler) -{ - boost_asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - template class rewrapped_handler { @@ -169,6 +153,22 @@ public: Context context_; }; +template +inline void* asio_handler_allocate(std::size_t size, + wrapped_handler* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + wrapped_handler* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + template inline void asio_handler_invoke(const Function& function, wrapped_handler* this_handler) @@ -178,6 +178,22 @@ inline void asio_handler_invoke(const Function& function, function, this_handler->handler_)); } +template +inline void* asio_handler_allocate(std::size_t size, + rewrapped_handler* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->context_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + rewrapped_handler* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->context_); +} + template inline void asio_handler_invoke(const Function& function, rewrapped_handler* this_handler) diff --git a/include/boost/asio/error.hpp b/include/boost/asio/error.hpp index 1c02df43..01019453 100644 --- a/include/boost/asio/error.hpp +++ b/include/boost/asio/error.hpp @@ -106,6 +106,9 @@ enum basic_errors /// Message too long. message_size = BOOST_ASIO_SOCKET_ERROR(EMSGSIZE), + /// The name was too long. + name_too_long = BOOST_ASIO_SOCKET_ERROR(ENAMETOOLONG), + /// Network is down. network_down = BOOST_ASIO_SOCKET_ERROR(ENETDOWN), diff --git a/include/boost/asio/impl/read_at.ipp b/include/boost/asio/impl/read_at.ipp new file mode 100644 index 00000000..e2240bb6 --- /dev/null +++ b/include/boost/asio/impl/read_at.ipp @@ -0,0 +1,339 @@ +// +// read_at.ipp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_READ_AT_IPP +#define BOOST_ASIO_READ_AT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = d.read_some_at( + offset + total_transferred, tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + if (completion_condition(ec, total_transferred)) + return total_transferred; + } + ec = boost::system::error_code(); + return total_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, buffers, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, buffers, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + std::size_t total_transferred = 0; + for (;;) + { + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + std::size_t bytes_transferred = d.read_some_at( + offset + total_transferred, b.prepare(bytes_available), ec); + b.commit(bytes_transferred); + total_transferred += bytes_transferred; + if (b.size() == b.max_size() + || completion_condition(ec, total_transferred)) + return total_transferred; + } +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, b, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, b, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class read_at_handler + { + public: + typedef boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> buffers_type; + + read_at_handler(AsyncRandomAccessReadDevice& stream, + boost::uint64_t offset, const buffers_type& buffers, + CompletionCondition completion_condition, ReadHandler handler) + : stream_(stream), + offset_(offset), + buffers_(buffers), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + if (completion_condition_(ec, total_transferred_) + || buffers_.begin() == buffers_.end()) + { + handler_(ec, total_transferred_); + } + else + { + stream_.async_read_some_at( + offset_ + total_transferred_, buffers_, *this); + } + } + + //private: + AsyncRandomAccessReadDevice& stream_; + boost::uint64_t offset_; + buffers_type buffers_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_at_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_at_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_at_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler handler) +{ + boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + d.async_read_some_at(offset, tmp, + detail::read_at_handler( + d, offset, tmp, completion_condition, handler)); +} + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + ReadHandler handler) +{ + async_read_at(d, offset, buffers, transfer_all(), handler); +} + +namespace detail +{ + template + class read_at_streambuf_handler + { + public: + read_at_streambuf_handler(AsyncRandomAccessReadDevice& stream, + boost::uint64_t offset, basic_streambuf& streambuf, + CompletionCondition completion_condition, ReadHandler handler) + : stream_(stream), + offset_(offset), + streambuf_(streambuf), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + streambuf_.commit(bytes_transferred); + if (streambuf_.size() == streambuf_.max_size() + || completion_condition_(ec, total_transferred_)) + { + handler_(ec, total_transferred_); + } + else + { + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some_at(offset_ + total_transferred_, + streambuf_.prepare(bytes_available), *this); + } + } + + //private: + AsyncRandomAccessReadDevice& stream_; + boost::uint64_t offset_; + boost::asio::basic_streambuf& streambuf_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_at_streambuf_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_at_streambuf_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_at_streambuf_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, ReadHandler handler) +{ + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + d.async_read_some_at(offset, b.prepare(bytes_available), + detail::read_at_streambuf_handler( + d, offset, b, completion_condition, handler)); +} + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + ReadHandler handler) +{ + async_read_at(d, offset, b, transfer_all(), handler); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_READ_AT_IPP diff --git a/include/boost/asio/impl/read_until.ipp b/include/boost/asio/impl/read_until.ipp index 2a8ce056..8c970a71 100644 --- a/include/boost/asio/impl/read_until.ipp +++ b/include/boost/asio/impl/read_until.ipp @@ -25,8 +25,8 @@ #include #include +#include #include -#include #include #include #include @@ -55,24 +55,24 @@ std::size_t read_until(SyncReadStream& s, // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); // Look for a match. - iterator iter = std::find(begin, end, delim); + iterator iter = std::find(start, end, delim); if (iter != end) { // Found a match. We're done. ec = boost::system::error_code(); - return iter.position() + 1; + return iter - begin + 1; } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -147,33 +147,33 @@ std::size_t read_until(SyncReadStream& s, // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); // Look for a match. std::pair result = boost::asio::detail::partial_search( - begin, end, delim.begin(), delim.end()); + start, end, delim.begin(), delim.end()); if (result.first != end) { if (result.second) { // Full match. We're done. ec = boost::system::error_code(); - return result.first.position() + delim.length(); + return result.first - begin + delim.length(); } else { // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first.position(); + next_search_start = result.first - begin; } } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -213,33 +213,33 @@ std::size_t read_until(SyncReadStream& s, // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); // Look for a match. boost::match_results match_results; - if (boost::regex_search(begin, end, match_results, expr, + if (boost::regex_search(start, end, match_results, expr, boost::match_default | boost::match_partial)) { if (match_results[0].matched) { // Full match. We're done. ec = boost::system::error_code(); - return match_results[0].second.position(); + return match_results[0].second - begin; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start = match_results[0].first.position(); + next_search_start = match_results[0].first - begin; } } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -258,6 +258,73 @@ std::size_t read_until(SyncReadStream& s, } } +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, + MatchCondition match_condition, boost::system::error_code& ec, + typename boost::enable_if >::type*) +{ + std::size_t next_search_start = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); + + // Look for a match. + std::pair result = match_condition(start, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + ec = boost::system::error_code(); + return result.first - begin; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + b.commit(s.read_some(b.prepare(bytes_available), ec)); + if (ec) + return 0; + } +} + +template +inline std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, MatchCondition match_condition, + typename boost::enable_if >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, b, match_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + namespace detail { template @@ -292,18 +359,18 @@ namespace detail // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); // Look for a match. - iterator iter = std::find(begin, end, delim_); + iterator iter = std::find(start, end, delim_); if (iter != end) { // Found a match. We're done. - std::size_t bytes = iter.position() + 1; + std::size_t bytes = iter - begin + 1; handler_(ec, bytes); return; } @@ -318,7 +385,7 @@ namespace detail } // Next search can start with the new data. - next_search_start_ = end.position(); + next_search_start_ = end - begin; // Start a new asynchronous read operation to obtain more data. std::size_t bytes_available = @@ -370,11 +437,10 @@ void async_read_until(AsyncReadStream& s, // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); // Look for a match. iterator iter = std::find(begin, end, delim); @@ -382,7 +448,7 @@ void async_read_until(AsyncReadStream& s, { // Found a match. We're done. boost::system::error_code ec; - std::size_t bytes = iter.position() + 1; + std::size_t bytes = iter - begin + 1; s.io_service().post(detail::bind_handler(handler, ec, bytes)); return; } @@ -400,7 +466,7 @@ void async_read_until(AsyncReadStream& s, std::min(512, b.max_size() - b.size()); s.async_read_some(b.prepare(bytes_available), detail::read_until_delim_handler( - s, b, delim, end.position(), handler)); + s, b, delim, end - begin, handler)); } namespace detail @@ -438,34 +504,34 @@ namespace detail // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); // Look for a match. std::pair result = boost::asio::detail::partial_search( - begin, end, delim_.begin(), delim_.end()); + start, end, delim_.begin(), delim_.end()); if (result.first != end) { if (result.second) { // Full match. We're done. - std::size_t bytes = result.first.position() + delim_.length(); + std::size_t bytes = result.first - begin + delim_.length(); handler_(ec, bytes); return; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start_ = result.first.position(); + next_search_start_ = result.first - begin; } } else { // No match. Next search can start with the new data. - next_search_start_ = end.position(); + next_search_start_ = end - begin; } // Check if buffer is full. @@ -528,11 +594,10 @@ void async_read_until(AsyncReadStream& s, // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); // Look for a match. std::size_t next_search_start; @@ -544,20 +609,20 @@ void async_read_until(AsyncReadStream& s, { // Full match. We're done. boost::system::error_code ec; - std::size_t bytes = result.first.position() + delim.length(); + std::size_t bytes = result.first - begin + delim.length(); s.io_service().post(detail::bind_handler(handler, ec, bytes)); return; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first.position(); + next_search_start = result.first - begin; } } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -612,34 +677,34 @@ namespace detail // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); // Look for a match. boost::match_results match_results; - if (boost::regex_search(begin, end, match_results, expr_, + if (boost::regex_search(start, end, match_results, expr_, boost::match_default | boost::match_partial)) { if (match_results[0].matched) { // Full match. We're done. - std::size_t bytes = match_results[0].second.position(); + std::size_t bytes = match_results[0].second - begin; handler_(ec, bytes); return; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start_ = match_results[0].first.position(); + next_search_start_ = match_results[0].first - begin; } } else { // No match. Next search can start with the new data. - next_search_start_ = end.position(); + next_search_start_ = end - begin; } // Check if buffer is full. @@ -702,11 +767,10 @@ void async_read_until(AsyncReadStream& s, // Determine the range of the data to be searched. typedef typename boost::asio::basic_streambuf< Allocator>::const_buffers_type const_buffers_type; - typedef boost::asio::detail::const_buffers_iterator< - const_buffers_type> iterator; + typedef boost::asio::buffers_iterator iterator; const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); // Look for a match. std::size_t next_search_start; @@ -718,20 +782,20 @@ void async_read_until(AsyncReadStream& s, { // Full match. We're done. boost::system::error_code ec; - std::size_t bytes = match_results[0].second.position(); + std::size_t bytes = match_results[0].second - begin; s.io_service().post(detail::bind_handler(handler, ec, bytes)); return; } else { // Partial match. Next search needs to start from beginning of match. - next_search_start = match_results[0].first.position(); + next_search_start = match_results[0].first - begin; } } else { // No match. Next search can start with the new data. - next_search_start = end.position(); + next_search_start = end - begin; } // Check if buffer is full. @@ -750,6 +814,182 @@ void async_read_until(AsyncReadStream& s, s, b, expr, next_search_start, handler)); } +namespace detail +{ + template + class read_until_match_handler + { + public: + read_until_match_handler(AsyncReadStream& stream, + boost::asio::basic_streambuf& streambuf, + MatchCondition match_condition, std::size_t next_search_start, + ReadHandler handler) + : stream_(stream), + streambuf_(streambuf), + match_condition_(match_condition), + next_search_start_(next_search_start), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + // Check for errors. + if (ec) + { + std::size_t bytes = 0; + handler_(ec, bytes); + return; + } + + // Commit received data to streambuf's get area. + streambuf_.commit(bytes_transferred); + + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = streambuf_.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); + + // Look for a match. + std::pair result = match_condition_(start, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + std::size_t bytes = result.first - begin; + handler_(ec, bytes); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start_ = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start_ = end - begin; + } + + // Check if buffer is full. + if (streambuf_.size() == streambuf_.max_size()) + { + std::size_t bytes = 0; + boost::system::error_code ec(error::not_found); + handler_(ec, bytes); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some(streambuf_.prepare(bytes_available), *this); + } + + //private: + AsyncReadStream& stream_; + boost::asio::basic_streambuf& streambuf_; + MatchCondition match_condition_; + std::size_t next_search_start_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_until_match_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_match_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_until_match_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, + MatchCondition match_condition, ReadHandler handler, + typename boost::enable_if >::type*) +{ + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); + + // Look for a match. + std::size_t next_search_start; + std::pair result = match_condition(begin, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + boost::system::error_code ec; + std::size_t bytes = result.first - begin; + s.io_service().post(detail::bind_handler(handler, ec, bytes)); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + boost::system::error_code ec(error::not_found); + s.io_service().post(detail::bind_handler(handler, ec, 0)); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + s.async_read_some(b.prepare(bytes_available), + detail::read_until_match_handler< + AsyncReadStream, Allocator, MatchCondition, ReadHandler>( + s, b, match_condition, next_search_start, handler)); +} + } // namespace asio } // namespace boost diff --git a/include/boost/asio/impl/serial_port_base.ipp b/include/boost/asio/impl/serial_port_base.ipp new file mode 100644 index 00000000..3dd7ba89 --- /dev/null +++ b/include/boost/asio/impl/serial_port_base.ipp @@ -0,0 +1,541 @@ +// +// serial_port_base.ipp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SERIAL_PORT_BASE_IPP +#define BOOST_ASIO_SERIAL_PORT_BASE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { + +inline serial_port_base::baud_rate::baud_rate(unsigned int rate) + : value_(rate) +{ +} + +inline unsigned int serial_port_base::baud_rate::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::baud_rate::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.BaudRate = value_; +#else + speed_t baud; + switch (value_) + { + // Do POSIX-specified rates first. + case 0: baud = B0; break; + case 50: baud = B50; break; + case 75: baud = B75; break; + case 110: baud = B110; break; + case 134: baud = B134; break; + case 150: baud = B150; break; + case 200: baud = B200; break; + case 300: baud = B300; break; + case 600: baud = B600; break; + case 1200: baud = B1200; break; + case 1800: baud = B1800; break; + case 2400: baud = B2400; break; + case 4800: baud = B4800; break; + case 9600: baud = B9600; break; + case 19200: baud = B19200; break; + case 38400: baud = B38400; break; + // And now the extended ones conditionally. +# ifdef B7200 + case 7200: baud = B7200; break; +# endif +# ifdef B14400 + case 14400: baud = B14400; break; +# endif +# ifdef B57600 + case 57600: baud = B57600; break; +# endif +# ifdef B115200 + case 115200: baud = B115200; break; +# endif +# ifdef B230400 + case 230400: baud = B230400; break; +# endif +# ifdef B460800 + case 460800: baud = B460800; break; +# endif +# ifdef B500000 + case 500000: baud = B500000; break; +# endif +# ifdef B576000 + case 576000: baud = B576000; break; +# endif +# ifdef B921600 + case 921600: baud = B921600; break; +# endif +# ifdef B1000000 + case 1000000: baud = B1000000; break; +# endif +# ifdef B1152000 + case 1152000: baud = B1152000; break; +# endif +# ifdef B2000000 + case 2000000: baud = B2000000; break; +# endif +# ifdef B3000000 + case 3000000: baud = B3000000; break; +# endif +# ifdef B3500000 + case 3500000: baud = B3500000; break; +# endif +# ifdef B4000000 + case 4000000: baud = B4000000; break; +# endif + default: + baud = B0; + ec = boost::asio::error::invalid_argument; + return ec; + } +# if defined(_BSD_SOURCE) + ::cfsetspeed(&storage, baud); +# else + ::cfsetispeed(&storage, baud); + ::cfsetospeed(&storage, baud); +# endif +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::baud_rate::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + value_ = storage.BaudRate; +#else + speed_t baud = ::cfgetospeed(&storage); + switch (baud) + { + // First do those specified by POSIX. + case B0: value_ = 0; break; + case B50: value_ = 50; break; + case B75: value_ = 75; break; + case B110: value_ = 110; break; + case B134: value_ = 134; break; + case B150: value_ = 150; break; + case B200: value_ = 200; break; + case B300: value_ = 300; break; + case B600: value_ = 600; break; + case B1200: value_ = 1200; break; + case B1800: value_ = 1800; break; + case B2400: value_ = 2400; break; + case B4800: value_ = 4800; break; + case B9600: value_ = 9600; break; + case B19200: value_ = 19200; break; + case B38400: value_ = 38400; break; + // Now conditionally handle a bunch of extended rates. +# ifdef B7200 + case B7200: value_ = 7200; break; +# endif +# ifdef B14400 + case B14400: value_ = 14400; break; +# endif +# ifdef B57600 + case B57600: value_ = 57600; break; +# endif +# ifdef B115200 + case B115200: value_ = 115200; break; +# endif +# ifdef B230400 + case B230400: value_ = 230400; break; +# endif +# ifdef B460800 + case B460800: value_ = 460800; break; +# endif +# ifdef B500000 + case B500000: value_ = 500000; break; +# endif +# ifdef B576000 + case B576000: value_ = 576000; break; +# endif +# ifdef B921600 + case B921600: value_ = 921600; break; +# endif +# ifdef B1000000 + case B1000000: value_ = 1000000; break; +# endif +# ifdef B1152000 + case B1152000: value_ = 1152000; break; +# endif +# ifdef B2000000 + case B2000000: value_ = 2000000; break; +# endif +# ifdef B3000000 + case B3000000: value_ = 3000000; break; +# endif +# ifdef B3500000 + case B3500000: value_ = 3500000; break; +# endif +# ifdef B4000000 + case B4000000: value_ = 4000000; break; +# endif + default: + value_ = 0; + ec = boost::asio::error::invalid_argument; + return ec; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline serial_port_base::flow_control::flow_control( + serial_port_base::flow_control::type t) + : value_(t) +{ + if (t != none && t != software && t != hardware) + throw std::out_of_range("invalid flow_control value"); +} + +inline serial_port_base::flow_control::type +serial_port_base::flow_control::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::flow_control::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.fOutxCtsFlow = FALSE; + storage.fOutxDsrFlow = FALSE; + storage.fTXContinueOnXoff = TRUE; + storage.fDtrControl = DTR_CONTROL_ENABLE; + storage.fDsrSensitivity = FALSE; + storage.fOutX = FALSE; + storage.fInX = FALSE; + storage.fRtsControl = RTS_CONTROL_ENABLE; + switch (value_) + { + case none: + break; + case software: + storage.fOutX = TRUE; + storage.fInX = TRUE; + break; + case hardware: + storage.fOutxCtsFlow = TRUE; + storage.fRtsControl = RTS_CONTROL_HANDSHAKE; + break; + default: + break; + } +#else + switch (value_) + { + case none: + storage.c_iflag &= ~(IXOFF | IXON); +# if defined(_BSD_SOURCE) + storage.c_cflag &= ~CRTSCTS; +# endif + break; + case software: + storage.c_iflag |= IXOFF | IXON; +# if defined(_BSD_SOURCE) + storage.c_cflag &= ~CRTSCTS; +# endif + break; + case hardware: +# if defined(_BSD_SOURCE) + storage.c_iflag &= ~(IXOFF | IXON); + storage.c_cflag |= CRTSCTS; + break; +# else + ec = boost::asio::error::operation_not_supported; + return ec; +# endif + default: + break; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::flow_control::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.fOutX && storage.fInX) + { + value_ = software; + } + else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE) + { + value_ = hardware; + } + else + { + value_ = none; + } +#else + if (storage.c_iflag & (IXOFF | IXON)) + { + value_ = software; + } + else if (storage.c_cflag & CRTSCTS) + { + value_ = hardware; + } + else + { + value_ = none; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline serial_port_base::parity::parity(serial_port_base::parity::type t) + : value_(t) +{ + if (t != none && t != odd && t != even) + throw std::out_of_range("invalid parity value"); +} + +inline serial_port_base::parity::type serial_port_base::parity::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::parity::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + switch (value_) + { + case none: + storage.fParity = FALSE; + storage.Parity = NOPARITY; + break; + case odd: + storage.fParity = TRUE; + storage.Parity = ODDPARITY; + break; + case even: + storage.fParity = TRUE; + storage.Parity = EVENPARITY; + break; + default: + break; + } +#else + switch (value_) + { + case none: + storage.c_iflag |= IGNPAR; + storage.c_cflag &= ~(PARENB | PARODD); + break; + case even: + storage.c_iflag &= ~(IGNPAR | PARMRK); + storage.c_iflag |= INPCK; + storage.c_cflag |= PARENB; + storage.c_cflag &= ~PARODD; + break; + case odd: + storage.c_iflag &= ~(IGNPAR | PARMRK); + storage.c_iflag |= INPCK; + storage.c_cflag |= (PARENB | PARODD); + break; + default: + break; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::parity::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.Parity == EVENPARITY) + { + value_ = even; + } + else if (storage.Parity == ODDPARITY) + { + value_ = odd; + } + else + { + value_ = none; + } +#else + if (storage.c_cflag & PARENB) + { + if (storage.c_cflag & PARODD) + { + value_ = odd; + } + else + { + value_ = even; + } + } + else + { + value_ = none; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline serial_port_base::stop_bits::stop_bits( + serial_port_base::stop_bits::type t) + : value_(t) +{ + if (t != one && t != onepointfive && t != two) + throw std::out_of_range("invalid stop_bits value"); +} + +inline serial_port_base::stop_bits::type +serial_port_base::stop_bits::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::stop_bits::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + switch (value_) + { + case one: + storage.StopBits = ONESTOPBIT; + break; + case onepointfive: + storage.StopBits = ONE5STOPBITS; + break; + case two: + storage.StopBits = TWOSTOPBITS; + break; + default: + break; + } +#else + switch (value_) + { + case one: + storage.c_cflag &= ~CSTOPB; + break; + case two: + storage.c_cflag |= CSTOPB; + break; + default: + ec = boost::asio::error::operation_not_supported; + return ec; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::stop_bits::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.StopBits == ONESTOPBIT) + { + value_ = one; + } + else if (storage.StopBits == ONE5STOPBITS) + { + value_ = onepointfive; + } + else if (storage.StopBits == TWOSTOPBITS) + { + value_ = two; + } + else + { + value_ = one; + } +#else + value_ = (storage.c_cflag & CSTOPB) ? two : one; +#endif + ec = boost::system::error_code(); + return ec; +} + +inline serial_port_base::character_size::character_size(unsigned int t) + : value_(t) +{ + if (t < 5 || t > 8) + throw std::out_of_range("invalid character_size value"); +} + +inline unsigned int serial_port_base::character_size::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::character_size::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.ByteSize = value_; +#else + storage.c_cflag &= ~CSIZE; + switch (value_) + { + case 5: storage.c_cflag |= CS5; break; + case 6: storage.c_cflag |= CS6; break; + case 7: storage.c_cflag |= CS7; break; + case 8: storage.c_cflag |= CS8; break; + default: break; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::character_size::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + value_ = storage.ByteSize; +#else + if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; } + else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; } + else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; } + else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; } + else + { + // Hmmm, use 8 for now. + value_ = 8; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SERIAL_PORT_BASE_IPP diff --git a/include/boost/asio/impl/write_at.ipp b/include/boost/asio/impl/write_at.ipp new file mode 100644 index 00000000..d49f55de --- /dev/null +++ b/include/boost/asio/impl/write_at.ipp @@ -0,0 +1,298 @@ +// +// write_at.ipp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WRITE_AT_IPP +#define BOOST_ASIO_WRITE_AT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = d.write_some_at( + offset + total_transferred, tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + if (completion_condition(ec, total_transferred)) + return total_transferred; + } + ec = boost::system::error_code(); + return total_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, buffers, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, buffers, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + std::size_t bytes_transferred = write_at( + d, offset, b.data(), completion_condition, ec); + b.consume(bytes_transferred); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, b, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class write_at_handler + { + public: + typedef boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> buffers_type; + + write_at_handler(AsyncRandomAccessWriteDevice& stream, + boost::uint64_t offset, const buffers_type& buffers, + CompletionCondition completion_condition, WriteHandler handler) + : stream_(stream), + buffers_(buffers), + offset_(offset), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + if (completion_condition_(ec, total_transferred_) + || buffers_.begin() == buffers_.end()) + { + handler_(ec, total_transferred_); + } + else + { + stream_.async_write_some_at( + offset_ + total_transferred_, buffers_, *this); + } + } + + //private: + AsyncRandomAccessWriteDevice& stream_; + buffers_type buffers_; + boost::uint64_t offset_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + write_at_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_at_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + write_at_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler handler) +{ + boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + d.async_write_some_at(offset, tmp, + detail::write_at_handler( + d, offset, tmp, completion_condition, handler)); +} + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + WriteHandler handler) +{ + async_write_at(d, offset, buffers, transfer_all(), handler); +} + +namespace detail +{ + template + class write_at_streambuf_handler + { + public: + write_at_streambuf_handler( + boost::asio::basic_streambuf& streambuf, + WriteHandler handler) + : streambuf_(streambuf), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + streambuf_.consume(bytes_transferred); + handler_(ec, bytes_transferred); + } + + //private: + boost::asio::basic_streambuf& streambuf_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + write_at_streambuf_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_at_streambuf_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + write_at_streambuf_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, WriteHandler handler) +{ + async_write_at(d, offset, b.data(), completion_condition, + detail::write_at_streambuf_handler< + AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler)); +} + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + WriteHandler handler) +{ + async_write_at(d, offset, b, transfer_all(), handler); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_WRITE_AT_IPP diff --git a/include/boost/asio/ip/icmp.hpp b/include/boost/asio/ip/icmp.hpp new file mode 100644 index 00000000..1230128e --- /dev/null +++ b/include/boost/asio/ip/icmp.hpp @@ -0,0 +1,120 @@ +// +// icmp.hpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_ICMP_HPP +#define BOOST_ASIO_IP_ICMP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Encapsulates the flags needed for ICMP. +/** + * The boost::asio::ip::icmp class contains flags necessary for ICMP sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol, InternetProtocol. + */ +class icmp +{ +public: + /// The type of a ICMP endpoint. + typedef basic_endpoint endpoint; + + /// The type of a resolver query. + typedef basic_resolver_query resolver_query; + + /// The type of a resolver iterator. + typedef basic_resolver_iterator resolver_iterator; + + /// Construct to represent the IPv4 ICMP protocol. + static icmp v4() + { + return icmp(IPPROTO_ICMP, PF_INET); + } + + /// Construct to represent the IPv6 ICMP protocol. + static icmp v6() + { + return icmp(IPPROTO_ICMPV6, PF_INET6); + } + + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_RAW; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return protocol_; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return family_; + } + + /// The ICMP socket type. + typedef basic_raw_socket socket; + + /// The ICMP resolver type. + typedef basic_resolver resolver; + + /// Compare two protocols for equality. + friend bool operator==(const icmp& p1, const icmp& p2) + { + return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_; + } + + /// Compare two protocols for inequality. + friend bool operator!=(const icmp& p1, const icmp& p2) + { + return p1.protocol_ != p2.protocol_ || p1.family_ != p2.family_; + } + +private: + // Construct with a specific family. + explicit icmp(int protocol, int family) + : protocol_(protocol), + family_(family) + { + } + + int protocol_; + int family_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_ICMP_HPP diff --git a/include/boost/asio/local/basic_endpoint.hpp b/include/boost/asio/local/basic_endpoint.hpp new file mode 100644 index 00000000..a9c1b559 --- /dev/null +++ b/include/boost/asio/local/basic_endpoint.hpp @@ -0,0 +1,267 @@ +// +// basic_endpoint.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Derived from a public domain implementation written by Daniel Casimiro. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP +#define BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS) +# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_LOCAL_SOCKETS 1 +# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS) + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + + +namespace boost { +namespace asio { +namespace local { + +/// Describes an endpoint for a UNIX socket. +/** + * The boost::asio::local::basic_endpoint class template describes an endpoint + * that may be associated with a particular UNIX socket. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * Endpoint. + */ +template +class basic_endpoint +{ +public: + /// The protocol type associated with the endpoint. + typedef Protocol protocol_type; + + /// The type of the endpoint structure. This type is dependent on the + /// underlying implementation of the socket layer. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined data_type; +#else + typedef boost::asio::detail::socket_addr_type data_type; +#endif + + /// Default constructor. + basic_endpoint() + { + init("", 0); + } + + /// Construct an endpoint using the specified path name. + basic_endpoint(const char* path) + { + using namespace std; // For strlen. + init(path, strlen(path)); + } + + /// Construct an endpoint using the specified path name. + basic_endpoint(const std::string& path) + { + init(path.data(), path.length()); + } + + /// Copy constructor. + basic_endpoint(const basic_endpoint& other) + : data_(other.data_), + path_length_(other.path_length_) + { + } + + /// Assign from another endpoint. + basic_endpoint& operator=(const basic_endpoint& other) + { + data_ = other.data_; + path_length_ = other.path_length_; + return *this; + } + + /// The protocol associated with the endpoint. + protocol_type protocol() const + { + return protocol_type(); + } + + /// Get the underlying endpoint in the native type. + data_type* data() + { + return &data_.base; + } + + /// Get the underlying endpoint in the native type. + const data_type* data() const + { + return &data_.base; + } + + /// Get the underlying size of the endpoint in the native type. + std::size_t size() const + { + return path_length_ + + offsetof(boost::asio::detail::sockaddr_un_type, sun_path); + } + + /// Set the underlying size of the endpoint in the native type. + void resize(std::size_t size) + { + if (size > sizeof(boost::asio::detail::sockaddr_un_type)) + { + boost::system::system_error e(boost::asio::error::invalid_argument); + boost::throw_exception(e); + } + else if (size == 0) + { + path_length_ = 0; + } + else + { + path_length_ = size + - offsetof(boost::asio::detail::sockaddr_un_type, sun_path); + + // The path returned by the operating system may be NUL-terminated. + if (path_length_ > 0 && data_.local.sun_path[path_length_] == 0) + --path_length_; + } + } + + /// Get the capacity of the endpoint in the native type. + std::size_t capacity() const + { + return sizeof(boost::asio::detail::sockaddr_un_type); + } + + /// Get the path associated with the endpoint. + std::string path() const + { + return std::string(data_.local.sun_path, path_length_); + } + + /// Set the path associated with the endpoint. + void path(const char* p) + { + using namespace std; // For strlen. + init(p, strlen(p)); + } + + /// Set the path associated with the endpoint. + void path(const std::string& p) + { + init(p.data(), p.length()); + } + + /// Compare two endpoints for equality. + friend bool operator==(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() == e2.path(); + } + + /// Compare two endpoints for inequality. + friend bool operator!=(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() != e2.path(); + } + + /// Compare endpoints for ordering. + friend bool operator<(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() < e2.path(); + } + +private: + // The underlying UNIX socket address. + union data_union + { + boost::asio::detail::socket_addr_type base; + boost::asio::detail::sockaddr_un_type local; + } data_; + + // The length of the path associated with the endpoint. + std::size_t path_length_; + + // Initialise with a specified path. + void init(const char* path, std::size_t path_length) + { + if (path_length > sizeof(data_.local.sun_path) - 1) + { + // The buffer is not large enough to store this address. + boost::system::error_code ec(boost::asio::error::name_too_long); + boost::asio::detail::throw_error(ec); + } + + using namespace std; // For memcpy. + data_.local = boost::asio::detail::sockaddr_un_type(); + data_.local.sun_family = AF_UNIX; + memcpy(data_.local.sun_path, path, path_length); + path_length_ = path_length; + + // NUL-terminate normal path names. Names that start with a NUL are in the + // UNIX domain protocol's "abstract namespace" and are not NUL-terminated. + if (path_length > 0 && data_.local.sun_path[0] == 0) + data_.local.sun_path[path_length] = 0; + } +}; + +/// Output an endpoint as a string. +/** + * Used to output a human-readable string for a specified endpoint. + * + * @param os The output stream to which the string will be written. + * + * @param endpoint The endpoint to be written. + * + * @return The output stream. + * + * @relates boost::asio::local::basic_endpoint + */ +template +std::basic_ostream& operator<<( + std::basic_ostream& os, + const basic_endpoint& endpoint) +{ + os << endpoint.path(); + return os; +} + +} // namespace local +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP diff --git a/include/boost/asio/local/connect_pair.hpp b/include/boost/asio/local/connect_pair.hpp new file mode 100644 index 00000000..39a5e2af --- /dev/null +++ b/include/boost/asio/local/connect_pair.hpp @@ -0,0 +1,102 @@ +// +// connect_pair.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP +#define BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace local { + +/// Create a pair of connected sockets. +template +void connect_pair( + basic_socket& socket1, + basic_socket& socket2); + +/// Create a pair of connected sockets. +template +boost::system::error_code connect_pair( + basic_socket& socket1, + basic_socket& socket2, + boost::system::error_code& ec); + +template +inline void connect_pair( + basic_socket& socket1, + basic_socket& socket2) +{ + boost::system::error_code ec; + connect_pair(socket1, socket2, ec); + boost::asio::detail::throw_error(ec); +} + +template +inline boost::system::error_code connect_pair( + basic_socket& socket1, + basic_socket& socket2, + boost::system::error_code& ec) +{ + // Check that this function is only being used with a UNIX domain socket. + boost::asio::local::basic_endpoint* tmp + = static_cast(0); + (void)tmp; + + Protocol protocol; + boost::asio::detail::socket_type sv[2]; + if (boost::asio::detail::socket_ops::socketpair(protocol.family(), + protocol.type(), protocol.protocol(), sv, ec) + == boost::asio::detail::socket_error_retval) + return ec; + + if (socket1.assign(protocol, sv[0], ec)) + { + boost::system::error_code temp_ec; + boost::asio::detail::socket_ops::close(sv[0], temp_ec); + boost::asio::detail::socket_ops::close(sv[1], temp_ec); + return ec; + } + + if (socket2.assign(protocol, sv[1], ec)) + { + boost::system::error_code temp_ec; + socket1.close(temp_ec); + boost::asio::detail::socket_ops::close(sv[1], temp_ec); + return ec; + } + + return ec; +} + +} // namespace local +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP diff --git a/include/boost/asio/local/datagram_protocol.hpp b/include/boost/asio/local/datagram_protocol.hpp new file mode 100644 index 00000000..75407c25 --- /dev/null +++ b/include/boost/asio/local/datagram_protocol.hpp @@ -0,0 +1,80 @@ +// +// datagram_protocol.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP +#define BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace local { + +/// Encapsulates the flags needed for datagram-oriented UNIX sockets. +/** + * The boost::asio::local::datagram_protocol class contains flags necessary for + * datagram-oriented UNIX domain sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol. + */ +class datagram_protocol +{ +public: + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_DGRAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return 0; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return AF_UNIX; + } + + /// The type of a UNIX domain endpoint. + typedef basic_endpoint endpoint; + + /// The UNIX domain socket type. + typedef basic_datagram_socket socket; +}; + +} // namespace local +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP diff --git a/include/boost/asio/local/stream_protocol.hpp b/include/boost/asio/local/stream_protocol.hpp new file mode 100644 index 00000000..8839661a --- /dev/null +++ b/include/boost/asio/local/stream_protocol.hpp @@ -0,0 +1,88 @@ +// +// stream_protocol.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP +#define BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace local { + +/// Encapsulates the flags needed for stream-oriented UNIX sockets. +/** + * The boost::asio::local::stream_protocol class contains flags necessary for + * stream-oriented UNIX domain sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol. + */ +class stream_protocol +{ +public: + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_STREAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return 0; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return AF_UNIX; + } + + /// The type of a UNIX domain endpoint. + typedef basic_endpoint endpoint; + + /// The UNIX domain socket type. + typedef basic_stream_socket socket; + + /// The UNIX domain acceptor type. + typedef basic_socket_acceptor acceptor; + + /// The UNIX domain iostream type. + typedef basic_socket_iostream iostream; +}; + +} // namespace local +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP diff --git a/include/boost/asio/posix/basic_descriptor.hpp b/include/boost/asio/posix/basic_descriptor.hpp new file mode 100644 index 00000000..74fc2ed6 --- /dev/null +++ b/include/boost/asio/posix/basic_descriptor.hpp @@ -0,0 +1,282 @@ +// +// basic_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP +#define BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace posix { + +/// Provides POSIX descriptor functionality. +/** + * The posix::basic_descriptor class template provides the ability to wrap a + * POSIX descriptor. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_descriptor + : public basic_io_object, + public descriptor_base +{ +public: + /// The native representation of a descriptor. + typedef typename DescriptorService::native_type native_type; + + /// A basic_descriptor is always the lowest layer. + typedef basic_descriptor lowest_layer_type; + + /// Construct a basic_descriptor without opening it. + /** + * This constructor creates a descriptor without opening it. + * + * @param io_service The io_service object that the descriptor will use to + * dispatch handlers for any asynchronous operations performed on the + * descriptor. + */ + explicit basic_descriptor(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct a basic_descriptor on an existing native descriptor. + /** + * This constructor creates a descriptor object to hold an existing native + * descriptor. + * + * @param io_service The io_service object that the descriptor will use to + * dispatch handlers for any asynchronous operations performed on the + * descriptor. + * + * @param native_descriptor A native descriptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_descriptor(boost::asio::io_service& io_service, + const native_type& native_descriptor) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_descriptor, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_descriptor cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Assign an existing native descriptor to the descriptor. + /* + * This function opens the descriptor to hold an existing native descriptor. + * + * @param native_descriptor A native descriptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_type& native_descriptor) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_descriptor, ec); + boost::asio::detail::throw_error(ec); + } + + /// Assign an existing native descriptor to the descriptor. + /* + * This function opens the descriptor to hold an existing native descriptor. + * + * @param native_descriptor A native descriptor. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const native_type& native_descriptor, + boost::system::error_code& ec) + { + return this->service.assign(this->implementation, native_descriptor, ec); + } + + /// Determine whether the descriptor is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the descriptor. + /** + * This function is used to close the descriptor. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->service.close(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Close the descriptor. + /** + * This function is used to close the descriptor. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native descriptor representation. + /** + * This function may be used to obtain the underlying representation of the + * descriptor. This is intended to allow access to native descriptor + * functionality that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the descriptor. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the descriptor. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Perform an IO control command on the descriptor. + /** + * This function is used to execute an IO control command on the descriptor. + * + * @param command The IO control command to be performed on the descriptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * boost::asio::posix::descriptor_base::bytes_readable @n + * boost::asio::posix::descriptor_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::posix::stream_descriptor descriptor(io_service); + * ... + * boost::asio::posix::stream_descriptor::bytes_readable command; + * descriptor.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + void io_control(IoControlCommand& command) + { + boost::system::error_code ec; + this->service.io_control(this->implementation, command, ec); + boost::asio::detail::throw_error(ec); + } + + /// Perform an IO control command on the descriptor. + /** + * This function is used to execute an IO control command on the descriptor. + * + * @param command The IO control command to be performed on the descriptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * boost::asio::posix::descriptor_base::bytes_readable @n + * boost::asio::posix::descriptor_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::posix::stream_descriptor descriptor(io_service); + * ... + * boost::asio::posix::stream_descriptor::bytes_readable command; + * boost::system::error_code ec; + * descriptor.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + boost::system::error_code io_control(IoControlCommand& command, + boost::system::error_code& ec) + { + return this->service.io_control(this->implementation, command, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_descriptor() + { + } +}; + +} // namespace posix +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP diff --git a/include/boost/asio/posix/basic_stream_descriptor.hpp b/include/boost/asio/posix/basic_stream_descriptor.hpp new file mode 100644 index 00000000..6559a688 --- /dev/null +++ b/include/boost/asio/posix/basic_stream_descriptor.hpp @@ -0,0 +1,306 @@ +// +// basic_stream_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP +#define BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace posix { + +/// Provides stream-oriented descriptor functionality. +/** + * The posix::basic_stream_descriptor class template provides asynchronous and + * blocking stream-oriented descriptor functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class basic_stream_descriptor + : public basic_descriptor +{ +public: + /// The native representation of a descriptor. + typedef typename StreamDescriptorService::native_type native_type; + + /// Construct a basic_stream_descriptor without opening it. + /** + * This constructor creates a stream descriptor without opening it. The + * descriptor needs to be opened and then connected or accepted before data + * can be sent or received on it. + * + * @param io_service The io_service object that the stream descriptor will + * use to dispatch handlers for any asynchronous operations performed on the + * descriptor. + */ + explicit basic_stream_descriptor(boost::asio::io_service& io_service) + : basic_descriptor(io_service) + { + } + + /// Construct a basic_stream_descriptor on an existing native descriptor. + /** + * This constructor creates a stream descriptor object to hold an existing + * native descriptor. + * + * @param io_service The io_service object that the stream descriptor will + * use to dispatch handlers for any asynchronous operations performed on the + * descriptor. + * + * @param native_descriptor The new underlying descriptor implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_descriptor(boost::asio::io_service& io_service, + const native_type& native_descriptor) + : basic_descriptor(io_service, native_descriptor) + { + } + + /// Write some data to the descriptor. + /** + * This function is used to write data to the stream descriptor. The function + * call will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the descriptor. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the descriptor. + /** + * This function is used to write data to the stream descriptor. The function + * call will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the descriptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream + * descriptor. The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the descriptor. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the descriptor. + /** + * This function is used to read data from the stream descriptor. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the descriptor. + /** + * This function is used to read data from the stream descriptor. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream + * descriptor. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace posix +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP diff --git a/include/boost/asio/posix/descriptor_base.hpp b/include/boost/asio/posix/descriptor_base.hpp new file mode 100644 index 00000000..19a57276 --- /dev/null +++ b/include/boost/asio/posix/descriptor_base.hpp @@ -0,0 +1,95 @@ +// +// descriptor_base.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP +#define BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace posix { + +/// The descriptor_base class is used as a base for the basic_stream_descriptor +/// class template so that we have a common place to define the associated +/// IO control commands. +class descriptor_base +{ +public: + /// IO control command to set the blocking mode of the descriptor. + /** + * Implements the FIONBIO IO control command. + * + * @par Example + * @code + * boost::asio::posix::stream_descriptor descriptor(io_service); + * ... + * boost::asio::descriptor_base::non_blocking_io command(true); + * descriptor.io_control(command); + * @endcode + * + * @par Concepts: + * IoControlCommand. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined non_blocking_io; +#else + typedef boost::asio::detail::io_control::non_blocking_io non_blocking_io; +#endif + + /// IO control command to get the amount of data that can be read without + /// blocking. + /** + * Implements the FIONREAD IO control command. + * + * @par Example + * @code + * boost::asio::posix::stream_descriptor descriptor(io_service); + * ... + * boost::asio::descriptor_base::bytes_readable command(true); + * descriptor.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + * + * @par Concepts: + * IoControlCommand. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined bytes_readable; +#else + typedef boost::asio::detail::io_control::bytes_readable bytes_readable; +#endif + +protected: + /// Protected destructor to prevent deletion through this type. + ~descriptor_base() + { + } +}; + +} // namespace posix +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP diff --git a/include/boost/asio/posix/stream_descriptor.hpp b/include/boost/asio/posix/stream_descriptor.hpp new file mode 100644 index 00000000..ff728e2e --- /dev/null +++ b/include/boost/asio/posix/stream_descriptor.hpp @@ -0,0 +1,41 @@ +// +// stream_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP +#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace posix { + +/// Typedef for the typical usage of a stream-oriented descriptor. +typedef basic_stream_descriptor<> stream_descriptor; + +} // namespace posix +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP diff --git a/include/boost/asio/posix/stream_descriptor_service.hpp b/include/boost/asio/posix/stream_descriptor_service.hpp new file mode 100644 index 00000000..0b6d55f4 --- /dev/null +++ b/include/boost/asio/posix/stream_descriptor_service.hpp @@ -0,0 +1,202 @@ +// +// stream_descriptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP +#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) +# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1 +# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) + +#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace posix { + +/// Default service implementation for a stream descriptor. +class stream_descriptor_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_descriptor_service< + detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_descriptor_service< + detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_descriptor_service< + detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_descriptor_service< + detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a stream descriptor implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native descriptor type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new stream descriptor service for the specified io_service. + explicit stream_descriptor_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined descriptorr objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new stream descriptor implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a stream descriptor implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native descriptor to a stream descriptor. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_descriptor, boost::system::error_code& ec) + { + return service_impl_.assign(impl, native_descriptor, ec); + } + + /// Determine whether the descriptor is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a stream descriptor implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native descriptor implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the descriptor. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Perform an IO control command on the descriptor. + template + boost::system::error_code io_control(implementation_type& impl, + IoControlCommand& command, boost::system::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler descriptorr) + { + service_impl_.async_write_some(impl, buffers, descriptorr); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler descriptorr) + { + service_impl_.async_read_some(impl, buffers, descriptorr); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace posix +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP diff --git a/include/boost/asio/raw_socket_service.hpp b/include/boost/asio/raw_socket_service.hpp new file mode 100644 index 00000000..ec7cc2ae --- /dev/null +++ b/include/boost/asio/raw_socket_service.hpp @@ -0,0 +1,325 @@ +// +// raw_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_RAW_SOCKET_SERVICE_HPP +#define BOOST_ASIO_RAW_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Default service implementation for a raw socket. +template +class raw_socket_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_socket_service< + Protocol, detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_socket_service< + Protocol, detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_socket_service< + Protocol, detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_socket_service< + Protocol, detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a raw socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// The native socket type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef typename service_impl_type::native_type native_type; +#endif + + /// Construct a new raw socket service for the specified io_service. + explicit raw_socket_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + raw_socket_service >(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new raw socket implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a raw socket implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + // Open a new raw socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (protocol.type() == SOCK_RAW) + service_impl_.open(impl, protocol, ec); + else + ec = boost::asio::error::invalid_argument; + return ec; + } + + /// Assign an existing native socket to a raw socket. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_type& native_socket, + boost::system::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a raw socket implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native socket implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the socket. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.at_mark(impl, ec); + } + + /// Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.available(impl, ec); + } + + // Bind the raw socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Connect the raw socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + return service_impl_.connect(impl, peer_endpoint, ec); + } + + /// Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, ConnectHandler handler) + { + service_impl_.async_connect(impl, peer_endpoint, handler); + } + + /// Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, boost::system::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, boost::system::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template + boost::system::error_code io_control(implementation_type& impl, + IoControlCommand& command, boost::system::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.remote_endpoint(impl, ec); + } + + /// Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + return service_impl_.shutdown(impl, what, ec); + } + + /// Send the given data to the peer. + template + std::size_t send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send(impl, buffers, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send(impl, buffers, flags, handler); + } + + /// Send raw data to the specified endpoint. + template + std::size_t send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send_to(impl, buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send_to(impl, buffers, destination, flags, handler); + } + + /// Receive some data from the peer. + template + std::size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive(impl, buffers, flags, ec); + } + + /// Start an asynchronous receive. + template + void async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive(impl, buffers, flags, handler); + } + + /// Receive raw data with the endpoint of the sender. + template + std::size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, + ec); + } + + /// Start an asynchronous receive that will get the endpoint of the sender. + template + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags, + handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_RAW_SOCKET_SERVICE_HPP diff --git a/include/boost/asio/read_at.hpp b/include/boost/asio/read_at.hpp new file mode 100644 index 00000000..8e096d7b --- /dev/null +++ b/include/boost/asio/read_at.hpp @@ -0,0 +1,564 @@ +// +// read_at.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_READ_AT_HPP +#define BOOST_ASIO_READ_AT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +/** + * @defgroup read_at boost::asio::read_at + */ +/*@{*/ + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::read_at(d, 42, boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::read_at( + * d, 42, buffers, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::read_at(d, 42, boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest read_some_at + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code boost::asio::read_at( + * d, 42, b, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/*@}*/ +/** + * @defgroup async_read_at boost::asio::async_read_at + */ +/*@{*/ + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::async_read_at(d, 42, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::async_read_at( + * d, 42, buffers, + * boost::asio::transfer_all(), + * handler); @endcode + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's async_read_some_at function are + * required. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::async_read_at(d, 42, + * boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b A basic_streambuf object into which the data will be read. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note This overload is equivalent to calling: + * @code boost::asio::async_read_at( + * d, 42, b, + * boost::asio::transfer_all(), + * handler); @endcode + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset, + basic_streambuf& b, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b A basic_streambuf object into which the data will be read. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's async_read_some_at function are + * required. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition, ReadHandler handler); + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#include + +#endif // BOOST_ASIO_READ_AT_HPP diff --git a/include/boost/asio/read_until.hpp b/include/boost/asio/read_until.hpp index 9ef877e5..e282be85 100644 --- a/include/boost/asio/read_until.hpp +++ b/include/boost/asio/read_until.hpp @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include #include #include @@ -30,6 +33,36 @@ namespace boost { namespace asio { +namespace detail +{ + template + struct has_result_type + { + struct big { char a[100]; }; + template static big helper(U, ...); + template static char helper(U, typename U::result_type* = 0); + static const T& ref(); + enum { value = (sizeof((helper)((ref)())) == 1) }; + }; +} // namespace detail + +/// Type trait used to determine whether a type can be used as a match condition +/// function with read_until and async_read_until. +template +struct is_match_condition +{ +#if defined(GENERATING_DOCUMENTATION) + /// The value member is true if the type may be used as a match condition. + static const bool value; +#else + enum + { + value = boost::is_function::type>::value + || detail::has_result_type::value + }; +#endif +}; + /** * @defgroup read_until boost::asio::read_until */ @@ -243,6 +276,158 @@ std::size_t read_until(SyncReadStream& s, boost::asio::basic_streambuf& b, const boost::regex& expr, boost::system::error_code& ec); +/// Read data into a streambuf until a function object indicates a match. +/** + * This function is used to read data into the specified streambuf until a + * user-defined match condition function object, when applied to the data + * contained in the streambuf, indicates a successful match. The call will + * block until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the match condition function object already indicates + * a match, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @returns The number of bytes in the streambuf's get area that have been fully + * consumed by the match function. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + * + * @par Examples + * To read data into a streambuf until whitespace is encountered: + * @code typedef boost::asio::buffers_iterator< + * boost::asio::streambuf::const_buffers_type> iterator; + * + * std::pair + * match_whitespace(iterator begin, iterator end) + * { + * iterator i = begin; + * while (i != end) + * if (std::isspace(*i++)) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * ... + * boost::asio::streambuf b; + * boost::asio::read_until(s, b, match_whitespace); + * @endcode + * + * To read data into a streambuf until a matching character is found: + * @code class match_char + * { + * public: + * explicit match_char(char c) : c_(c) {} + * + * template + * std::pair operator()( + * Iterator begin, Iterator end) const + * { + * Iterator i = begin; + * while (i != end) + * if (c_ == *i++) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * + * private: + * char c_; + * }; + * + * namespace asio { + * template <> struct is_match_condition + * : public boost::true_type {}; + * } // namespace asio + * ... + * boost::asio::streambuf b; + * boost::asio::read_until(s, b, match_char('a')); + * @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, MatchCondition match_condition, + typename boost::enable_if >::type* = 0); + +/// Read data into a streambuf until a function object indicates a match. +/** + * This function is used to read data into the specified streambuf until a + * user-defined match condition function object, when applied to the data + * contained in the streambuf, indicates a successful match. The call will + * block until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the match condition function object already indicates + * a match, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area that have been fully + * consumed by the match function. Returns 0 if an error occurred. + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, + MatchCondition match_condition, boost::system::error_code& ec, + typename boost::enable_if >::type* = 0); + /*@}*/ /** * @defgroup async_read_until boost::asio::async_read_until @@ -442,6 +627,127 @@ void async_read_until(AsyncReadStream& s, boost::asio::basic_streambuf& b, const boost::regex& expr, ReadHandler handler); +/// Start an asynchronous operation to read data into a streambuf until a +/// function object indicates a match. +/** + * This function is used to asynchronously read data into the specified + * streambuf until a user-defined match condition function object, when applied + * to the data contained in the streambuf, indicates a successful match. The + * function call always returns immediately. The asynchronous operation will + * continue until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the match condition function object already + * indicates a match, the operation completes immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area that have been fully consumed by the + * // match function. O if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + * + * @par Examples + * To asynchronously read data into a streambuf until whitespace is encountered: + * @code typedef boost::asio::buffers_iterator< + * boost::asio::streambuf::const_buffers_type> iterator; + * + * std::pair + * match_whitespace(iterator begin, iterator end) + * { + * iterator i = begin; + * while (i != end) + * if (std::isspace(*i++)) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * ... + * void handler(const boost::system::error_code& e, std::size_t size); + * ... + * boost::asio::streambuf b; + * boost::asio::async_read_until(s, b, match_whitespace, handler); + * @endcode + * + * To asynchronously read data into a streambuf until a matching character is + * found: + * @code class match_char + * { + * public: + * explicit match_char(char c) : c_(c) {} + * + * template + * std::pair operator()( + * Iterator begin, Iterator end) const + * { + * Iterator i = begin; + * while (i != end) + * if (c_ == *i++) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * + * private: + * char c_; + * }; + * + * namespace asio { + * template <> struct is_match_condition + * : public boost::true_type {}; + * } // namespace asio + * ... + * void handler(const boost::system::error_code& e, std::size_t size); + * ... + * boost::asio::streambuf b; + * boost::asio::async_read_until(s, b, match_char('a'), handler); + * @endcode + */ +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, + MatchCondition match_condition, ReadHandler handler, + typename boost::enable_if >::type* = 0); + /*@}*/ } // namespace asio diff --git a/include/boost/asio/serial_port.hpp b/include/boost/asio/serial_port.hpp new file mode 100644 index 00000000..0be39e05 --- /dev/null +++ b/include/boost/asio/serial_port.hpp @@ -0,0 +1,40 @@ +// +// serial_port.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SERIAL_PORT_HPP +#define BOOST_ASIO_SERIAL_PORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { + +/// Typedef for the typical usage of a serial port. +typedef basic_serial_port<> serial_port; + +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_SERIAL_PORT_HPP diff --git a/include/boost/asio/serial_port_base.hpp b/include/boost/asio/serial_port_base.hpp new file mode 100644 index 00000000..0379c378 --- /dev/null +++ b/include/boost/asio/serial_port_base.hpp @@ -0,0 +1,159 @@ +// +// serial_port_base.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SERIAL_PORT_BASE_HPP +#define BOOST_ASIO_SERIAL_PORT_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# include +#endif +#include +#include + +#include + +#if defined(GENERATING_DOCUMENTATION) +# define BOOST_ASIO_OPTION_STORAGE implementation_defined +#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# define BOOST_ASIO_OPTION_STORAGE DCB +#else +# define BOOST_ASIO_OPTION_STORAGE termios +#endif + +namespace boost { +namespace asio { + +/// The serial_port_base class is used as a base for the basic_serial_port class +/// template so that we have a common place to define the serial port options. +class serial_port_base +{ +public: + /// Serial port option to permit changing the baud rate. + /** + * Implements changing the baud rate for a given serial port. + */ + class baud_rate + { + public: + explicit baud_rate(unsigned int rate = 0); + unsigned int value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + unsigned int value_; + }; + + /// Serial port option to permit changing the flow control. + /** + * Implements changing the flow control for a given serial port. + */ + class flow_control + { + public: + enum type { none, software, hardware }; + explicit flow_control(type t = none); + type value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the parity. + /** + * Implements changing the parity for a given serial port. + */ + class parity + { + public: + enum type { none, odd, even }; + explicit parity(type t = none); + type value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the number of stop bits. + /** + * Implements changing the number of stop bits for a given serial port. + */ + class stop_bits + { + public: + enum type { one, onepointfive, two }; + explicit stop_bits(type t = one); + type value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the character size. + /** + * Implements changing the character size for a given serial port. + */ + class character_size + { + public: + explicit character_size(unsigned int t = 8); + unsigned int value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + unsigned int value_; + }; + +protected: + /// Protected destructor to prevent deletion through this type. + ~serial_port_base() + { + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +private: + // Workaround to enable the empty base optimisation with Borland C++. + char dummy_; +#endif +}; + +} // namespace asio +} // namespace boost + +#include + +#undef BOOST_ASIO_OPTION_STORAGE + +#include + +#endif // BOOST_ASIO_SERIAL_PORT_BASE_HPP diff --git a/include/boost/asio/serial_port_service.hpp b/include/boost/asio/serial_port_service.hpp new file mode 100644 index 00000000..23d81922 --- /dev/null +++ b/include/boost/asio/serial_port_service.hpp @@ -0,0 +1,224 @@ +// +// serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SERIAL_PORT_SERVICE_HPP +#define BOOST_ASIO_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_SERIAL_PORT) +# if defined(BOOST_ASIO_HAS_IOCP) \ + || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_SERIAL_PORT 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +#endif // !defined(BOOST_ASIO_DISABLE_STREAM_HANDLE) + +#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { + +/// Default service implementation for a serial port. +class serial_port_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_serial_port_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_serial_port_service< + detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_serial_port_service< + detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_serial_port_service< + detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_serial_port_service< + detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a serial port implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new serial port service for the specified io_service. + explicit serial_port_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new serial port implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a serial port implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Open a serial port. + boost::system::error_code open(implementation_type& impl, + const std::string& device, boost::system::error_code& ec) + { + return service_impl_.open(impl, device, ec); + } + + /// Assign an existing native handle to a serial port. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a serial port implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Set a serial port option. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, boost::system::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a serial port option. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, boost::system::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Send a break sequence to the serial port. + boost::system::error_code send_break(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.send_break(impl, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some(impl, buffers, handler); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some(impl, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_SERIAL_PORT_SERVICE_HPP diff --git a/include/boost/asio/ssl/detail/openssl_operation.hpp b/include/boost/asio/ssl/detail/openssl_operation.hpp index b4ce6fb0..42699a5c 100644 --- a/include/boost/asio/ssl/detail/openssl_operation.hpp +++ b/include/boost/asio/ssl/detail/openssl_operation.hpp @@ -169,14 +169,11 @@ public: ((::SSL_get_shutdown( session_ ) & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN); - if (is_shut_down_sent && is_shut_down_received && is_operation_done) + if (is_shut_down_sent && is_shut_down_received && is_operation_done && !is_write_needed) // SSL connection is shut down cleanly return handler_(boost::system::error_code(), 1); - if (is_shut_down_received && !is_write_needed) - return handler_(boost::asio::error::eof, 0); - - if (is_shut_down_received) + if (is_shut_down_received && !is_operation_done) // Shutdown has been requested, while we were reading or writing... // abort our action... return handler_(boost::asio::error::shut_down, 0); @@ -226,7 +223,7 @@ public: return start(); } - else if (is_read_needed) + else if (is_read_needed || (is_shut_down_sent && !is_shut_down_received)) { return read_(); } diff --git a/include/boost/asio/version.hpp b/include/boost/asio/version.hpp index f0fe4bb7..a02a3d0e 100644 --- a/include/boost/asio/version.hpp +++ b/include/boost/asio/version.hpp @@ -18,6 +18,6 @@ // BOOST_ASIO_VERSION % 100 is the sub-minor version // BOOST_ASIO_VERSION / 100 % 1000 is the minor version // BOOST_ASIO_VERSION / 100000 is the major version -#define BOOST_ASIO_VERSION 100000 // 1.0.0 +#define BOOST_ASIO_VERSION 100100 // 1.1.0 #endif // BOOST_ASIO_VERSION_HPP diff --git a/include/boost/asio/windows/basic_handle.hpp b/include/boost/asio/windows/basic_handle.hpp new file mode 100644 index 00000000..109fd5e9 --- /dev/null +++ b/include/boost/asio/windows/basic_handle.hpp @@ -0,0 +1,213 @@ +// +// basic_handle.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace windows { + +/// Provides Windows handle functionality. +/** + * The windows::basic_handle class template provides the ability to wrap a + * Windows handle. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_handle + : public basic_io_object +{ +public: + /// The native representation of a handle. + typedef typename HandleService::native_type native_type; + + /// A basic_handle is always the lowest layer. + typedef basic_handle lowest_layer_type; + + /// Construct a basic_handle without opening it. + /** + * This constructor creates a handle without opening it. + * + * @param io_service The io_service object that the handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + */ + explicit basic_handle(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct a basic_handle on an existing native handle. + /** + * This constructor creates a handle object to hold an existing native handle. + * + * @param io_service The io_service object that the handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + * + * @param native_handle A native handle. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_handle(boost::asio::io_service& io_service, + const native_type& native_handle) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_handle, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_handle cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param native_handle A native handle. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_type& native_handle) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_handle, ec); + boost::asio::detail::throw_error(ec); + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param native_handle A native handle. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const native_type& native_handle, + boost::system::error_code& ec) + { + return this->service.assign(this->implementation, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->service.close(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native handle representation. + /** + * This function may be used to obtain the underlying representation of the + * handle. This is intended to allow access to native handle functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_handle() + { + } +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP diff --git a/include/boost/asio/windows/basic_random_access_handle.hpp b/include/boost/asio/windows/basic_random_access_handle.hpp new file mode 100644 index 00000000..d6b63b18 --- /dev/null +++ b/include/boost/asio/windows/basic_random_access_handle.hpp @@ -0,0 +1,322 @@ +// +// basic_random_access_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Provides random-access handle functionality. +/** + * The windows::basic_random_access_handle class template provides asynchronous + * and blocking random-access handle functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_random_access_handle + : public basic_handle +{ +public: + /// The native representation of a handle. + typedef typename RandomAccessHandleService::native_type native_type; + + /// Construct a basic_random_access_handle without opening it. + /** + * This constructor creates a random-access handle without opening it. The + * handle needs to be opened before data can be written to or or read from it. + * + * @param io_service The io_service object that the random-access handle will + * use to dispatch handlers for any asynchronous operations performed on the + * handle. + */ + explicit basic_random_access_handle(boost::asio::io_service& io_service) + : basic_handle(io_service) + { + } + + /// Construct a basic_random_access_handle on an existing native handle. + /** + * This constructor creates a random-access handle object to hold an existing + * native handle. + * + * @param io_service The io_service object that the random-access handle will + * use to dispatch handlers for any asynchronous operations performed on the + * handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_random_access_handle(boost::asio::io_service& io_service, + const native_type& native_handle) + : basic_handle(io_service, native_handle) + { + } + + /// Write some data to the handle at the specified offset. + /** + * This function is used to write data to the random-access handle. The + * function call will block until one or more bytes of the data has been + * written successfully, or until an error occurs. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some_at operation may not write all of the data. Consider + * using the @ref write_at function if you need to ensure that all data is + * written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.write_some_at(42, boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.write_some_at( + this->implementation, offset, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the handle at the specified offset. + /** + * This function is used to write data to the random-access handle. The + * function call will block until one or more bytes of the data has been + * written successfully, or until an error occurs. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write_at function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return this->service.write_some_at( + this->implementation, offset, buffers, ec); + } + + /// Start an asynchronous write at the specified offset. + /** + * This function is used to asynchronously write data to the random-access + * handle. The function call always returns immediately. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write_at function if you need to ensure that + * all data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_write_some_at(42, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler) + { + this->service.async_write_some_at( + this->implementation, offset, buffers, handler); + } + + /// Read some data from the handle at the specified offset. + /** + * This function is used to read data from the random-access handle. The + * function call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read_at function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.read_some_at(42, boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.read_some_at( + this->implementation, offset, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the handle at the specified offset. + /** + * This function is used to read data from the random-access handle. The + * function call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read_at function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return this->service.read_some_at( + this->implementation, offset, buffers, ec); + } + + /// Start an asynchronous read at the specified offset. + /** + * This function is used to asynchronously read data from the random-access + * handle. The function call always returns immediately. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read_at function if you need to ensure that + * the requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_read_some_at(42, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler) + { + this->service.async_read_some_at( + this->implementation, offset, buffers, handler); + } +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP diff --git a/include/boost/asio/windows/basic_stream_handle.hpp b/include/boost/asio/windows/basic_stream_handle.hpp new file mode 100644 index 00000000..aaa8448b --- /dev/null +++ b/include/boost/asio/windows/basic_stream_handle.hpp @@ -0,0 +1,304 @@ +// +// basic_stream_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Provides stream-oriented handle functionality. +/** + * The windows::basic_stream_handle class template provides asynchronous and + * blocking stream-oriented handle functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class basic_stream_handle + : public basic_handle +{ +public: + /// The native representation of a handle. + typedef typename StreamHandleService::native_type native_type; + + /// Construct a basic_stream_handle without opening it. + /** + * This constructor creates a stream handle without opening it. The handle + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param io_service The io_service object that the stream handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + */ + explicit basic_stream_handle(boost::asio::io_service& io_service) + : basic_handle(io_service) + { + } + + /// Construct a basic_stream_handle on an existing native handle. + /** + * This constructor creates a stream handle object to hold an existing native + * handle. + * + * @param io_service The io_service object that the stream handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_handle(boost::asio::io_service& io_service, + const native_type& native_handle) + : basic_handle(io_service, native_handle) + { + } + + /// Write some data to the handle. + /** + * This function is used to write data to the stream handle. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the handle. + /** + * This function is used to write data to the stream handle. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream handle. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the handle. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the handle. + /** + * This function is used to read data from the stream handle. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the handle. + /** + * This function is used to read data from the stream handle. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream handle. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP diff --git a/include/boost/asio/windows/random_access_handle.hpp b/include/boost/asio/windows/random_access_handle.hpp new file mode 100644 index 00000000..38e79e90 --- /dev/null +++ b/include/boost/asio/windows/random_access_handle.hpp @@ -0,0 +1,41 @@ +// +// random_access_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Typedef for the typical usage of a random-access handle. +typedef basic_random_access_handle<> random_access_handle; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP diff --git a/include/boost/asio/windows/random_access_handle_service.hpp b/include/boost/asio/windows/random_access_handle_service.hpp new file mode 100644 index 00000000..3b112233 --- /dev/null +++ b/include/boost/asio/windows/random_access_handle_service.hpp @@ -0,0 +1,181 @@ +// +// random_access_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP +#define BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +# if defined(BOOST_ASIO_HAS_IOCP) +# define BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +#endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) + +#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Default service implementation for a random-access handle. +class random_access_handle_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. + typedef detail::win_iocp_handle_service service_impl_type; + +public: + /// The type of a random-access handle implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new random-access handle service for the specified io_service. + explicit random_access_handle_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + random_access_handle_service>(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new random-access handle implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a random-access handle implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native handle to a random-access handle. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a random-access handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Write the given data at the specified offset. + template + std::size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some_at(impl, offset, buffers, ec); + } + + /// Start an asynchronous write at the specified offset. + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some_at(impl, offset, buffers, handler); + } + + /// Read some data from the specified offset. + template + std::size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some_at(impl, offset, buffers, ec); + } + + /// Start an asynchronous read at the specified offset. + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some_at(impl, offset, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP diff --git a/include/boost/asio/windows/stream_handle.hpp b/include/boost/asio/windows/stream_handle.hpp new file mode 100644 index 00000000..b247197e --- /dev/null +++ b/include/boost/asio/windows/stream_handle.hpp @@ -0,0 +1,41 @@ +// +// stream_handle.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Typedef for the typical usage of a stream-oriented handle. +typedef basic_stream_handle<> stream_handle; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP diff --git a/include/boost/asio/windows/stream_handle_service.hpp b/include/boost/asio/windows/stream_handle_service.hpp new file mode 100644 index 00000000..29cdc95b --- /dev/null +++ b/include/boost/asio/windows/stream_handle_service.hpp @@ -0,0 +1,179 @@ +// +// stream_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP +#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE) +# if defined(BOOST_ASIO_HAS_IOCP) +# define BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +#endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE) + +#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Default service implementation for a stream handle. +class stream_handle_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. + typedef detail::win_iocp_handle_service service_impl_type; + +public: + /// The type of a stream handle implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new stream handle service for the specified io_service. + explicit stream_handle_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new stream handle implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a stream handle implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native handle to a stream handle. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a stream handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some(impl, buffers, handler); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some(impl, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP diff --git a/include/boost/asio/write.hpp b/include/boost/asio/write.hpp index 7ef2103f..9cb100b1 100644 --- a/include/boost/asio/write.hpp +++ b/include/boost/asio/write.hpp @@ -167,7 +167,7 @@ template & b, */ /*@{*/ -/// Start an asynchronous operation to write of all of the supplied data to a +/// Start an asynchronous operation to write all of the supplied data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of @@ -406,7 +406,7 @@ template = 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +/** + * @defgroup write_at boost::asio::write_at + */ +/*@{*/ + +/// Write all of the supplied data at the specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::write_at(d, 42, boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::write_at( + * d, offset, buffers, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::write_at(d, 42, boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/// Write all of the supplied data at the specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code boost::asio::write_at( + * d, 42, b, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, basic_streambuf& b); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition, + boost::system::error_code& ec); + +/*@}*/ +/** + * @defgroup async_write_at boost::asio::async_write_at + */ +/*@{*/ + +/// Start an asynchronous operation to write all of the supplied data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::async_write_at(d, 42, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler); + +/// Start an asynchronous operation to write a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's async_write_some_at function are + * required. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::async_write_at(d, 42, + * boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler handler); + +/// Start an asynchronous operation to write all of the supplied data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b A basic_streambuf object from which data will be written. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, WriteHandler handler); + +/// Start an asynchronous operation to write a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b A basic_streambuf object from which data will be written. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest async_write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's async_write_some_at function are + * required. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition, + WriteHandler handler); + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#include + +#endif // BOOST_ASIO_WRITE_AT_HPP diff --git a/test/Jamfile b/test/Jamfile index bae3b377..1c11d408 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -45,6 +45,7 @@ test-suite "asio" [ run buffered_read_stream.cpp