2 // windows/basic_object_handle.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 // Copyright (c) 2011 Boris Schaeling (boris@highscore.de)
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)
12 #ifndef BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
13 #define BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
19 #include <boost/asio/detail/config.hpp>
21 #if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \
22 || defined(GENERATING_DOCUMENTATION)
24 #include <boost/asio/any_io_executor.hpp>
25 #include <boost/asio/async_result.hpp>
26 #include <boost/asio/detail/io_object_impl.hpp>
27 #include <boost/asio/detail/throw_error.hpp>
28 #include <boost/asio/detail/win_object_handle_service.hpp>
29 #include <boost/asio/error.hpp>
30 #include <boost/asio/execution_context.hpp>
32 #if defined(BOOST_ASIO_HAS_MOVE)
34 #endif // defined(BOOST_ASIO_HAS_MOVE)
36 #include <boost/asio/detail/push_options.hpp>
42 /// Provides object-oriented handle functionality.
44 * The windows::basic_object_handle class provides asynchronous and blocking
45 * object-oriented handle functionality.
48 * @e Distinct @e objects: Safe.@n
49 * @e Shared @e objects: Unsafe.
51 template <typename Executor = any_io_executor>
52 class basic_object_handle
55 /// The type of the executor associated with the object.
56 typedef Executor executor_type;
58 /// Rebinds the handle type to another executor.
59 template <typename Executor1>
60 struct rebind_executor
62 /// The handle type when rebound to the specified executor.
63 typedef basic_object_handle<Executor1> other;
66 /// The native representation of a handle.
67 #if defined(GENERATING_DOCUMENTATION)
68 typedef implementation_defined native_handle_type;
70 typedef boost::asio::detail::win_object_handle_service::native_handle_type
74 /// An object handle is always the lowest layer.
75 typedef basic_object_handle lowest_layer_type;
77 /// Construct an object handle without opening it.
79 * This constructor creates an object handle without opening it.
81 * @param ex The I/O executor that the object handle will use, by default, to
82 * dispatch handlers for any asynchronous operations performed on the
85 explicit basic_object_handle(const executor_type& ex)
90 /// Construct an object handle without opening it.
92 * This constructor creates an object handle without opening it.
94 * @param context An execution context which provides the I/O executor that
95 * the object handle will use, by default, to dispatch handlers for any
96 * asynchronous operations performed on the object handle.
98 template <typename ExecutionContext>
99 explicit basic_object_handle(ExecutionContext& context,
101 is_convertible<ExecutionContext&, execution_context&>::value,
103 >::type = defaulted_constraint())
104 : impl_(0, 0, context)
108 /// Construct an object handle on an existing native handle.
110 * This constructor creates an object handle object to hold an existing native
113 * @param ex The I/O executor that the object handle will use, by default, to
114 * dispatch handlers for any asynchronous operations performed on the
117 * @param native_handle The new underlying handle implementation.
119 * @throws boost::system::system_error Thrown on failure.
121 basic_object_handle(const executor_type& ex,
122 const native_handle_type& native_handle)
125 boost::system::error_code ec;
126 impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
127 boost::asio::detail::throw_error(ec, "assign");
130 /// Construct an object handle on an existing native handle.
132 * This constructor creates an object handle object to hold an existing native
135 * @param context An execution context which provides the I/O executor that
136 * the object handle will use, by default, to dispatch handlers for any
137 * asynchronous operations performed on the object handle.
139 * @param native_handle The new underlying handle implementation.
141 * @throws boost::system::system_error Thrown on failure.
143 template <typename ExecutionContext>
144 basic_object_handle(ExecutionContext& context,
145 const native_handle_type& native_handle,
147 is_convertible<ExecutionContext&, execution_context&>::value
149 : impl_(0, 0, context)
151 boost::system::error_code ec;
152 impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);
153 boost::asio::detail::throw_error(ec, "assign");
156 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
157 /// Move-construct an object handle from another.
159 * This constructor moves an object handle from one object to another.
161 * @param other The other object handle object from which the move will
164 * @note Following the move, the moved-from object is in the same state as if
165 * constructed using the @c basic_object_handle(const executor_type&)
168 basic_object_handle(basic_object_handle&& other)
169 : impl_(std::move(other.impl_))
173 /// Move-assign an object handle from another.
175 * This assignment operator moves an object handle from one object to another.
177 * @param other The other object handle object from which the move will
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&)
184 basic_object_handle& operator=(basic_object_handle&& other)
186 impl_ = std::move(other.impl_);
189 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
191 /// Get the executor associated with the object.
192 executor_type get_executor() BOOST_ASIO_NOEXCEPT
194 return impl_.get_executor();
197 /// Get a reference to the lowest layer.
199 * This function returns a reference to the lowest layer in a stack of
200 * layers. Since an object handle cannot contain any further layers, it simply
201 * returns a reference to itself.
203 * @return A reference to the lowest layer in the stack of layers. Ownership
204 * is not transferred to the caller.
206 lowest_layer_type& lowest_layer()
211 /// Get a const reference to the lowest layer.
213 * This function returns a const reference to the lowest layer in a stack of
214 * layers. Since an object handle cannot contain any further layers, it simply
215 * returns a reference to itself.
217 * @return A const reference to the lowest layer in the stack of layers.
218 * Ownership is not transferred to the caller.
220 const lowest_layer_type& lowest_layer() const
225 /// Assign an existing native handle to the handle.
227 * This function opens the handle to hold an existing native handle.
229 * @param handle A native handle.
231 * @throws boost::system::system_error Thrown on failure.
233 void assign(const native_handle_type& handle)
235 boost::system::error_code ec;
236 impl_.get_service().assign(impl_.get_implementation(), handle, ec);
237 boost::asio::detail::throw_error(ec, "assign");
240 /// Assign an existing native handle to the handle.
242 * This function opens the handle to hold an existing native handle.
244 * @param handle A native handle.
246 * @param ec Set to indicate what error occurred, if any.
248 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
249 boost::system::error_code& ec)
251 impl_.get_service().assign(impl_.get_implementation(), handle, ec);
252 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
255 /// Determine whether the handle is open.
258 return impl_.get_service().is_open(impl_.get_implementation());
261 /// Close the handle.
263 * This function is used to close the handle. Any asynchronous read or write
264 * operations will be cancelled immediately, and will complete with the
265 * boost::asio::error::operation_aborted error.
267 * @throws boost::system::system_error Thrown on failure.
271 boost::system::error_code ec;
272 impl_.get_service().close(impl_.get_implementation(), ec);
273 boost::asio::detail::throw_error(ec, "close");
276 /// Close the handle.
278 * This function is used to close the handle. Any asynchronous read or write
279 * operations will be cancelled immediately, and will complete with the
280 * boost::asio::error::operation_aborted error.
282 * @param ec Set to indicate what error occurred, if any.
284 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
286 impl_.get_service().close(impl_.get_implementation(), ec);
287 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
290 /// Get the native handle representation.
292 * This function may be used to obtain the underlying representation of the
293 * handle. This is intended to allow access to native handle functionality
294 * that is not otherwise provided.
296 native_handle_type native_handle()
298 return impl_.get_service().native_handle(impl_.get_implementation());
301 /// Cancel all asynchronous operations associated with the handle.
303 * This function causes all outstanding asynchronous read or write operations
304 * to finish immediately, and the handlers for cancelled operations will be
305 * passed the boost::asio::error::operation_aborted error.
307 * @throws boost::system::system_error Thrown on failure.
311 boost::system::error_code ec;
312 impl_.get_service().cancel(impl_.get_implementation(), ec);
313 boost::asio::detail::throw_error(ec, "cancel");
316 /// Cancel all asynchronous operations associated with the handle.
318 * This function causes all outstanding asynchronous read or write operations
319 * to finish immediately, and the handlers for cancelled operations will be
320 * passed the boost::asio::error::operation_aborted error.
322 * @param ec Set to indicate what error occurred, if any.
324 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
326 impl_.get_service().cancel(impl_.get_implementation(), ec);
327 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
330 /// Perform a blocking wait on the object handle.
332 * This function is used to wait for the object handle to be set to the
333 * signalled state. This function blocks and does not return until the object
334 * handle has been set to the signalled state.
336 * @throws boost::system::system_error Thrown on failure.
340 boost::system::error_code ec;
341 impl_.get_service().wait(impl_.get_implementation(), ec);
342 boost::asio::detail::throw_error(ec, "wait");
345 /// Perform a blocking wait on the object handle.
347 * This function is used to wait for the object handle to be set to the
348 * signalled state. This function blocks and does not return until the object
349 * handle has been set to the signalled state.
351 * @param ec Set to indicate what error occurred, if any.
353 void wait(boost::system::error_code& ec)
355 impl_.get_service().wait(impl_.get_implementation(), ec);
358 /// Start an asynchronous wait on the object handle.
360 * This function is be used to initiate an asynchronous wait against the
361 * object handle. It is an initiating function for an @ref
362 * asynchronous_operation, and always returns immediately.
364 * @param token The @ref completion_token that will be used to produce a
365 * completion handler, which will be called when the wait completes.
366 * Potential completion tokens include @ref use_future, @ref use_awaitable,
367 * @ref yield_context, or a function object with the correct completion
368 * signature. The function signature of the completion handler must be:
369 * @code void handler(
370 * const boost::system::error_code& error // Result of operation.
372 * Regardless of whether the asynchronous operation completes immediately or
373 * not, the completion handler will not be invoked from within this function.
374 * On immediate completion, invocation of the handler will be performed in a
375 * manner equivalent to using boost::asio::post().
377 * @par Completion Signature
378 * @code void(boost::system::error_code) @endcode
381 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
382 WaitToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
383 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitToken,
384 void (boost::system::error_code))
386 BOOST_ASIO_MOVE_ARG(WaitToken) token
387 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
389 return async_initiate<WaitToken, void (boost::system::error_code)>(
390 initiate_async_wait(this), token);
394 // Disallow copying and assignment.
395 basic_object_handle(const basic_object_handle&) BOOST_ASIO_DELETED;
396 basic_object_handle& operator=(const basic_object_handle&) BOOST_ASIO_DELETED;
398 class initiate_async_wait
401 typedef Executor executor_type;
403 explicit initiate_async_wait(basic_object_handle* self)
408 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
410 return self_->get_executor();
413 template <typename WaitHandler>
414 void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler) const
416 // If you get an error on the following line it means that your handler
417 // does not meet the documented type requirements for a WaitHandler.
418 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
420 detail::non_const_lvalue<WaitHandler> handler2(handler);
421 self_->impl_.get_service().async_wait(
422 self_->impl_.get_implementation(),
423 handler2.value, self_->impl_.get_executor());
427 basic_object_handle* self_;
430 boost::asio::detail::io_object_impl<
431 boost::asio::detail::win_object_handle_service, Executor> impl_;
434 } // namespace windows
438 #include <boost/asio/detail/pop_options.hpp>
440 #endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
441 // || defined(GENERATING_DOCUMENTATION)
443 #endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP