]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/posix/basic_descriptor.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / asio / posix / basic_descriptor.hpp
1 //
2 // posix/basic_descriptor.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 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/async_result.hpp>
24 #include <boost/asio/detail/handler_type_requirements.hpp>
25 #include <boost/asio/detail/io_object_impl.hpp>
26 #include <boost/asio/detail/non_const_lvalue.hpp>
27 #include <boost/asio/detail/reactive_descriptor_service.hpp>
28 #include <boost/asio/detail/throw_error.hpp>
29 #include <boost/asio/error.hpp>
30 #include <boost/asio/execution_context.hpp>
31 #include <boost/asio/executor.hpp>
32 #include <boost/asio/posix/descriptor_base.hpp>
33
34 #if defined(BOOST_ASIO_HAS_MOVE)
35 # include <utility>
36 #endif // defined(BOOST_ASIO_HAS_MOVE)
37
38 #include <boost/asio/detail/push_options.hpp>
39
40 namespace boost {
41 namespace asio {
42 namespace posix {
43
44 /// Provides POSIX descriptor functionality.
45 /**
46 * The posix::basic_descriptor class template provides the ability to wrap a
47 * POSIX descriptor.
48 *
49 * @par Thread Safety
50 * @e Distinct @e objects: Safe.@n
51 * @e Shared @e objects: Unsafe.
52 */
53 template <typename Executor = executor>
54 class basic_descriptor
55 : public descriptor_base
56 {
57 public:
58 /// The type of the executor associated with the object.
59 typedef Executor executor_type;
60
61 /// Rebinds the descriptor type to another executor.
62 template <typename Executor1>
63 struct rebind_executor
64 {
65 /// The descriptor type when rebound to the specified executor.
66 typedef basic_descriptor<Executor1> other;
67 };
68
69 /// The native representation of a descriptor.
70 #if defined(GENERATING_DOCUMENTATION)
71 typedef implementation_defined native_handle_type;
72 #else
73 typedef detail::reactive_descriptor_service::native_handle_type
74 native_handle_type;
75 #endif
76
77 /// A descriptor is always the lowest layer.
78 typedef basic_descriptor lowest_layer_type;
79
80 /// Construct a descriptor without opening it.
81 /**
82 * This constructor creates a descriptor without opening it.
83 *
84 * @param ex The I/O executor that the descriptor will use, by default, to
85 * dispatch handlers for any asynchronous operations performed on the
86 * descriptor.
87 */
88 explicit basic_descriptor(const executor_type& ex)
89 : impl_(ex)
90 {
91 }
92
93 /// Construct a descriptor without opening it.
94 /**
95 * This constructor creates a descriptor without opening it.
96 *
97 * @param context An execution context which provides the I/O executor that
98 * the descriptor will use, by default, to dispatch handlers for any
99 * asynchronous operations performed on the descriptor.
100 */
101 template <typename ExecutionContext>
102 explicit basic_descriptor(ExecutionContext& context,
103 typename enable_if<
104 is_convertible<ExecutionContext&, execution_context&>::value
105 >::type* = 0)
106 : impl_(context)
107 {
108 }
109
110 /// Construct a descriptor on an existing native descriptor.
111 /**
112 * This constructor creates a descriptor object to hold an existing native
113 * descriptor.
114 *
115 * @param ex The I/O executor that the descriptor will use, by default, to
116 * dispatch handlers for any asynchronous operations performed on the
117 * descriptor.
118 *
119 * @param native_descriptor A native descriptor.
120 *
121 * @throws boost::system::system_error Thrown on failure.
122 */
123 basic_descriptor(const executor_type& ex,
124 const native_handle_type& native_descriptor)
125 : impl_(ex)
126 {
127 boost::system::error_code ec;
128 impl_.get_service().assign(impl_.get_implementation(),
129 native_descriptor, ec);
130 boost::asio::detail::throw_error(ec, "assign");
131 }
132
133 /// Construct a descriptor on an existing native descriptor.
134 /**
135 * This constructor creates a descriptor object to hold an existing native
136 * descriptor.
137 *
138 * @param context An execution context which provides the I/O executor that
139 * the descriptor will use, by default, to dispatch handlers for any
140 * asynchronous operations performed on the descriptor.
141 *
142 * @param native_descriptor A native descriptor.
143 *
144 * @throws boost::system::system_error Thrown on failure.
145 */
146 template <typename ExecutionContext>
147 basic_descriptor(ExecutionContext& context,
148 const native_handle_type& native_descriptor,
149 typename enable_if<
150 is_convertible<ExecutionContext&, execution_context&>::value
151 >::type* = 0)
152 : impl_(context)
153 {
154 boost::system::error_code ec;
155 impl_.get_service().assign(impl_.get_implementation(),
156 native_descriptor, ec);
157 boost::asio::detail::throw_error(ec, "assign");
158 }
159
160 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
161 /// Move-construct a descriptor from another.
162 /**
163 * This constructor moves a descriptor from one object to another.
164 *
165 * @param other The other descriptor object from which the move will
166 * occur.
167 *
168 * @note Following the move, the moved-from object is in the same state as if
169 * constructed using the @c basic_descriptor(const executor_type&)
170 * constructor.
171 */
172 basic_descriptor(basic_descriptor&& other)
173 : impl_(std::move(other.impl_))
174 {
175 }
176
177 /// Move-assign a descriptor from another.
178 /**
179 * This assignment operator moves a descriptor from one object to another.
180 *
181 * @param other The other descriptor object from which the move will
182 * occur.
183 *
184 * @note Following the move, the moved-from object is in the same state as if
185 * constructed using the @c basic_descriptor(const executor_type&)
186 * constructor.
187 */
188 basic_descriptor& operator=(basic_descriptor&& other)
189 {
190 impl_ = std::move(other.impl_);
191 return *this;
192 }
193 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
194
195 /// Get the executor associated with the object.
196 executor_type get_executor() BOOST_ASIO_NOEXCEPT
197 {
198 return impl_.get_executor();
199 }
200
201 /// Get a reference to the lowest layer.
202 /**
203 * This function returns a reference to the lowest layer in a stack of
204 * layers. Since a descriptor cannot contain any further layers, it
205 * simply returns a reference to itself.
206 *
207 * @return A reference to the lowest layer in the stack of layers. Ownership
208 * is not transferred to the caller.
209 */
210 lowest_layer_type& lowest_layer()
211 {
212 return *this;
213 }
214
215 /// Get a const reference to the lowest layer.
216 /**
217 * This function returns a const reference to the lowest layer in a stack of
218 * layers. Since a descriptor cannot contain any further layers, it
219 * simply returns a reference to itself.
220 *
221 * @return A const reference to the lowest layer in the stack of layers.
222 * Ownership is not transferred to the caller.
223 */
224 const lowest_layer_type& lowest_layer() const
225 {
226 return *this;
227 }
228
229 /// Assign an existing native descriptor to the descriptor.
230 /*
231 * This function opens the descriptor to hold an existing native descriptor.
232 *
233 * @param native_descriptor A native descriptor.
234 *
235 * @throws boost::system::system_error Thrown on failure.
236 */
237 void assign(const native_handle_type& native_descriptor)
238 {
239 boost::system::error_code ec;
240 impl_.get_service().assign(impl_.get_implementation(),
241 native_descriptor, ec);
242 boost::asio::detail::throw_error(ec, "assign");
243 }
244
245 /// Assign an existing native descriptor to the descriptor.
246 /*
247 * This function opens the descriptor to hold an existing native descriptor.
248 *
249 * @param native_descriptor A native descriptor.
250 *
251 * @param ec Set to indicate what error occurred, if any.
252 */
253 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,
254 boost::system::error_code& ec)
255 {
256 impl_.get_service().assign(
257 impl_.get_implementation(), native_descriptor, ec);
258 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
259 }
260
261 /// Determine whether the descriptor is open.
262 bool is_open() const
263 {
264 return impl_.get_service().is_open(impl_.get_implementation());
265 }
266
267 /// Close the descriptor.
268 /**
269 * This function is used to close the descriptor. Any asynchronous read or
270 * write operations will be cancelled immediately, and will complete with the
271 * boost::asio::error::operation_aborted error.
272 *
273 * @throws boost::system::system_error Thrown on failure. Note that, even if
274 * the function indicates an error, the underlying descriptor is closed.
275 */
276 void close()
277 {
278 boost::system::error_code ec;
279 impl_.get_service().close(impl_.get_implementation(), ec);
280 boost::asio::detail::throw_error(ec, "close");
281 }
282
283 /// Close the descriptor.
284 /**
285 * This function is used to close the descriptor. Any asynchronous read or
286 * write operations will be cancelled immediately, and will complete with the
287 * boost::asio::error::operation_aborted error.
288 *
289 * @param ec Set to indicate what error occurred, if any. Note that, even if
290 * the function indicates an error, the underlying descriptor is closed.
291 */
292 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
293 {
294 impl_.get_service().close(impl_.get_implementation(), ec);
295 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
296 }
297
298 /// Get the native descriptor representation.
299 /**
300 * This function may be used to obtain the underlying representation of the
301 * descriptor. This is intended to allow access to native descriptor
302 * functionality that is not otherwise provided.
303 */
304 native_handle_type native_handle()
305 {
306 return impl_.get_service().native_handle(impl_.get_implementation());
307 }
308
309 /// Release ownership of the native descriptor implementation.
310 /**
311 * This function may be used to obtain the underlying representation of the
312 * descriptor. After calling this function, @c is_open() returns false. The
313 * caller is responsible for closing the descriptor.
314 *
315 * All outstanding asynchronous read or write operations will finish
316 * immediately, and the handlers for cancelled operations will be passed the
317 * boost::asio::error::operation_aborted error.
318 */
319 native_handle_type release()
320 {
321 return impl_.get_service().release(impl_.get_implementation());
322 }
323
324 /// Cancel all asynchronous operations associated with the descriptor.
325 /**
326 * This function causes all outstanding asynchronous read or write operations
327 * to finish immediately, and the handlers for cancelled operations will be
328 * passed the boost::asio::error::operation_aborted error.
329 *
330 * @throws boost::system::system_error Thrown on failure.
331 */
332 void cancel()
333 {
334 boost::system::error_code ec;
335 impl_.get_service().cancel(impl_.get_implementation(), ec);
336 boost::asio::detail::throw_error(ec, "cancel");
337 }
338
339 /// Cancel all asynchronous operations associated with the descriptor.
340 /**
341 * This function causes all outstanding asynchronous read or write operations
342 * to finish immediately, and the handlers for cancelled operations will be
343 * passed the boost::asio::error::operation_aborted error.
344 *
345 * @param ec Set to indicate what error occurred, if any.
346 */
347 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
348 {
349 impl_.get_service().cancel(impl_.get_implementation(), ec);
350 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
351 }
352
353 /// Perform an IO control command on the descriptor.
354 /**
355 * This function is used to execute an IO control command on the descriptor.
356 *
357 * @param command The IO control command to be performed on the descriptor.
358 *
359 * @throws boost::system::system_error Thrown on failure.
360 *
361 * @sa IoControlCommand @n
362 * boost::asio::posix::descriptor_base::bytes_readable @n
363 * boost::asio::posix::descriptor_base::non_blocking_io
364 *
365 * @par Example
366 * Getting the number of bytes ready to read:
367 * @code
368 * boost::asio::posix::stream_descriptor descriptor(my_context);
369 * ...
370 * boost::asio::posix::stream_descriptor::bytes_readable command;
371 * descriptor.io_control(command);
372 * std::size_t bytes_readable = command.get();
373 * @endcode
374 */
375 template <typename IoControlCommand>
376 void io_control(IoControlCommand& command)
377 {
378 boost::system::error_code ec;
379 impl_.get_service().io_control(impl_.get_implementation(), command, ec);
380 boost::asio::detail::throw_error(ec, "io_control");
381 }
382
383 /// Perform an IO control command on the descriptor.
384 /**
385 * This function is used to execute an IO control command on the descriptor.
386 *
387 * @param command The IO control command to be performed on the descriptor.
388 *
389 * @param ec Set to indicate what error occurred, if any.
390 *
391 * @sa IoControlCommand @n
392 * boost::asio::posix::descriptor_base::bytes_readable @n
393 * boost::asio::posix::descriptor_base::non_blocking_io
394 *
395 * @par Example
396 * Getting the number of bytes ready to read:
397 * @code
398 * boost::asio::posix::stream_descriptor descriptor(my_context);
399 * ...
400 * boost::asio::posix::stream_descriptor::bytes_readable command;
401 * boost::system::error_code ec;
402 * descriptor.io_control(command, ec);
403 * if (ec)
404 * {
405 * // An error occurred.
406 * }
407 * std::size_t bytes_readable = command.get();
408 * @endcode
409 */
410 template <typename IoControlCommand>
411 BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
412 boost::system::error_code& ec)
413 {
414 impl_.get_service().io_control(impl_.get_implementation(), command, ec);
415 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
416 }
417
418 /// Gets the non-blocking mode of the descriptor.
419 /**
420 * @returns @c true if the descriptor's synchronous operations will fail with
421 * boost::asio::error::would_block if they are unable to perform the requested
422 * operation immediately. If @c false, synchronous operations will block
423 * until complete.
424 *
425 * @note The non-blocking mode has no effect on the behaviour of asynchronous
426 * operations. Asynchronous operations will never fail with the error
427 * boost::asio::error::would_block.
428 */
429 bool non_blocking() const
430 {
431 return impl_.get_service().non_blocking(impl_.get_implementation());
432 }
433
434 /// Sets the non-blocking mode of the descriptor.
435 /**
436 * @param mode If @c true, the descriptor's synchronous operations will fail
437 * with boost::asio::error::would_block if they are unable to perform the
438 * requested operation immediately. If @c false, synchronous operations will
439 * block until complete.
440 *
441 * @throws boost::system::system_error Thrown on failure.
442 *
443 * @note The non-blocking mode has no effect on the behaviour of asynchronous
444 * operations. Asynchronous operations will never fail with the error
445 * boost::asio::error::would_block.
446 */
447 void non_blocking(bool mode)
448 {
449 boost::system::error_code ec;
450 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
451 boost::asio::detail::throw_error(ec, "non_blocking");
452 }
453
454 /// Sets the non-blocking mode of the descriptor.
455 /**
456 * @param mode If @c true, the descriptor's synchronous operations will fail
457 * with boost::asio::error::would_block if they are unable to perform the
458 * requested operation immediately. If @c false, synchronous operations will
459 * block until complete.
460 *
461 * @param ec Set to indicate what error occurred, if any.
462 *
463 * @note The non-blocking mode has no effect on the behaviour of asynchronous
464 * operations. Asynchronous operations will never fail with the error
465 * boost::asio::error::would_block.
466 */
467 BOOST_ASIO_SYNC_OP_VOID non_blocking(
468 bool mode, boost::system::error_code& ec)
469 {
470 impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
471 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
472 }
473
474 /// Gets the non-blocking mode of the native descriptor implementation.
475 /**
476 * This function is used to retrieve the non-blocking mode of the underlying
477 * native descriptor. This mode has no effect on the behaviour of the
478 * descriptor object's synchronous operations.
479 *
480 * @returns @c true if the underlying descriptor is in non-blocking mode and
481 * direct system calls may fail with boost::asio::error::would_block (or the
482 * equivalent system error).
483 *
484 * @note The current non-blocking mode is cached by the descriptor object.
485 * Consequently, the return value may be incorrect if the non-blocking mode
486 * was set directly on the native descriptor.
487 */
488 bool native_non_blocking() const
489 {
490 return impl_.get_service().native_non_blocking(
491 impl_.get_implementation());
492 }
493
494 /// Sets the non-blocking mode of the native descriptor implementation.
495 /**
496 * This function is used to modify the non-blocking mode of the underlying
497 * native descriptor. It has no effect on the behaviour of the descriptor
498 * object's synchronous operations.
499 *
500 * @param mode If @c true, the underlying descriptor is put into non-blocking
501 * mode and direct system calls may fail with boost::asio::error::would_block
502 * (or the equivalent system error).
503 *
504 * @throws boost::system::system_error Thrown on failure. If the @c mode is
505 * @c false, but the current value of @c non_blocking() is @c true, this
506 * function fails with boost::asio::error::invalid_argument, as the
507 * combination does not make sense.
508 */
509 void native_non_blocking(bool mode)
510 {
511 boost::system::error_code ec;
512 impl_.get_service().native_non_blocking(
513 impl_.get_implementation(), mode, ec);
514 boost::asio::detail::throw_error(ec, "native_non_blocking");
515 }
516
517 /// Sets the non-blocking mode of the native descriptor implementation.
518 /**
519 * This function is used to modify the non-blocking mode of the underlying
520 * native descriptor. It has no effect on the behaviour of the descriptor
521 * object's synchronous operations.
522 *
523 * @param mode If @c true, the underlying descriptor is put into non-blocking
524 * mode and direct system calls may fail with boost::asio::error::would_block
525 * (or the equivalent system error).
526 *
527 * @param ec Set to indicate what error occurred, if any. If the @c mode is
528 * @c false, but the current value of @c non_blocking() is @c true, this
529 * function fails with boost::asio::error::invalid_argument, as the
530 * combination does not make sense.
531 */
532 BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
533 bool mode, boost::system::error_code& ec)
534 {
535 impl_.get_service().native_non_blocking(
536 impl_.get_implementation(), mode, ec);
537 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
538 }
539
540 /// Wait for the descriptor to become ready to read, ready to write, or to
541 /// have pending error conditions.
542 /**
543 * This function is used to perform a blocking wait for a descriptor to enter
544 * a ready to read, write or error condition state.
545 *
546 * @param w Specifies the desired descriptor state.
547 *
548 * @par Example
549 * Waiting for a descriptor to become readable.
550 * @code
551 * boost::asio::posix::stream_descriptor descriptor(my_context);
552 * ...
553 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read);
554 * @endcode
555 */
556 void wait(wait_type w)
557 {
558 boost::system::error_code ec;
559 impl_.get_service().wait(impl_.get_implementation(), w, ec);
560 boost::asio::detail::throw_error(ec, "wait");
561 }
562
563 /// Wait for the descriptor to become ready to read, ready to write, or to
564 /// have pending error conditions.
565 /**
566 * This function is used to perform a blocking wait for a descriptor to enter
567 * a ready to read, write or error condition state.
568 *
569 * @param w Specifies the desired descriptor state.
570 *
571 * @param ec Set to indicate what error occurred, if any.
572 *
573 * @par Example
574 * Waiting for a descriptor to become readable.
575 * @code
576 * boost::asio::posix::stream_descriptor descriptor(my_context);
577 * ...
578 * boost::system::error_code ec;
579 * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec);
580 * @endcode
581 */
582 BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
583 {
584 impl_.get_service().wait(impl_.get_implementation(), w, ec);
585 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
586 }
587
588 /// Asynchronously wait for the descriptor to become ready to read, ready to
589 /// write, or to have pending error conditions.
590 /**
591 * This function is used to perform an asynchronous wait for a descriptor to
592 * enter a ready to read, write or error condition state.
593 *
594 * @param w Specifies the desired descriptor state.
595 *
596 * @param handler The handler to be called when the wait operation completes.
597 * Copies will be made of the handler as required. The function signature of
598 * the handler must be:
599 * @code void handler(
600 * const boost::system::error_code& error // Result of operation
601 * ); @endcode
602 * Regardless of whether the asynchronous operation completes immediately or
603 * not, the handler will not be invoked from within this function. On
604 * immediate completion, invocation of the handler will be performed in a
605 * manner equivalent to using boost::asio::post().
606 *
607 * @par Example
608 * @code
609 * void wait_handler(const boost::system::error_code& error)
610 * {
611 * if (!error)
612 * {
613 * // Wait succeeded.
614 * }
615 * }
616 *
617 * ...
618 *
619 * boost::asio::posix::stream_descriptor descriptor(my_context);
620 * ...
621 * descriptor.async_wait(
622 * boost::asio::posix::stream_descriptor::wait_read,
623 * wait_handler);
624 * @endcode
625 */
626 template <
627 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
628 WaitHandler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
629 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,
630 void (boost::system::error_code))
631 async_wait(wait_type w,
632 BOOST_ASIO_MOVE_ARG(WaitHandler) handler
633 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
634 {
635 return async_initiate<WaitHandler, void (boost::system::error_code)>(
636 initiate_async_wait(this), handler, w);
637 }
638
639 protected:
640 /// Protected destructor to prevent deletion through this type.
641 /**
642 * This function destroys the descriptor, cancelling any outstanding
643 * asynchronous wait operations associated with the descriptor as if by
644 * calling @c cancel.
645 */
646 ~basic_descriptor()
647 {
648 }
649
650 detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;
651
652 private:
653 // Disallow copying and assignment.
654 basic_descriptor(const basic_descriptor&) BOOST_ASIO_DELETED;
655 basic_descriptor& operator=(const basic_descriptor&) BOOST_ASIO_DELETED;
656
657 class initiate_async_wait
658 {
659 public:
660 typedef Executor executor_type;
661
662 explicit initiate_async_wait(basic_descriptor* self)
663 : self_(self)
664 {
665 }
666
667 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
668 {
669 return self_->get_executor();
670 }
671
672 template <typename WaitHandler>
673 void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) const
674 {
675 // If you get an error on the following line it means that your handler
676 // does not meet the documented type requirements for a WaitHandler.
677 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
678
679 detail::non_const_lvalue<WaitHandler> handler2(handler);
680 self_->impl_.get_service().async_wait(
681 self_->impl_.get_implementation(), w, handler2.value,
682 self_->impl_.get_implementation_executor());
683 }
684
685 private:
686 basic_descriptor* self_;
687 };
688 };
689
690 } // namespace posix
691 } // namespace asio
692 } // namespace boost
693
694 #include <boost/asio/detail/pop_options.hpp>
695
696 #endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
697 // || defined(GENERATING_DOCUMENTATION)
698
699 #endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP