1//
2// posix/basic_stream_descriptor.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
12#define BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19
20#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
21 || defined(GENERATING_DOCUMENTATION)
22
23#include <cstddef>
24#include <boost/asio/detail/handler_type_requirements.hpp>
25#include <boost/asio/detail/throw_error.hpp>
26#include <boost/asio/error.hpp>
27#include <boost/asio/posix/basic_descriptor.hpp>
28#include <boost/asio/posix/stream_descriptor_service.hpp>
29
30#include <boost/asio/detail/push_options.hpp>
31
32namespace boost {
33namespace asio {
34namespace posix {
35
36/// Provides stream-oriented descriptor functionality.
37/**
38 * The posix::basic_stream_descriptor class template provides asynchronous and
39 * blocking stream-oriented descriptor functionality.
40 *
41 * @par Thread Safety
42 * @e Distinct @e objects: Safe.@n
43 * @e Shared @e objects: Unsafe.
44 *
45 * @par Concepts:
46 * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
47 */
48template <typename StreamDescriptorService = stream_descriptor_service>
49class basic_stream_descriptor
50 : public basic_descriptor<StreamDescriptorService>
51{
52public:
53 /// (Deprecated: Use native_handle_type.) The native representation of a
54 /// descriptor.
55 typedef typename StreamDescriptorService::native_handle_type native_type;
56
57 /// The native representation of a descriptor.
58 typedef typename StreamDescriptorService::native_handle_type
59 native_handle_type;
60
61 /// Construct a basic_stream_descriptor without opening it.
62 /**
63 * This constructor creates a stream descriptor without opening it. The
64 * descriptor needs to be opened and then connected or accepted before data
65 * can be sent or received on it.
66 *
67 * @param io_service The io_service object that the stream descriptor will
68 * use to dispatch handlers for any asynchronous operations performed on the
69 * descriptor.
70 */
71 explicit basic_stream_descriptor(boost::asio::io_service& io_service)
72 : basic_descriptor<StreamDescriptorService>(io_service)
73 {
74 }
75
76 /// Construct a basic_stream_descriptor on an existing native descriptor.
77 /**
78 * This constructor creates a stream descriptor object to hold an existing
79 * native descriptor.
80 *
81 * @param io_service The io_service object that the stream descriptor will
82 * use to dispatch handlers for any asynchronous operations performed on the
83 * descriptor.
84 *
85 * @param native_descriptor The new underlying descriptor implementation.
86 *
87 * @throws boost::system::system_error Thrown on failure.
88 */
89 basic_stream_descriptor(boost::asio::io_service& io_service,
90 const native_handle_type& native_descriptor)
91 : basic_descriptor<StreamDescriptorService>(io_service, native_descriptor)
92 {
93 }
94
95#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
96 /// Move-construct a basic_stream_descriptor from another.
97 /**
98 * This constructor moves a stream descriptor from one object to another.
99 *
100 * @param other The other basic_stream_descriptor object from which the move
101 * will occur.
102 *
103 * @note Following the move, the moved-from object is in the same state as if
104 * constructed using the @c basic_stream_descriptor(io_service&) constructor.
105 */
106 basic_stream_descriptor(basic_stream_descriptor&& other)
107 : basic_descriptor<StreamDescriptorService>(
108 BOOST_ASIO_MOVE_CAST(basic_stream_descriptor)(other))
109 {
110 }
111
112 /// Move-assign a basic_stream_descriptor from another.
113 /**
114 * This assignment operator moves a stream descriptor from one object to
115 * another.
116 *
117 * @param other The other basic_stream_descriptor object from which the move
118 * will occur.
119 *
120 * @note Following the move, the moved-from object is in the same state as if
121 * constructed using the @c basic_stream_descriptor(io_service&) constructor.
122 */
123 basic_stream_descriptor& operator=(basic_stream_descriptor&& other)
124 {
125 basic_descriptor<StreamDescriptorService>::operator=(
126 BOOST_ASIO_MOVE_CAST(basic_stream_descriptor)(other));
127 return *this;
128 }
129#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
130
131 /// Write some data to the descriptor.
132 /**
133 * This function is used to write data to the stream descriptor. The function
134 * call will block until one or more bytes of the data has been written
135 * successfully, or until an error occurs.
136 *
137 * @param buffers One or more data buffers to be written to the descriptor.
138 *
139 * @returns The number of bytes written.
140 *
141 * @throws boost::system::system_error Thrown on failure. An error code of
142 * boost::asio::error::eof indicates that the connection was closed by the
143 * peer.
144 *
145 * @note The write_some operation may not transmit all of the data to the
146 * peer. Consider using the @ref write function if you need to ensure that
147 * all data is written before the blocking operation completes.
148 *
149 * @par Example
150 * To write a single data buffer use the @ref buffer function as follows:
151 * @code
152 * descriptor.write_some(boost::asio::buffer(data, size));
153 * @endcode
154 * See the @ref buffer documentation for information on writing multiple
155 * buffers in one go, and how to use it with arrays, boost::array or
156 * std::vector.
157 */
158 template <typename ConstBufferSequence>
159 std::size_t write_some(const ConstBufferSequence& buffers)
160 {
161 boost::system::error_code ec;
162 std::size_t s = this->get_service().write_some(
163 this->get_implementation(), buffers, ec);
164 boost::asio::detail::throw_error(ec, "write_some");
165 return s;
166 }
167
168 /// Write some data to the descriptor.
169 /**
170 * This function is used to write data to the stream descriptor. The function
171 * call will block until one or more bytes of the data has been written
172 * successfully, or until an error occurs.
173 *
174 * @param buffers One or more data buffers to be written to the descriptor.
175 *
176 * @param ec Set to indicate what error occurred, if any.
177 *
178 * @returns The number of bytes written. Returns 0 if an error occurred.
179 *
180 * @note The write_some operation may not transmit all of the data to the
181 * peer. Consider using the @ref write function if you need to ensure that
182 * all data is written before the blocking operation completes.
183 */
184 template <typename ConstBufferSequence>
185 std::size_t write_some(const ConstBufferSequence& buffers,
186 boost::system::error_code& ec)
187 {
188 return this->get_service().write_some(
189 this->get_implementation(), buffers, ec);
190 }
191
192 /// Start an asynchronous write.
193 /**
194 * This function is used to asynchronously write data to the stream
195 * descriptor. The function call always returns immediately.
196 *
197 * @param buffers One or more data buffers to be written to the descriptor.
198 * Although the buffers object may be copied as necessary, ownership of the
199 * underlying memory blocks is retained by the caller, which must guarantee
200 * that they remain valid until the handler is called.
201 *
202 * @param handler The handler to be called when the write operation completes.
203 * Copies will be made of the handler as required. The function signature of
204 * the handler must be:
205 * @code void handler(
206 * const boost::system::error_code& error, // Result of operation.
207 * std::size_t bytes_transferred // Number of bytes written.
208 * ); @endcode
209 * Regardless of whether the asynchronous operation completes immediately or
210 * not, the handler will not be invoked from within this function. Invocation
211 * of the handler will be performed in a manner equivalent to using
212 * boost::asio::io_service::post().
213 *
214 * @note The write operation may not transmit all of the data to the peer.
215 * Consider using the @ref async_write function if you need to ensure that all
216 * data is written before the asynchronous operation completes.
217 *
218 * @par Example
219 * To write a single data buffer use the @ref buffer function as follows:
220 * @code
221 * descriptor.async_write_some(boost::asio::buffer(data, size), handler);
222 * @endcode
223 * See the @ref buffer documentation for information on writing multiple
224 * buffers in one go, and how to use it with arrays, boost::array or
225 * std::vector.
226 */
227 template <typename ConstBufferSequence, typename WriteHandler>
228 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
229 void (boost::system::error_code, std::size_t))
230 async_write_some(const ConstBufferSequence& buffers,
231 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
232 {
233 // If you get an error on the following line it means that your handler does
234 // not meet the documented type requirements for a WriteHandler.
235 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
236
237 return this->get_service().async_write_some(this->get_implementation(),
238 buffers, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
239 }
240
241 /// Read some data from the descriptor.
242 /**
243 * This function is used to read data from the stream descriptor. The function
244 * call will block until one or more bytes of data has been read successfully,
245 * or until an error occurs.
246 *
247 * @param buffers One or more buffers into which the data will be read.
248 *
249 * @returns The number of bytes read.
250 *
251 * @throws boost::system::system_error Thrown on failure. An error code of
252 * boost::asio::error::eof indicates that the connection was closed by the
253 * peer.
254 *
255 * @note The read_some operation may not read all of the requested number of
256 * bytes. Consider using the @ref read function if you need to ensure that
257 * the requested amount of data is read before the blocking operation
258 * completes.
259 *
260 * @par Example
261 * To read into a single data buffer use the @ref buffer function as follows:
262 * @code
263 * descriptor.read_some(boost::asio::buffer(data, size));
264 * @endcode
265 * See the @ref buffer documentation for information on reading into multiple
266 * buffers in one go, and how to use it with arrays, boost::array or
267 * std::vector.
268 */
269 template <typename MutableBufferSequence>
270 std::size_t read_some(const MutableBufferSequence& buffers)
271 {
272 boost::system::error_code ec;
273 std::size_t s = this->get_service().read_some(
274 this->get_implementation(), buffers, ec);
275 boost::asio::detail::throw_error(ec, "read_some");
276 return s;
277 }
278
279 /// Read some data from the descriptor.
280 /**
281 * This function is used to read data from the stream descriptor. The function
282 * call will block until one or more bytes of data has been read successfully,
283 * or until an error occurs.
284 *
285 * @param buffers One or more buffers into which the data will be read.
286 *
287 * @param ec Set to indicate what error occurred, if any.
288 *
289 * @returns The number of bytes read. Returns 0 if an error occurred.
290 *
291 * @note The read_some operation may not read all of the requested number of
292 * bytes. Consider using the @ref read function if you need to ensure that
293 * the requested amount of data is read before the blocking operation
294 * completes.
295 */
296 template <typename MutableBufferSequence>
297 std::size_t read_some(const MutableBufferSequence& buffers,
298 boost::system::error_code& ec)
299 {
300 return this->get_service().read_some(
301 this->get_implementation(), buffers, ec);
302 }
303
304 /// Start an asynchronous read.
305 /**
306 * This function is used to asynchronously read data from the stream
307 * descriptor. The function call always returns immediately.
308 *
309 * @param buffers One or more buffers into which the data will be read.
310 * Although the buffers object may be copied as necessary, ownership of the
311 * underlying memory blocks is retained by the caller, which must guarantee
312 * that they remain valid until the handler is called.
313 *
314 * @param handler The handler to be called when the read operation completes.
315 * Copies will be made of the handler as required. The function signature of
316 * the handler must be:
317 * @code void handler(
318 * const boost::system::error_code& error, // Result of operation.
319 * std::size_t bytes_transferred // Number of bytes read.
320 * ); @endcode
321 * Regardless of whether the asynchronous operation completes immediately or
322 * not, the handler will not be invoked from within this function. Invocation
323 * of the handler will be performed in a manner equivalent to using
324 * boost::asio::io_service::post().
325 *
326 * @note The read operation may not read all of the requested number of bytes.
327 * Consider using the @ref async_read function if you need to ensure that the
328 * requested amount of data is read before the asynchronous operation
329 * completes.
330 *
331 * @par Example
332 * To read into a single data buffer use the @ref buffer function as follows:
333 * @code
334 * descriptor.async_read_some(boost::asio::buffer(data, size), handler);
335 * @endcode
336 * See the @ref buffer documentation for information on reading into multiple
337 * buffers in one go, and how to use it with arrays, boost::array or
338 * std::vector.
339 */
340 template <typename MutableBufferSequence, typename ReadHandler>
341 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
342 void (boost::system::error_code, std::size_t))
343 async_read_some(const MutableBufferSequence& buffers,
344 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
345 {
346 // If you get an error on the following line it means that your handler does
347 // not meet the documented type requirements for a ReadHandler.
348 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
349
350 return this->get_service().async_read_some(this->get_implementation(),
351 buffers, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
352 }
353};
354
355} // namespace posix
356} // namespace asio
357} // namespace boost
358
359#include <boost/asio/detail/pop_options.hpp>
360
361#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
362 // || defined(GENERATING_DOCUMENTATION)
363
364#endif // BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
365