basic_overlapped_handle.hpp 15 KB

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