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.

basic_descriptor.hpp 19KB

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