basic_object_handle.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. //
  2. // windows/basic_object_handle.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. // Copyright (c) 2011 Boris Schaeling (boris@highscore.de)
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. #ifndef ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
  12. #define ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  14. # pragma once
  15. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #include "asio/detail/config.hpp"
  17. #if defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE) \
  18. || defined(GENERATING_DOCUMENTATION)
  19. #include <utility>
  20. #include "asio/any_io_executor.hpp"
  21. #include "asio/async_result.hpp"
  22. #include "asio/detail/io_object_impl.hpp"
  23. #include "asio/detail/throw_error.hpp"
  24. #include "asio/detail/win_object_handle_service.hpp"
  25. #include "asio/error.hpp"
  26. #include "asio/execution_context.hpp"
  27. #include "asio/detail/push_options.hpp"
  28. namespace asio {
  29. namespace windows {
  30. /// Provides object-oriented handle functionality.
  31. /**
  32. * The windows::basic_object_handle class provides asynchronous and blocking
  33. * object-oriented handle functionality.
  34. *
  35. * @par Thread Safety
  36. * @e Distinct @e objects: Safe.@n
  37. * @e Shared @e objects: Unsafe.
  38. */
  39. template <typename Executor = any_io_executor>
  40. class basic_object_handle
  41. {
  42. private:
  43. class initiate_async_wait;
  44. public:
  45. /// The type of the executor associated with the object.
  46. typedef Executor executor_type;
  47. /// Rebinds the handle type to another executor.
  48. template <typename Executor1>
  49. struct rebind_executor
  50. {
  51. /// The handle type when rebound to the specified executor.
  52. typedef basic_object_handle<Executor1> other;
  53. };
  54. /// The native representation of a handle.
  55. #if defined(GENERATING_DOCUMENTATION)
  56. typedef implementation_defined native_handle_type;
  57. #else
  58. typedef asio::detail::win_object_handle_service::native_handle_type
  59. native_handle_type;
  60. #endif
  61. /// An object handle is always the lowest layer.
  62. typedef basic_object_handle lowest_layer_type;
  63. /// Construct an object handle without opening it.
  64. /**
  65. * This constructor creates an object handle without opening it.
  66. *
  67. * @param ex The I/O executor that the object handle will use, by default, to
  68. * dispatch handlers for any asynchronous operations performed on the
  69. * object handle.
  70. */
  71. explicit basic_object_handle(const executor_type& ex)
  72. : impl_(0, ex)
  73. {
  74. }
  75. /// Construct an object handle without opening it.
  76. /**
  77. * This constructor creates an object handle without opening it.
  78. *
  79. * @param context An execution context which provides the I/O executor that
  80. * the object handle will use, by default, to dispatch handlers for any
  81. * asynchronous operations performed on the object handle.
  82. */
  83. template <typename ExecutionContext>
  84. explicit basic_object_handle(ExecutionContext& context,
  85. constraint_t<
  86. is_convertible<ExecutionContext&, execution_context&>::value,
  87. defaulted_constraint
  88. > = defaulted_constraint())
  89. : impl_(0, 0, context)
  90. {
  91. }
  92. /// Construct an object handle on an existing native handle.
  93. /**
  94. * This constructor creates an object handle object to hold an existing native
  95. * handle.
  96. *
  97. * @param ex The I/O executor that the object handle will use, by default, to
  98. * dispatch handlers for any asynchronous operations performed on the
  99. * object handle.
  100. *
  101. * @param native_handle The new underlying handle implementation.
  102. *
  103. * @throws asio::system_error Thrown on failure.
  104. */
  105. basic_object_handle(const executor_type& ex,
  106. const native_handle_type& native_handle)
  107. : impl_(0, ex)
  108. {
  109. asio::error_code ec;
  110. impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
  111. asio::detail::throw_error(ec, "assign");
  112. }
  113. /// Construct an object handle on an existing native handle.
  114. /**
  115. * This constructor creates an object handle object to hold an existing native
  116. * handle.
  117. *
  118. * @param context An execution context which provides the I/O executor that
  119. * the object handle will use, by default, to dispatch handlers for any
  120. * asynchronous operations performed on the object handle.
  121. *
  122. * @param native_handle The new underlying handle implementation.
  123. *
  124. * @throws asio::system_error Thrown on failure.
  125. */
  126. template <typename ExecutionContext>
  127. basic_object_handle(ExecutionContext& context,
  128. const native_handle_type& native_handle,
  129. constraint_t<
  130. is_convertible<ExecutionContext&, execution_context&>::value
  131. > = 0)
  132. : impl_(0, 0, context)
  133. {
  134. asio::error_code ec;
  135. impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
  136. asio::detail::throw_error(ec, "assign");
  137. }
  138. /// Move-construct an object handle from another.
  139. /**
  140. * This constructor moves an object handle from one object to another.
  141. *
  142. * @param other The other object handle object from which the move will
  143. * occur.
  144. *
  145. * @note Following the move, the moved-from object is in the same state as if
  146. * constructed using the @c basic_object_handle(const executor_type&)
  147. * constructor.
  148. */
  149. basic_object_handle(basic_object_handle&& other)
  150. : impl_(std::move(other.impl_))
  151. {
  152. }
  153. /// Move-assign an object handle from another.
  154. /**
  155. * This assignment operator moves an object handle from one object to another.
  156. *
  157. * @param other The other object handle object from which the move will
  158. * occur.
  159. *
  160. * @note Following the move, the moved-from object is in the same state as if
  161. * constructed using the @c basic_object_handle(const executor_type&)
  162. * constructor.
  163. */
  164. basic_object_handle& operator=(basic_object_handle&& other)
  165. {
  166. impl_ = std::move(other.impl_);
  167. return *this;
  168. }
  169. // All handles have access to each other's implementations.
  170. template <typename Executor1>
  171. friend class basic_object_handle;
  172. /// Move-construct an object handle from a handle of another executor type.
  173. /**
  174. * This constructor moves an object handle from one object to another.
  175. *
  176. * @param other The other object handle object from which the move will
  177. * occur.
  178. *
  179. * @note Following the move, the moved-from object is in the same state as if
  180. * constructed using the @c basic_object_handle(const executor_type&)
  181. * constructor.
  182. */
  183. template<typename Executor1>
  184. basic_object_handle(basic_object_handle<Executor1>&& other,
  185. constraint_t<
  186. is_convertible<Executor1, Executor>::value,
  187. defaulted_constraint
  188. > = defaulted_constraint())
  189. : impl_(std::move(other.impl_))
  190. {
  191. }
  192. /// Move-assign an object handle from a handle of another executor type.
  193. /**
  194. * This assignment operator moves an object handle from one object to another.
  195. *
  196. * @param other The other object handle object from which the move will
  197. * occur.
  198. *
  199. * @note Following the move, the moved-from object is in the same state as if
  200. * constructed using the @c basic_object_handle(const executor_type&)
  201. * constructor.
  202. */
  203. template<typename Executor1>
  204. constraint_t<
  205. is_convertible<Executor1, Executor>::value,
  206. basic_object_handle&
  207. > operator=(basic_object_handle<Executor1>&& other)
  208. {
  209. impl_ = std::move(other.impl_);
  210. return *this;
  211. }
  212. /// Get the executor associated with the object.
  213. const executor_type& get_executor() noexcept
  214. {
  215. return impl_.get_executor();
  216. }
  217. /// Get a reference to the lowest layer.
  218. /**
  219. * This function returns a reference to the lowest layer in a stack of
  220. * layers. Since an object handle cannot contain any further layers, it simply
  221. * returns a reference to itself.
  222. *
  223. * @return A reference to the lowest layer in the stack of layers. Ownership
  224. * is not transferred to the caller.
  225. */
  226. lowest_layer_type& lowest_layer()
  227. {
  228. return *this;
  229. }
  230. /// Get a const reference to the lowest layer.
  231. /**
  232. * This function returns a const reference to the lowest layer in a stack of
  233. * layers. Since an object handle cannot contain any further layers, it simply
  234. * returns a reference to itself.
  235. *
  236. * @return A const reference to the lowest layer in the stack of layers.
  237. * Ownership is not transferred to the caller.
  238. */
  239. const lowest_layer_type& lowest_layer() const
  240. {
  241. return *this;
  242. }
  243. /// Assign an existing native handle to the handle.
  244. /*
  245. * This function opens the handle to hold an existing native handle.
  246. *
  247. * @param handle A native handle.
  248. *
  249. * @throws asio::system_error Thrown on failure.
  250. */
  251. void assign(const native_handle_type& handle)
  252. {
  253. asio::error_code ec;
  254. impl_.get_service().assign(impl_.get_implementation(), handle, ec);
  255. asio::detail::throw_error(ec, "assign");
  256. }
  257. /// Assign an existing native handle to the handle.
  258. /*
  259. * This function opens the handle to hold an existing native handle.
  260. *
  261. * @param handle A native handle.
  262. *
  263. * @param ec Set to indicate what error occurred, if any.
  264. */
  265. ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
  266. asio::error_code& ec)
  267. {
  268. impl_.get_service().assign(impl_.get_implementation(), handle, ec);
  269. ASIO_SYNC_OP_VOID_RETURN(ec);
  270. }
  271. /// Determine whether the handle is open.
  272. bool is_open() const
  273. {
  274. return impl_.get_service().is_open(impl_.get_implementation());
  275. }
  276. /// Close the handle.
  277. /**
  278. * This function is used to close the handle. Any asynchronous read or write
  279. * operations will be cancelled immediately, and will complete with the
  280. * asio::error::operation_aborted error.
  281. *
  282. * @throws asio::system_error Thrown on failure.
  283. */
  284. void close()
  285. {
  286. asio::error_code ec;
  287. impl_.get_service().close(impl_.get_implementation(), ec);
  288. asio::detail::throw_error(ec, "close");
  289. }
  290. /// Close the handle.
  291. /**
  292. * This function is used to close the handle. Any asynchronous read or write
  293. * operations will be cancelled immediately, and will complete with the
  294. * asio::error::operation_aborted error.
  295. *
  296. * @param ec Set to indicate what error occurred, if any.
  297. */
  298. ASIO_SYNC_OP_VOID close(asio::error_code& ec)
  299. {
  300. impl_.get_service().close(impl_.get_implementation(), ec);
  301. ASIO_SYNC_OP_VOID_RETURN(ec);
  302. }
  303. /// Get the native handle representation.
  304. /**
  305. * This function may be used to obtain the underlying representation of the
  306. * handle. This is intended to allow access to native handle functionality
  307. * that is not otherwise provided.
  308. */
  309. native_handle_type native_handle()
  310. {
  311. return impl_.get_service().native_handle(impl_.get_implementation());
  312. }
  313. /// Cancel all asynchronous operations associated with the handle.
  314. /**
  315. * This function causes all outstanding asynchronous read or write operations
  316. * to finish immediately, and the handlers for cancelled operations will be
  317. * passed the asio::error::operation_aborted error.
  318. *
  319. * @throws asio::system_error Thrown on failure.
  320. */
  321. void cancel()
  322. {
  323. asio::error_code ec;
  324. impl_.get_service().cancel(impl_.get_implementation(), ec);
  325. asio::detail::throw_error(ec, "cancel");
  326. }
  327. /// Cancel all asynchronous operations associated with the handle.
  328. /**
  329. * This function causes all outstanding asynchronous read or write operations
  330. * to finish immediately, and the handlers for cancelled operations will be
  331. * passed the asio::error::operation_aborted error.
  332. *
  333. * @param ec Set to indicate what error occurred, if any.
  334. */
  335. ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
  336. {
  337. impl_.get_service().cancel(impl_.get_implementation(), ec);
  338. ASIO_SYNC_OP_VOID_RETURN(ec);
  339. }
  340. /// Perform a blocking wait on the object handle.
  341. /**
  342. * This function is used to wait for the object handle to be set to the
  343. * signalled state. This function blocks and does not return until the object
  344. * handle has been set to the signalled state.
  345. *
  346. * @throws asio::system_error Thrown on failure.
  347. */
  348. void wait()
  349. {
  350. asio::error_code ec;
  351. impl_.get_service().wait(impl_.get_implementation(), ec);
  352. asio::detail::throw_error(ec, "wait");
  353. }
  354. /// Perform a blocking wait on the object handle.
  355. /**
  356. * This function is used to wait for the object handle to be set to the
  357. * signalled state. This function blocks and does not return until the object
  358. * handle has been set to the signalled state.
  359. *
  360. * @param ec Set to indicate what error occurred, if any.
  361. */
  362. void wait(asio::error_code& ec)
  363. {
  364. impl_.get_service().wait(impl_.get_implementation(), ec);
  365. }
  366. /// Start an asynchronous wait on the object handle.
  367. /**
  368. * This function is be used to initiate an asynchronous wait against the
  369. * object handle. It is an initiating function for an @ref
  370. * asynchronous_operation, and always returns immediately.
  371. *
  372. * @param token The @ref completion_token that will be used to produce a
  373. * completion handler, which will be called when the wait completes.
  374. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  375. * @ref yield_context, or a function object with the correct completion
  376. * signature. The function signature of the completion handler must be:
  377. * @code void handler(
  378. * const asio::error_code& error // Result of operation.
  379. * ); @endcode
  380. * Regardless of whether the asynchronous operation completes immediately or
  381. * not, the completion handler will not be invoked from within this function.
  382. * On immediate completion, invocation of the handler will be performed in a
  383. * manner equivalent to using asio::post().
  384. *
  385. * @par Completion Signature
  386. * @code void(asio::error_code) @endcode
  387. */
  388. template <
  389. ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))
  390. WaitToken = default_completion_token_t<executor_type>>
  391. auto async_wait(
  392. WaitToken&& token = default_completion_token_t<executor_type>())
  393. -> decltype(
  394. async_initiate<WaitToken, void (asio::error_code)>(
  395. declval<initiate_async_wait>(), token))
  396. {
  397. return async_initiate<WaitToken, void (asio::error_code)>(
  398. initiate_async_wait(this), token);
  399. }
  400. private:
  401. // Disallow copying and assignment.
  402. basic_object_handle(const basic_object_handle&) = delete;
  403. basic_object_handle& operator=(const basic_object_handle&) = delete;
  404. class initiate_async_wait
  405. {
  406. public:
  407. typedef Executor executor_type;
  408. explicit initiate_async_wait(basic_object_handle* self)
  409. : self_(self)
  410. {
  411. }
  412. const executor_type& get_executor() const noexcept
  413. {
  414. return self_->get_executor();
  415. }
  416. template <typename WaitHandler>
  417. void operator()(WaitHandler&& handler) const
  418. {
  419. // If you get an error on the following line it means that your handler
  420. // does not meet the documented type requirements for a WaitHandler.
  421. ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
  422. detail::non_const_lvalue<WaitHandler> handler2(handler);
  423. self_->impl_.get_service().async_wait(
  424. self_->impl_.get_implementation(),
  425. handler2.value, self_->impl_.get_executor());
  426. }
  427. private:
  428. basic_object_handle* self_;
  429. };
  430. asio::detail::io_object_impl<
  431. asio::detail::win_object_handle_service, Executor> impl_;
  432. };
  433. } // namespace windows
  434. } // namespace asio
  435. #include "asio/detail/pop_options.hpp"
  436. #endif // defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE)
  437. // || defined(GENERATING_DOCUMENTATION)
  438. #endif // ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP