basic_object_handle.hpp 16 KB

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