basic_object_handle.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. //
  2. // windows/basic_object_handle.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 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 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 <boost/asio/async_result.hpp>
  20. #include <boost/asio/detail/io_object_impl.hpp>
  21. #include <boost/asio/detail/throw_error.hpp>
  22. #include <boost/asio/detail/win_object_handle_service.hpp>
  23. #include <boost/asio/error.hpp>
  24. #include <boost/asio/execution_context.hpp>
  25. #include <boost/asio/executor.hpp>
  26. #if defined(BOOST_ASIO_HAS_MOVE)
  27. # include <utility>
  28. #endif // defined(BOOST_ASIO_HAS_MOVE)
  29. #include <boost/asio/detail/push_options.hpp>
  30. namespace boost {
  31. namespace asio {
  32. namespace windows {
  33. /// Provides object-oriented handle functionality.
  34. /**
  35. * The windows::basic_object_handle class provides asynchronous and blocking
  36. * object-oriented handle functionality.
  37. *
  38. * @par Thread Safety
  39. * @e Distinct @e objects: Safe.@n
  40. * @e Shared @e objects: Unsafe.
  41. */
  42. template <typename Executor = executor>
  43. class basic_object_handle
  44. {
  45. public:
  46. /// The type of the executor associated with the object.
  47. typedef Executor executor_type;
  48. /// The native representation of a handle.
  49. #if defined(GENERATING_DOCUMENTATION)
  50. typedef implementation_defined native_handle_type;
  51. #else
  52. typedef boost::asio::detail::win_object_handle_service::native_handle_type
  53. native_handle_type;
  54. #endif
  55. /// An object handle is always the lowest layer.
  56. typedef basic_object_handle lowest_layer_type;
  57. /// Construct an object handle without opening it.
  58. /**
  59. * This constructor creates an object handle without opening it.
  60. *
  61. * @param ex The I/O executor that the object handle will use, by default, to
  62. * dispatch handlers for any asynchronous operations performed on the
  63. * object handle.
  64. */
  65. explicit basic_object_handle(const executor_type& ex)
  66. : impl_(ex)
  67. {
  68. }
  69. /// Construct an object handle without opening it.
  70. /**
  71. * This constructor creates an object handle without opening it.
  72. *
  73. * @param context An execution context which provides the I/O executor that
  74. * the object handle will use, by default, to dispatch handlers for any
  75. * asynchronous operations performed on the object handle.
  76. */
  77. template <typename ExecutionContext>
  78. explicit basic_object_handle(ExecutionContext& context,
  79. typename enable_if<
  80. is_convertible<ExecutionContext&, execution_context&>::value,
  81. basic_object_handle
  82. >::type* = 0)
  83. : impl_(context)
  84. {
  85. }
  86. /// Construct an object handle on an existing native handle.
  87. /**
  88. * This constructor creates an object handle object to hold an existing native
  89. * handle.
  90. *
  91. * @param ex The I/O executor that the object handle will use, by default, to
  92. * dispatch handlers for any asynchronous operations performed on the
  93. * object handle.
  94. *
  95. * @param native_handle The new underlying handle implementation.
  96. *
  97. * @throws boost::system::system_error Thrown on failure.
  98. */
  99. basic_object_handle(const executor_type& ex,
  100. const native_handle_type& native_handle)
  101. : impl_(ex)
  102. {
  103. boost::system::error_code ec;
  104. impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
  105. boost::asio::detail::throw_error(ec, "assign");
  106. }
  107. /// Construct an object handle on an existing native handle.
  108. /**
  109. * This constructor creates an object handle object to hold an existing native
  110. * handle.
  111. *
  112. * @param context An execution context which provides the I/O executor that
  113. * the object handle will use, by default, to dispatch handlers for any
  114. * asynchronous operations performed on the object handle.
  115. *
  116. * @param native_handle The new underlying handle implementation.
  117. *
  118. * @throws boost::system::system_error Thrown on failure.
  119. */
  120. template <typename ExecutionContext>
  121. basic_object_handle(ExecutionContext& context,
  122. const native_handle_type& native_handle,
  123. typename enable_if<
  124. is_convertible<ExecutionContext&, execution_context&>::value
  125. >::type* = 0)
  126. : impl_(context)
  127. {
  128. boost::system::error_code ec;
  129. impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
  130. boost::asio::detail::throw_error(ec, "assign");
  131. }
  132. #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  133. /// Move-construct an object handle from another.
  134. /**
  135. * This constructor moves an object handle from one object to another.
  136. *
  137. * @param other The other object handle object from which the move will
  138. * occur.
  139. *
  140. * @note Following the move, the moved-from object is in the same state as if
  141. * constructed using the @c basic_object_handle(const executor_type&)
  142. * constructor.
  143. */
  144. basic_object_handle(basic_object_handle&& other)
  145. : impl_(std::move(other.impl_))
  146. {
  147. }
  148. /// Move-assign an object handle from another.
  149. /**
  150. * This assignment operator moves an object handle from one object to another.
  151. *
  152. * @param other The other object handle object from which the move will
  153. * occur.
  154. *
  155. * @note Following the move, the moved-from object is in the same state as if
  156. * constructed using the @c basic_object_handle(const executor_type&)
  157. * constructor.
  158. */
  159. basic_object_handle& operator=(basic_object_handle&& other)
  160. {
  161. impl_ = std::move(other.impl_);
  162. return *this;
  163. }
  164. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  165. /// Get the executor associated with the object.
  166. executor_type get_executor() BOOST_ASIO_NOEXCEPT
  167. {
  168. return impl_.get_executor();
  169. }
  170. /// Get a reference to the lowest layer.
  171. /**
  172. * This function returns a reference to the lowest layer in a stack of
  173. * layers. Since an object handle cannot contain any further layers, it simply
  174. * returns a reference to itself.
  175. *
  176. * @return A reference to the lowest layer in the stack of layers. Ownership
  177. * is not transferred to the caller.
  178. */
  179. lowest_layer_type& lowest_layer()
  180. {
  181. return *this;
  182. }
  183. /// Get a const reference to the lowest layer.
  184. /**
  185. * This function returns a const reference to the lowest layer in a stack of
  186. * layers. Since an object handle cannot contain any further layers, it simply
  187. * returns a reference to itself.
  188. *
  189. * @return A const reference to the lowest layer in the stack of layers.
  190. * Ownership is not transferred to the caller.
  191. */
  192. const lowest_layer_type& lowest_layer() const
  193. {
  194. return *this;
  195. }
  196. /// Assign an existing native handle to the handle.
  197. /*
  198. * This function opens the handle to hold an existing native handle.
  199. *
  200. * @param handle A native handle.
  201. *
  202. * @throws boost::system::system_error Thrown on failure.
  203. */
  204. void assign(const native_handle_type& handle)
  205. {
  206. boost::system::error_code ec;
  207. impl_.get_service().assign(impl_.get_implementation(), handle, ec);
  208. boost::asio::detail::throw_error(ec, "assign");
  209. }
  210. /// Assign an existing native handle to the handle.
  211. /*
  212. * This function opens the handle to hold an existing native handle.
  213. *
  214. * @param handle A native handle.
  215. *
  216. * @param ec Set to indicate what error occurred, if any.
  217. */
  218. BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
  219. boost::system::error_code& ec)
  220. {
  221. impl_.get_service().assign(impl_.get_implementation(), handle, ec);
  222. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  223. }
  224. /// Determine whether the handle is open.
  225. bool is_open() const
  226. {
  227. return impl_.get_service().is_open(impl_.get_implementation());
  228. }
  229. /// Close the handle.
  230. /**
  231. * This function is used to close the handle. Any asynchronous read or write
  232. * operations will be cancelled immediately, and will complete with the
  233. * boost::asio::error::operation_aborted error.
  234. *
  235. * @throws boost::system::system_error Thrown on failure.
  236. */
  237. void close()
  238. {
  239. boost::system::error_code ec;
  240. impl_.get_service().close(impl_.get_implementation(), ec);
  241. boost::asio::detail::throw_error(ec, "close");
  242. }
  243. /// Close the handle.
  244. /**
  245. * This function is used to close the handle. Any asynchronous read or write
  246. * operations will be cancelled immediately, and will complete with the
  247. * boost::asio::error::operation_aborted error.
  248. *
  249. * @param ec Set to indicate what error occurred, if any.
  250. */
  251. BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
  252. {
  253. impl_.get_service().close(impl_.get_implementation(), ec);
  254. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  255. }
  256. /// Get the native handle representation.
  257. /**
  258. * This function may be used to obtain the underlying representation of the
  259. * handle. This is intended to allow access to native handle functionality
  260. * that is not otherwise provided.
  261. */
  262. native_handle_type native_handle()
  263. {
  264. return impl_.get_service().native_handle(impl_.get_implementation());
  265. }
  266. /// Cancel all asynchronous operations associated with the handle.
  267. /**
  268. * This function causes all outstanding asynchronous read or write operations
  269. * to finish immediately, and the handlers for cancelled operations will be
  270. * passed the boost::asio::error::operation_aborted error.
  271. *
  272. * @throws boost::system::system_error Thrown on failure.
  273. */
  274. void cancel()
  275. {
  276. boost::system::error_code ec;
  277. impl_.get_service().cancel(impl_.get_implementation(), ec);
  278. boost::asio::detail::throw_error(ec, "cancel");
  279. }
  280. /// Cancel all asynchronous operations associated with the handle.
  281. /**
  282. * This function causes all outstanding asynchronous read or write operations
  283. * to finish immediately, and the handlers for cancelled operations will be
  284. * passed the boost::asio::error::operation_aborted error.
  285. *
  286. * @param ec Set to indicate what error occurred, if any.
  287. */
  288. BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
  289. {
  290. impl_.get_service().cancel(impl_.get_implementation(), ec);
  291. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  292. }
  293. /// Perform a blocking wait on the object handle.
  294. /**
  295. * This function is used to wait for the object handle to be set to the
  296. * signalled state. This function blocks and does not return until the object
  297. * handle has been set to the signalled state.
  298. *
  299. * @throws boost::system::system_error Thrown on failure.
  300. */
  301. void wait()
  302. {
  303. boost::system::error_code ec;
  304. impl_.get_service().wait(impl_.get_implementation(), ec);
  305. boost::asio::detail::throw_error(ec, "wait");
  306. }
  307. /// Perform a blocking wait on the object handle.
  308. /**
  309. * This function is used to wait for the object handle to be set to the
  310. * signalled state. This function blocks and does not return until the object
  311. * handle has been set to the signalled state.
  312. *
  313. * @param ec Set to indicate what error occurred, if any.
  314. */
  315. void wait(boost::system::error_code& ec)
  316. {
  317. impl_.get_service().wait(impl_.get_implementation(), ec);
  318. }
  319. /// Start an asynchronous wait on the object handle.
  320. /**
  321. * This function is be used to initiate an asynchronous wait against the
  322. * object handle. It always returns immediately.
  323. *
  324. * @param handler The handler to be called when the object handle is set to
  325. * the signalled state. Copies will be made of the handler as required. The
  326. * function signature of the handler must be:
  327. * @code void handler(
  328. * const boost::system::error_code& error // Result of operation.
  329. * ); @endcode
  330. * Regardless of whether the asynchronous operation completes immediately or
  331. * not, the handler will not be invoked from within this function. On
  332. * immediate completion, invocation of the handler will be performed in a
  333. * manner equivalent to using boost::asio::post().
  334. */
  335. template <typename WaitHandler>
  336. BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
  337. void (boost::system::error_code))
  338. async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
  339. {
  340. boost::asio::async_completion<WaitHandler,
  341. void (boost::system::error_code)> init(handler);
  342. impl_.get_service().async_wait(impl_.get_implementation(),
  343. init.completion_handler, impl_.get_implementation_executor());
  344. return init.result.get();
  345. }
  346. private:
  347. // Disallow copying and assignment.
  348. basic_object_handle(const basic_object_handle&) BOOST_ASIO_DELETED;
  349. basic_object_handle& operator=(const basic_object_handle&) BOOST_ASIO_DELETED;
  350. boost::asio::detail::io_object_impl<
  351. boost::asio::detail::win_object_handle_service, Executor> impl_;
  352. };
  353. } // namespace windows
  354. } // namespace asio
  355. } // namespace boost
  356. #include <boost/asio/detail/pop_options.hpp>
  357. #endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
  358. // || defined(GENERATING_DOCUMENTATION)
  359. #endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP