basic_overlapped_handle.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. //
  2. // windows/basic_overlapped_handle.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2022 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 "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_iocp_handle_service.hpp"
  25. #include "asio/error.hpp"
  26. #include "asio/execution_context.hpp"
  27. #if defined(ASIO_HAS_MOVE)
  28. # include <utility>
  29. #endif // defined(ASIO_HAS_MOVE)
  30. #include "asio/detail/push_options.hpp"
  31. namespace asio {
  32. namespace windows {
  33. /// Provides Windows handle functionality for objects that support
  34. /// overlapped I/O.
  35. /**
  36. * The windows::overlapped_handle class provides the ability to wrap a Windows
  37. * handle. The underlying object referred to by the handle must support
  38. * overlapped I/O.
  39. *
  40. * @par Thread Safety
  41. * @e Distinct @e objects: Safe.@n
  42. * @e Shared @e objects: Unsafe.
  43. */
  44. template <typename Executor = any_io_executor>
  45. class basic_overlapped_handle
  46. {
  47. public:
  48. /// The type of the executor associated with the object.
  49. typedef Executor executor_type;
  50. /// Rebinds the handle type to another executor.
  51. template <typename Executor1>
  52. struct rebind_executor
  53. {
  54. /// The handle type when rebound to the specified executor.
  55. typedef basic_overlapped_handle<Executor1> other;
  56. };
  57. /// The native representation of a handle.
  58. #if defined(GENERATING_DOCUMENTATION)
  59. typedef implementation_defined native_handle_type;
  60. #else
  61. typedef asio::detail::win_iocp_handle_service::native_handle_type
  62. native_handle_type;
  63. #endif
  64. /// An overlapped_handle is always the lowest layer.
  65. typedef basic_overlapped_handle lowest_layer_type;
  66. /// Construct an overlapped handle without opening it.
  67. /**
  68. * This constructor creates an overlapped handle without opening it.
  69. *
  70. * @param ex The I/O executor that the overlapped handle will use, by default,
  71. * to dispatch handlers for any asynchronous operations performed on the
  72. * overlapped handle.
  73. */
  74. explicit basic_overlapped_handle(const executor_type& ex)
  75. : impl_(0, ex)
  76. {
  77. }
  78. /// Construct an overlapped handle without opening it.
  79. /**
  80. * This constructor creates an overlapped handle without opening it.
  81. *
  82. * @param context An execution context which provides the I/O executor that
  83. * the overlapped handle will use, by default, to dispatch handlers for any
  84. * asynchronous operations performed on the overlapped handle.
  85. */
  86. template <typename ExecutionContext>
  87. explicit basic_overlapped_handle(ExecutionContext& context,
  88. typename constraint<
  89. is_convertible<ExecutionContext&, execution_context&>::value,
  90. defaulted_constraint
  91. >::type = defaulted_constraint())
  92. : impl_(0, 0, context)
  93. {
  94. }
  95. /// Construct an overlapped handle on an existing native handle.
  96. /**
  97. * This constructor creates an overlapped handle object to hold an existing
  98. * native handle.
  99. *
  100. * @param ex The I/O executor that the overlapped handle will use, by default,
  101. * to dispatch handlers for any asynchronous operations performed on the
  102. * overlapped handle.
  103. *
  104. * @param native_handle The new underlying handle implementation.
  105. *
  106. * @throws asio::system_error Thrown on failure.
  107. */
  108. basic_overlapped_handle(const executor_type& ex,
  109. const native_handle_type& native_handle)
  110. : impl_(0, ex)
  111. {
  112. asio::error_code ec;
  113. impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
  114. asio::detail::throw_error(ec, "assign");
  115. }
  116. /// Construct an overlapped handle on an existing native handle.
  117. /**
  118. * This constructor creates an overlapped handle object to hold an existing
  119. * native handle.
  120. *
  121. * @param context An execution context which provides the I/O executor that
  122. * the overlapped handle will use, by default, to dispatch handlers for any
  123. * asynchronous operations performed on the overlapped handle.
  124. *
  125. * @param native_handle The new underlying handle implementation.
  126. *
  127. * @throws asio::system_error Thrown on failure.
  128. */
  129. template <typename ExecutionContext>
  130. basic_overlapped_handle(ExecutionContext& context,
  131. const native_handle_type& native_handle,
  132. typename constraint<
  133. is_convertible<ExecutionContext&, execution_context&>::value
  134. >::type = 0)
  135. : impl_(0, 0, context)
  136. {
  137. asio::error_code ec;
  138. impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
  139. asio::detail::throw_error(ec, "assign");
  140. }
  141. #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  142. /// Move-construct an overlapped handle from another.
  143. /**
  144. * This constructor moves a handle from one object to another.
  145. *
  146. * @param other The other overlapped handle object from which the move will
  147. * occur.
  148. *
  149. * @note Following the move, the moved-from object is in the same state as if
  150. * constructed using the @c overlapped_handle(const executor_type&)
  151. * constructor.
  152. */
  153. basic_overlapped_handle(basic_overlapped_handle&& other)
  154. : impl_(std::move(other.impl_))
  155. {
  156. }
  157. /// Move-assign an overlapped handle from another.
  158. /**
  159. * This assignment operator moves a handle from one object to another.
  160. *
  161. * @param other The other overlapped handle object from which the move will
  162. * occur.
  163. *
  164. * @note Following the move, the moved-from object is in the same state as if
  165. * constructed using the @c overlapped_handle(const executor_type&)
  166. * constructor.
  167. */
  168. basic_overlapped_handle& operator=(basic_overlapped_handle&& other)
  169. {
  170. impl_ = std::move(other.impl_);
  171. return *this;
  172. }
  173. #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  174. /// Get the executor associated with the object.
  175. executor_type get_executor() ASIO_NOEXCEPT
  176. {
  177. return impl_.get_executor();
  178. }
  179. /// Get a reference to the lowest layer.
  180. /**
  181. * This function returns a reference to the lowest layer in a stack of
  182. * layers. Since an overlapped_handle cannot contain any further layers, it
  183. * simply returns a reference to itself.
  184. *
  185. * @return A reference to the lowest layer in the stack of layers. Ownership
  186. * is not transferred to the caller.
  187. */
  188. lowest_layer_type& lowest_layer()
  189. {
  190. return *this;
  191. }
  192. /// Get a const reference to the lowest layer.
  193. /**
  194. * This function returns a const reference to the lowest layer in a stack of
  195. * layers. Since an overlapped_handle cannot contain any further layers, it
  196. * simply returns a reference to itself.
  197. *
  198. * @return A const reference to the lowest layer in the stack of layers.
  199. * Ownership is not transferred to the caller.
  200. */
  201. const lowest_layer_type& lowest_layer() const
  202. {
  203. return *this;
  204. }
  205. /// Assign an existing native handle to the handle.
  206. /*
  207. * This function opens the handle to hold an existing native handle.
  208. *
  209. * @param handle A native handle.
  210. *
  211. * @throws asio::system_error Thrown on failure.
  212. */
  213. void assign(const native_handle_type& handle)
  214. {
  215. asio::error_code ec;
  216. impl_.get_service().assign(impl_.get_implementation(), handle, ec);
  217. asio::detail::throw_error(ec, "assign");
  218. }
  219. /// Assign an existing native handle to the handle.
  220. /*
  221. * This function opens the handle to hold an existing native handle.
  222. *
  223. * @param handle A native handle.
  224. *
  225. * @param ec Set to indicate what error occurred, if any.
  226. */
  227. ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
  228. asio::error_code& ec)
  229. {
  230. impl_.get_service().assign(impl_.get_implementation(), handle, ec);
  231. ASIO_SYNC_OP_VOID_RETURN(ec);
  232. }
  233. /// Determine whether the handle is open.
  234. bool is_open() const
  235. {
  236. return impl_.get_service().is_open(impl_.get_implementation());
  237. }
  238. /// Close the handle.
  239. /**
  240. * This function is used to close the handle. Any asynchronous read or write
  241. * operations will be cancelled immediately, and will complete with the
  242. * asio::error::operation_aborted error.
  243. *
  244. * @throws asio::system_error Thrown on failure.
  245. */
  246. void close()
  247. {
  248. asio::error_code ec;
  249. impl_.get_service().close(impl_.get_implementation(), ec);
  250. asio::detail::throw_error(ec, "close");
  251. }
  252. /// Close the handle.
  253. /**
  254. * This function is used to close the handle. Any asynchronous read or write
  255. * operations will be cancelled immediately, and will complete with the
  256. * asio::error::operation_aborted error.
  257. *
  258. * @param ec Set to indicate what error occurred, if any.
  259. */
  260. ASIO_SYNC_OP_VOID close(asio::error_code& ec)
  261. {
  262. impl_.get_service().close(impl_.get_implementation(), ec);
  263. ASIO_SYNC_OP_VOID_RETURN(ec);
  264. }
  265. /// Get the native handle representation.
  266. /**
  267. * This function may be used to obtain the underlying representation of the
  268. * handle. This is intended to allow access to native handle functionality
  269. * that is not otherwise provided.
  270. */
  271. native_handle_type native_handle()
  272. {
  273. return impl_.get_service().native_handle(impl_.get_implementation());
  274. }
  275. /// Cancel all asynchronous operations associated with the handle.
  276. /**
  277. * This function causes all outstanding asynchronous read or write operations
  278. * to finish immediately, and the handlers for cancelled operations will be
  279. * passed the asio::error::operation_aborted error.
  280. *
  281. * @throws asio::system_error Thrown on failure.
  282. */
  283. void cancel()
  284. {
  285. asio::error_code ec;
  286. impl_.get_service().cancel(impl_.get_implementation(), ec);
  287. asio::detail::throw_error(ec, "cancel");
  288. }
  289. /// Cancel all asynchronous operations associated with the handle.
  290. /**
  291. * This function causes all outstanding asynchronous read or write operations
  292. * to finish immediately, and the handlers for cancelled operations will be
  293. * passed the asio::error::operation_aborted error.
  294. *
  295. * @param ec Set to indicate what error occurred, if any.
  296. */
  297. ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)
  298. {
  299. impl_.get_service().cancel(impl_.get_implementation(), ec);
  300. ASIO_SYNC_OP_VOID_RETURN(ec);
  301. }
  302. protected:
  303. /// Protected destructor to prevent deletion through this type.
  304. /**
  305. * This function destroys the handle, cancelling any outstanding asynchronous
  306. * wait operations associated with the handle as if by calling @c cancel.
  307. */
  308. ~basic_overlapped_handle()
  309. {
  310. }
  311. asio::detail::io_object_impl<
  312. asio::detail::win_iocp_handle_service, Executor> impl_;
  313. private:
  314. // Disallow copying and assignment.
  315. basic_overlapped_handle(const basic_overlapped_handle&) ASIO_DELETED;
  316. basic_overlapped_handle& operator=(
  317. const basic_overlapped_handle&) ASIO_DELETED;
  318. };
  319. } // namespace windows
  320. } // namespace asio
  321. #include "asio/detail/pop_options.hpp"
  322. #endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
  323. // || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
  324. // || defined(GENERATING_DOCUMENTATION)
  325. #endif // ASIO_WINDOWS_BASIC_OVERLAPPED_HANDLE_HPP