Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

671 lines
22KB

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