1//
2// posix/basic_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_DESCRIPTOR_HPP
12#define BOOST_ASIO_POSIX_BASIC_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 <boost/asio/basic_io_object.hpp>
24#include <boost/asio/detail/throw_error.hpp>
25#include <boost/asio/error.hpp>
26#include <boost/asio/posix/descriptor_base.hpp>
27
28#include <boost/asio/detail/push_options.hpp>
29
30namespace boost {
31namespace asio {
32namespace posix {
33
34/// Provides POSIX descriptor functionality.
35/**
36 * The posix::basic_descriptor class template provides the ability to wrap a
37 * POSIX descriptor.
38 *
39 * @par Thread Safety
40 * @e Distinct @e objects: Safe.@n
41 * @e Shared @e objects: Unsafe.
42 */
43template <typename DescriptorService>
44class basic_descriptor
45 : public basic_io_object<DescriptorService>,
46 public descriptor_base
47{
48public:
49 /// (Deprecated: Use native_handle_type.) The native representation of a
50 /// descriptor.
51 typedef typename DescriptorService::native_handle_type native_type;
52
53 /// The native representation of a descriptor.
54 typedef typename DescriptorService::native_handle_type native_handle_type;
55
56 /// A basic_descriptor is always the lowest layer.
57 typedef basic_descriptor<DescriptorService> lowest_layer_type;
58
59 /// Construct a basic_descriptor without opening it.
60 /**
61 * This constructor creates a descriptor without opening it.
62 *
63 * @param io_service The io_service object that the descriptor will use to
64 * dispatch handlers for any asynchronous operations performed on the
65 * descriptor.
66 */
67 explicit basic_descriptor(boost::asio::io_service& io_service)
68 : basic_io_object<DescriptorService>(io_service)
69 {
70 }
71
72 /// Construct a basic_descriptor on an existing native descriptor.
73 /**
74 * This constructor creates a descriptor object to hold an existing native
75 * descriptor.
76 *
77 * @param io_service The io_service object that the descriptor will use to
78 * dispatch handlers for any asynchronous operations performed on the
79 * descriptor.
80 *
81 * @param native_descriptor A native descriptor.
82 *
83 * @throws boost::system::system_error Thrown on failure.
84 */
85 basic_descriptor(boost::asio::io_service& io_service,
86 const native_handle_type& native_descriptor)
87 : basic_io_object<DescriptorService>(io_service)
88 {
89 boost::system::error_code ec;
90 this->get_service().assign(this->get_implementation(),
91 native_descriptor, ec);
92 boost::asio::detail::throw_error(ec, "assign");
93 }
94
95#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
96 /// Move-construct a basic_descriptor from another.
97 /**
98 * This constructor moves a descriptor from one object to another.
99 *
100 * @param other The other basic_descriptor object from which the move will
101 * occur.
102 *
103 * @note Following the move, the moved-from object is in the same state as if
104 * constructed using the @c basic_descriptor(io_service&) constructor.
105 */
106 basic_descriptor(basic_descriptor&& other)
107 : basic_io_object<DescriptorService>(
108 BOOST_ASIO_MOVE_CAST(basic_descriptor)(other))
109 {
110 }
111
112 /// Move-assign a basic_descriptor from another.
113 /**
114 * This assignment operator moves a descriptor from one object to another.
115 *
116 * @param other The other basic_descriptor object from which the move will
117 * occur.
118 *
119 * @note Following the move, the moved-from object is in the same state as if
120 * constructed using the @c basic_descriptor(io_service&) constructor.
121 */
122 basic_descriptor& operator=(basic_descriptor&& other)
123 {
124 basic_io_object<DescriptorService>::operator=(
125 BOOST_ASIO_MOVE_CAST(basic_descriptor)(other));
126 return *this;
127 }
128#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
129
130 /// Get a reference to the lowest layer.
131 /**
132 * This function returns a reference to the lowest layer in a stack of
133 * layers. Since a basic_descriptor cannot contain any further layers, it
134 * simply returns a reference to itself.
135 *
136 * @return A reference to the lowest layer in the stack of layers. Ownership
137 * is not transferred to the caller.
138 */
139 lowest_layer_type& lowest_layer()
140 {
141 return *this;
142 }
143
144 /// Get a const reference to the lowest layer.
145 /**
146 * This function returns a const reference to the lowest layer in a stack of
147 * layers. Since a basic_descriptor cannot contain any further layers, it
148 * simply returns a reference to itself.
149 *
150 * @return A const reference to the lowest layer in the stack of layers.
151 * Ownership is not transferred to the caller.
152 */
153 const lowest_layer_type& lowest_layer() const
154 {
155 return *this;
156 }
157
158 /// Assign an existing native descriptor to the descriptor.
159 /*
160 * This function opens the descriptor to hold an existing native descriptor.
161 *
162 * @param native_descriptor A native descriptor.
163 *
164 * @throws boost::system::system_error Thrown on failure.
165 */
166 void assign(const native_handle_type& native_descriptor)
167 {
168 boost::system::error_code ec;
169 this->get_service().assign(this->get_implementation(),
170 native_descriptor, ec);
171 boost::asio::detail::throw_error(ec, "assign");
172 }
173
174 /// Assign an existing native descriptor to the descriptor.
175 /*
176 * This function opens the descriptor to hold an existing native descriptor.
177 *
178 * @param native_descriptor A native descriptor.
179 *
180 * @param ec Set to indicate what error occurred, if any.
181 */
182 boost::system::error_code assign(const native_handle_type& native_descriptor,
183 boost::system::error_code& ec)
184 {
185 return this->get_service().assign(
186 this->get_implementation(), native_descriptor, ec);
187 }
188
189 /// Determine whether the descriptor is open.
190 bool is_open() const
191 {
192 return this->get_service().is_open(this->implementation);
193 }
194
195 /// Close the descriptor.
196 /**
197 * This function is used to close the descriptor. Any asynchronous read or
198 * write operations will be cancelled immediately, and will complete with the
199 * boost::asio::error::operation_aborted error.
200 *
201 * @throws boost::system::system_error Thrown on failure. Note that, even if
202 * the function indicates an error, the underlying descriptor is closed.
203 */
204 void close()
205 {
206 boost::system::error_code ec;
207 this->get_service().close(this->get_implementation(), ec);
208 boost::asio::detail::throw_error(ec, "close");
209 }
210
211 /// Close the descriptor.
212 /**
213 * This function is used to close the descriptor. Any asynchronous read or
214 * write operations will be cancelled immediately, and will complete with the
215 * boost::asio::error::operation_aborted error.
216 *
217 * @param ec Set to indicate what error occurred, if any. Note that, even if
218 * the function indicates an error, the underlying descriptor is closed.
219 */
220 boost::system::error_code close(boost::system::error_code& ec)
221 {
222 return this->get_service().close(this->get_implementation(), ec);
223 }
224
225 /// (Deprecated: Use native_handle().) Get the native descriptor
226 /// representation.
227 /**
228 * This function may be used to obtain the underlying representation of the
229 * descriptor. This is intended to allow access to native descriptor
230 * functionality that is not otherwise provided.
231 */
232 native_type native()
233 {
234 return this->get_service().native_handle(this->implementation);
235 }
236
237 /// Get the native descriptor representation.
238 /**
239 * This function may be used to obtain the underlying representation of the
240 * descriptor. This is intended to allow access to native descriptor
241 * functionality that is not otherwise provided.
242 */
243 native_handle_type native_handle()
244 {
245 return this->get_service().native_handle(this->implementation);
246 }
247
248 /// Release ownership of the native descriptor implementation.
249 /**
250 * This function may be used to obtain the underlying representation of the
251 * descriptor. After calling this function, @c is_open() returns false. The
252 * caller is responsible for closing the descriptor.
253 *
254 * All outstanding asynchronous read or write operations will finish
255 * immediately, and the handlers for cancelled operations will be passed the
256 * boost::asio::error::operation_aborted error.
257 */
258 native_handle_type release()
259 {
260 return this->get_service().release(this->implementation);
261 }
262
263 /// Cancel all asynchronous operations associated with the descriptor.
264 /**
265 * This function causes all outstanding asynchronous read or write operations
266 * to finish immediately, and the handlers for cancelled operations will be
267 * passed the boost::asio::error::operation_aborted error.
268 *
269 * @throws boost::system::system_error Thrown on failure.
270 */
271 void cancel()
272 {
273 boost::system::error_code ec;
274 this->get_service().cancel(this->get_implementation(), ec);
275 boost::asio::detail::throw_error(ec, "cancel");
276 }
277
278 /// Cancel all asynchronous operations associated with the descriptor.
279 /**
280 * This function causes all outstanding asynchronous read or write operations
281 * to finish immediately, and the handlers for cancelled operations will be
282 * passed the boost::asio::error::operation_aborted error.
283 *
284 * @param ec Set to indicate what error occurred, if any.
285 */
286 boost::system::error_code cancel(boost::system::error_code& ec)
287 {
288 return this->get_service().cancel(this->get_implementation(), ec);
289 }
290
291 /// Perform an IO control command on the descriptor.
292 /**
293 * This function is used to execute an IO control command on the descriptor.
294 *
295 * @param command The IO control command to be performed on the descriptor.
296 *
297 * @throws boost::system::system_error Thrown on failure.
298 *
299 * @sa IoControlCommand @n
300 * boost::asio::posix::descriptor_base::bytes_readable @n
301 * boost::asio::posix::descriptor_base::non_blocking_io
302 *
303 * @par Example
304 * Getting the number of bytes ready to read:
305 * @code
306 * boost::asio::posix::stream_descriptor descriptor(io_service);
307 * ...
308 * boost::asio::posix::stream_descriptor::bytes_readable command;
309 * descriptor.io_control(command);
310 * std::size_t bytes_readable = command.get();
311 * @endcode
312 */
313 template <typename IoControlCommand>
314 void io_control(IoControlCommand& command)
315 {
316 boost::system::error_code ec;
317 this->get_service().io_control(this->get_implementation(), command, ec);
318 boost::asio::detail::throw_error(ec, "io_control");
319 }
320
321 /// Perform an IO control command on the descriptor.
322 /**
323 * This function is used to execute an IO control command on the descriptor.
324 *
325 * @param command The IO control command to be performed on the descriptor.
326 *
327 * @param ec Set to indicate what error occurred, if any.
328 *
329 * @sa IoControlCommand @n
330 * boost::asio::posix::descriptor_base::bytes_readable @n
331 * boost::asio::posix::descriptor_base::non_blocking_io
332 *
333 * @par Example
334 * Getting the number of bytes ready to read:
335 * @code
336 * boost::asio::posix::stream_descriptor descriptor(io_service);
337 * ...
338 * boost::asio::posix::stream_descriptor::bytes_readable command;
339 * boost::system::error_code ec;
340 * descriptor.io_control(command, ec);
341 * if (ec)
342 * {
343 * // An error occurred.
344 * }
345 * std::size_t bytes_readable = command.get();
346 * @endcode
347 */
348 template <typename IoControlCommand>
349 boost::system::error_code io_control(IoControlCommand& command,
350 boost::system::error_code& ec)
351 {
352 return this->get_service().io_control(
353 this->get_implementation(), command, ec);
354 }
355
356 /// Gets the non-blocking mode of the descriptor.
357 /**
358 * @returns @c true if the descriptor's synchronous operations will fail with
359 * boost::asio::error::would_block if they are unable to perform the requested
360 * operation immediately. If @c false, synchronous operations will block
361 * until complete.
362 *
363 * @note The non-blocking mode has no effect on the behaviour of asynchronous
364 * operations. Asynchronous operations will never fail with the error
365 * boost::asio::error::would_block.
366 */
367 bool non_blocking() const
368 {
369 return this->get_service().non_blocking(this->implementation);
370 }
371
372 /// Sets the non-blocking mode of the descriptor.
373 /**
374 * @param mode If @c true, the descriptor's synchronous operations will fail
375 * with boost::asio::error::would_block if they are unable to perform the
376 * requested operation immediately. If @c false, synchronous operations will
377 * block until complete.
378 *
379 * @throws boost::system::system_error Thrown on failure.
380 *
381 * @note The non-blocking mode has no effect on the behaviour of asynchronous
382 * operations. Asynchronous operations will never fail with the error
383 * boost::asio::error::would_block.
384 */
385 void non_blocking(bool mode)
386 {
387 boost::system::error_code ec;
388 this->get_service().non_blocking(this->get_implementation(), mode, ec);
389 boost::asio::detail::throw_error(ec, "non_blocking");
390 }
391
392 /// Sets the non-blocking mode of the descriptor.
393 /**
394 * @param mode If @c true, the descriptor's synchronous operations will fail
395 * with boost::asio::error::would_block if they are unable to perform the
396 * requested operation immediately. If @c false, synchronous operations will
397 * block until complete.
398 *
399 * @param ec Set to indicate what error occurred, if any.
400 *
401 * @note The non-blocking mode has no effect on the behaviour of asynchronous
402 * operations. Asynchronous operations will never fail with the error
403 * boost::asio::error::would_block.
404 */
405 boost::system::error_code non_blocking(
406 bool mode, boost::system::error_code& ec)
407 {
408 return this->get_service().non_blocking(
409 this->get_implementation(), mode, ec);
410 }
411
412 /// Gets the non-blocking mode of the native descriptor implementation.
413 /**
414 * This function is used to retrieve the non-blocking mode of the underlying
415 * native descriptor. This mode has no effect on the behaviour of the
416 * descriptor object's synchronous operations.
417 *
418 * @returns @c true if the underlying descriptor is in non-blocking mode and
419 * direct system calls may fail with boost::asio::error::would_block (or the
420 * equivalent system error).
421 *
422 * @note The current non-blocking mode is cached by the descriptor object.
423 * Consequently, the return value may be incorrect if the non-blocking mode
424 * was set directly on the native descriptor.
425 */
426 bool native_non_blocking() const
427 {
428 return this->get_service().native_non_blocking(this->implementation);
429 }
430
431 /// Sets the non-blocking mode of the native descriptor implementation.
432 /**
433 * This function is used to modify the non-blocking mode of the underlying
434 * native descriptor. It has no effect on the behaviour of the descriptor
435 * object's synchronous operations.
436 *
437 * @param mode If @c true, the underlying descriptor is put into non-blocking
438 * mode and direct system calls may fail with boost::asio::error::would_block
439 * (or the equivalent system error).
440 *
441 * @throws boost::system::system_error Thrown on failure. If the @c mode is
442 * @c false, but the current value of @c non_blocking() is @c true, this
443 * function fails with boost::asio::error::invalid_argument, as the
444 * combination does not make sense.
445 */
446 void native_non_blocking(bool mode)
447 {
448 boost::system::error_code ec;
449 this->get_service().native_non_blocking(
450 this->get_implementation(), mode, ec);
451 boost::asio::detail::throw_error(ec, "native_non_blocking");
452 }
453
454 /// Sets the non-blocking mode of the native descriptor implementation.
455 /**
456 * This function is used to modify the non-blocking mode of the underlying
457 * native descriptor. It has no effect on the behaviour of the descriptor
458 * object's synchronous operations.
459 *
460 * @param mode If @c true, the underlying descriptor is put into non-blocking
461 * mode and direct system calls may fail with boost::asio::error::would_block
462 * (or the equivalent system error).
463 *
464 * @param ec Set to indicate what error occurred, if any. If the @c mode is
465 * @c false, but the current value of @c non_blocking() is @c true, this
466 * function fails with boost::asio::error::invalid_argument, as the
467 * combination does not make sense.
468 */
469 boost::system::error_code native_non_blocking(
470 bool mode, boost::system::error_code& ec)
471 {
472 return this->get_service().native_non_blocking(
473 this->get_implementation(), mode, ec);
474 }
475
476protected:
477 /// Protected destructor to prevent deletion through this type.
478 ~basic_descriptor()
479 {
480 }
481};
482
483} // namespace posix
484} // namespace asio
485} // namespace boost
486
487#include <boost/asio/detail/pop_options.hpp>
488
489#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
490 // || defined(GENERATING_DOCUMENTATION)
491
492#endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP
493