basic_overlapped_handle.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. //
  2. // windows/basic_overlapped_handle.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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_WINDOWS_BASIC_OVERLAPPED_HANDLE_HPP
  11. #define ASIO_WINDOWS_BASIC_OVERLAPPED_HANDLE_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_WINDOWS_RANDOM_ACCESS_HANDLE) \
  17. || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
  18. || defined(GENERATING_DOCUMENTATION)
  19. #include <cstddef>
  20. #include <utility>
  21. #include "asio/any_io_executor.hpp"
  22. #include "asio/async_result.hpp"
  23. #include "asio/detail/io_object_impl.hpp"
  24. #include "asio/detail/throw_error.hpp"
  25. #include "asio/detail/win_iocp_handle_service.hpp"
  26. #include "asio/error.hpp"
  27. #include "asio/execution_context.hpp"
  28. #include "asio/detail/push_options.hpp"
  29. namespace asio {
  30. namespace windows {
  31. /// Provides Windows handle functionality for objects that support
  32. /// overlapped I/O.
  33. /**
  34. * The windows::overlapped_handle class provides the ability to wrap a Windows
  35. * handle. The underlying object referred to by the handle must support
  36. * overlapped I/O.
  37. *
  38. * @par Thread Safety
  39. * @e Distinct @e objects: Safe.@n
  40. * @e Shared @e objects: Unsafe.
  41. */
  42. template <typename Executor = any_io_executor>
  43. class basic_overlapped_handle
  44. {
  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_overlapped_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 asio::detail::win_iocp_handle_service::native_handle_type
  60. native_handle_type;
  61. #endif
  62. /// An overlapped_handle is always the lowest layer.
  63. typedef basic_overlapped_handle lowest_layer_type;
  64. /// Construct an overlapped handle without opening it.
  65. /**
  66. * This constructor creates an overlapped handle without opening it.
  67. *
  68. * @param ex The I/O executor that the overlapped handle will use, by default,
  69. * to dispatch handlers for any asynchronous operations performed on the
  70. * overlapped handle.
  71. */
  72. explicit basic_overlapped_handle(const executor_type& ex)
  73. : impl_(0, ex)
  74. {
  75. }
  76. /// Construct an overlapped handle without opening it.
  77. /**
  78. * This constructor creates an overlapped handle without opening it.
  79. *
  80. * @param context An execution context which provides the I/O executor that
  81. * the overlapped handle will use, by default, to dispatch handlers for any
  82. * asynchronous operations performed on the overlapped handle.
  83. */
  84. template <typename ExecutionContext>
  85. explicit basic_overlapped_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 overlapped handle on an existing native handle.
  94. /**
  95. * This constructor creates an overlapped handle object to hold an existing
  96. * native handle.
  97. *
  98. * @param ex The I/O executor that the overlapped handle will use, by default,
  99. * to dispatch handlers for any asynchronous operations performed on the
  100. * overlapped handle.
  101. *
  102. * @param native_handle The new underlying handle implementation.
  103. *
  104. * @throws asio::system_error Thrown on failure.
  105. */
  106. basic_overlapped_handle(const executor_type& ex,
  107. const native_handle_type& native_handle)
  108. : impl_(0, ex)
  109. {
  110. asio::error_code ec;
  111. impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
  112. asio::detail::throw_error(ec, "assign");
  113. }
  114. /// Construct an overlapped handle on an existing native handle.
  115. /**
  116. * This constructor creates an overlapped handle object to hold an existing
  117. * native handle.
  118. *
  119. * @param context An execution context which provides the I/O executor that
  120. * the overlapped handle will use, by default, to dispatch handlers for any
  121. * asynchronous operations performed on the overlapped handle.
  122. *
  123. * @param native_handle The new underlying handle implementation.
  124. *
  125. * @throws asio::system_error Thrown on failure.
  126. */
  127. template <typename ExecutionContext>
  128. basic_overlapped_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. asio::error_code ec;
  136. impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
  137. asio::detail::throw_error(ec, "assign");
  138. }
  139. /// Move-construct an overlapped handle from another.
  140. /**
  141. * This constructor moves a handle from one object to another.
  142. *
  143. * @param other The other overlapped 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 overlapped_handle(const executor_type&)
  148. * constructor.
  149. */
  150. basic_overlapped_handle(basic_overlapped_handle&& other)
  151. : impl_(std::move(other.impl_))
  152. {
  153. }
  154. /// Move-assign an overlapped handle from another.
  155. /**
  156. * This assignment operator moves a handle from one object to another.
  157. *
  158. * @param other The other overlapped 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 overlapped_handle(const executor_type&)
  163. * constructor.
  164. */
  165. basic_overlapped_handle& operator=(basic_overlapped_handle&& other)
  166. {
  167. impl_ = std::move(other.impl_);
  168. return *this;
  169. }
  170. // All overlapped handles have access to each other's implementations.
  171. template <typename Executor1>
  172. friend class basic_overlapped_handle;
  173. /// Move-construct an overlapped handle from a handle of another executor
  174. /// type.
  175. /**
  176. * This constructor moves a handle from one object to another.
  177. *
  178. * @param other The other overlapped handle object from which the move will
  179. * occur.
  180. *
  181. * @note Following the move, the moved-from object is in the same state as if
  182. * constructed using the @c overlapped_handle(const executor_type&)
  183. * constructor.
  184. */
  185. template<typename Executor1>
  186. basic_overlapped_handle(basic_overlapped_handle<Executor1>&& other,
  187. constraint_t<
  188. is_convertible<Executor1, Executor>::value,
  189. defaulted_constraint
  190. > = defaulted_constraint())
  191. : impl_(std::move(other.impl_))
  192. {
  193. }
  194. /// Move-assign an overlapped handle from a handle of another executor type.
  195. /**
  196. * This assignment operator moves a handle from one object to another.
  197. *
  198. * @param other The other overlapped handle object from which the move will
  199. * occur.
  200. *
  201. * @note Following the move, the moved-from object is in the same state as if
  202. * constructed using the @c overlapped_handle(const executor_type&)
  203. * constructor.
  204. */
  205. template<typename Executor1>
  206. constraint_t<
  207. is_convertible<Executor1, Executor>::value,
  208. basic_overlapped_handle&
  209. > operator=(basic_overlapped_handle<Executor1>&& other)
  210. {
  211. impl_ = std::move(other.impl_);
  212. return *this;
  213. }
  214. /// Get the executor associated with the object.
  215. const executor_type& get_executor() noexcept
  216. {
  217. return impl_.get_executor();
  218. }
  219. /// Get a reference to the lowest layer.
  220. /**
  221. * This function returns a reference to the lowest layer in a stack of
  222. * layers. Since an overlapped_handle cannot contain any further layers, it
  223. * simply returns a reference to itself.
  224. *
  225. * @return A reference to the lowest layer in the stack of layers. Ownership
  226. * is not transferred to the caller.
  227. */
  228. lowest_layer_type& lowest_layer()
  229. {
  230. return *this;
  231. }
  232. /// Get a const reference to the lowest layer.
  233. /**
  234. * This function returns a const reference to the lowest layer in a stack of
  235. * layers. Since an overlapped_handle cannot contain any further layers, it
  236. * simply returns a reference to itself.
  237. *
  238. * @return A const reference to the lowest layer in the stack of layers.
  239. * Ownership is not transferred to the caller.
  240. */
  241. const lowest_layer_type& lowest_layer() const
  242. {
  243. return *this;
  244. }
  245. /// Assign an existing native handle to the handle.
  246. /*
  247. * This function opens the handle to hold an existing native handle.
  248. *
  249. * @param handle A native handle.
  250. *
  251. * @throws asio::system_error Thrown on failure.
  252. */
  253. void assign(const native_handle_type& handle)
  254. {
  255. asio::error_code ec;
  256. impl_.get_service().assign(impl_.get_implementation(), handle, ec);
  257. asio::detail::throw_error(ec, "assign");
  258. }
  259. /// Assign an existing native handle to the handle.
  260. /*
  261. * This function opens the handle to hold an existing native handle.
  262. *
  263. * @param handle A native handle.
  264. *
  265. * @param ec Set to indicate what error occurred, if any.
  266. */
  267. ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
  268. asio::error_code& ec)
  269. {
  270. impl_.get_service().assign(impl_.get_implementation(), handle, ec);
  271. ASIO_SYNC_OP_VOID_RETURN(ec);
  272. }
  273. /// Determine whether the handle is open.
  274. bool is_open() const
  275. {
  276. return impl_.get_service().is_open(impl_.get_implementation());
  277. }
  278. /// Close the handle.
  279. /**
  280. * This function is used to close the handle. Any asynchronous read or write
  281. * operations will be cancelled immediately, and will complete with the
  282. * asio::error::operation_aborted error.
  283. *
  284. * @throws asio::system_error Thrown on failure.
  285. */
  286. void close()
  287. {
  288. asio::error_code ec;
  289. impl_.get_service().close(impl_.get_implementation(), ec);
  290. asio::detail::throw_error(ec, "close");
  291. }
  292. /// Close the handle.
  293. /**
  294. * This function is used to close the handle. Any asynchronous read or write
  295. * operations will be cancelled immediately, and will complete with the
  296. * asio::error::operation_aborted error.
  297. *
  298. * @param ec Set to indicate what error occurred, if any.
  299. */
  300. ASIO_SYNC_OP_VOID close(asio::error_code& ec)
  301. {
  302. impl_.get_service().close(impl_.get_implementation(), ec);
  303. ASIO_SYNC_OP_VOID_RETURN(ec);
  304. }
  305. /// Release ownership of the underlying native handle.
  306. /**
  307. * This function causes all outstanding asynchronous operations to finish
  308. * immediately, and the handlers for cancelled operations will be passed the
  309. * asio::error::operation_aborted error. Ownership of the native handle
  310. * is then transferred to the caller.
  311. *
  312. * @throws asio::system_error Thrown on failure.
  313. *
  314. * @note This function is unsupported on Windows versions prior to Windows
  315. * 8.1, and will fail with asio::error::operation_not_supported on
  316. * these platforms.
  317. */
  318. #if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \
  319. && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
  320. __declspec(deprecated("This function always fails with "
  321. "operation_not_supported when used on Windows versions "
  322. "prior to Windows 8.1."))
  323. #endif
  324. native_handle_type release()
  325. {
  326. asio::error_code ec;
  327. native_handle_type s = impl_.get_service().release(
  328. impl_.get_implementation(), ec);
  329. asio::detail::throw_error(ec, "release");
  330. return s;
  331. }
  332. /// Release ownership of the underlying native handle.
  333. /**
  334. * This function causes all outstanding asynchronous operations to finish
  335. * immediately, and the handlers for cancelled operations will be passed the
  336. * asio::error::operation_aborted error. Ownership of the native handle
  337. * is then transferred to the caller.
  338. *
  339. * @param ec Set to indicate what error occurred, if any.
  340. *
  341. * @note This function is unsupported on Windows versions prior to Windows
  342. * 8.1, and will fail with asio::error::operation_not_supported on
  343. * these platforms.
  344. */
  345. #if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \
  346. && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
  347. __declspec(deprecated("This function always fails with "
  348. "operation_not_supported when used on Windows versions "
  349. "prior to Windows 8.1."))
  350. #endif
  351. native_handle_type release(asio::error_code& ec)
  352. {
  353. return impl_.get_service().release(impl_.get_implementation(), ec);
  354. }
  355. /// Get the native handle representation.
  356. /**
  357. * This function may be used to obtain the underlying representation of the
  358. * handle. This is intended to allow access to native handle functionality
  359. * that is not otherwise provided.
  360. */
  361. native_handle_type native_handle()
  362. {
  363. return impl_.get_service().native_handle(impl_.get_implementation());
  364. }
  365. /// Cancel all asynchronous operations associated with the handle.
  366. /**
  367. * This function causes all outstanding asynchronous read or write operations
  368. * to finish immediately, and the handlers for cancelled operations will be
  369. * passed the asio::error::operation_aborted error.
  370. *
  371. * @throws asio::system_error Thrown on failure.
  372. */
  373. void cancel()
  374. {
  375. asio::error_code ec;
  376. impl_.get_service().cancel(impl_.get_implementation(), ec);
  377. asio::detail::throw_error(ec, "cancel");
  378. }
  379. /// Cancel all asynchronous operations associated with the handle.
  380. /**
  381. * This function causes all outstanding asynchronous read or write operations
  382. * to finish immediately, and the handlers for cancelled operations will be
  383. * passed the asio::error::operation_aborted error.
  384. *
  385. * @param ec Set to indicate what error occurred, if any.
  386. */
  387. ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
  388. {
  389. impl_.get_service().cancel(impl_.get_implementation(), ec);
  390. ASIO_SYNC_OP_VOID_RETURN(ec);
  391. }
  392. protected:
  393. /// Protected destructor to prevent deletion through this type.
  394. /**
  395. * This function destroys the handle, cancelling any outstanding asynchronous
  396. * wait operations associated with the handle as if by calling @c cancel.
  397. */
  398. ~basic_overlapped_handle()
  399. {
  400. }
  401. asio::detail::io_object_impl<
  402. asio::detail::win_iocp_handle_service, Executor> impl_;
  403. private:
  404. // Disallow copying and assignment.
  405. basic_overlapped_handle(const basic_overlapped_handle&) = delete;
  406. basic_overlapped_handle& operator=(
  407. const basic_overlapped_handle&) = delete;
  408. };
  409. } // namespace windows
  410. } // namespace asio
  411. #include "asio/detail/pop_options.hpp"
  412. #endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
  413. // || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
  414. // || defined(GENERATING_DOCUMENTATION)
  415. #endif // ASIO_WINDOWS_BASIC_OVERLAPPED_HANDLE_HPP