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 | |
30 | namespace boost { |
31 | namespace asio { |
32 | namespace 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 | */ |
43 | template <typename DescriptorService> |
44 | class basic_descriptor |
45 | : public basic_io_object<DescriptorService>, |
46 | public descriptor_base |
47 | { |
48 | public: |
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(err: ec, location: "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(err: ec, location: "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(err: ec, location: "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(err: ec, location: "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(err: ec, location: "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(err: ec, location: "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(err: ec, location: "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 | |
476 | protected: |
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 | |