1//
2// windows/basic_object_handle.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 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
12#ifndef BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
13#define BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
14
15#if defined(_MSC_VER) && (_MSC_VER >= 1200)
16# pragma once
17#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18
19#include <boost/asio/detail/config.hpp>
20
21#if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \
22 || defined(GENERATING_DOCUMENTATION)
23
24#include <utility>
25#include <boost/asio/any_io_executor.hpp>
26#include <boost/asio/async_result.hpp>
27#include <boost/asio/detail/io_object_impl.hpp>
28#include <boost/asio/detail/throw_error.hpp>
29#include <boost/asio/detail/win_object_handle_service.hpp>
30#include <boost/asio/error.hpp>
31#include <boost/asio/execution_context.hpp>
32
33#include <boost/asio/detail/push_options.hpp>
34
35namespace boost {
36namespace asio {
37namespace windows {
38
39/// Provides object-oriented handle functionality.
40/**
41 * The windows::basic_object_handle class provides asynchronous and blocking
42 * object-oriented handle functionality.
43 *
44 * @par Thread Safety
45 * @e Distinct @e objects: Safe.@n
46 * @e Shared @e objects: Unsafe.
47 */
48template <typename Executor = any_io_executor>
49class basic_object_handle
50{
51private:
52 class initiate_async_wait;
53
54public:
55 /// The type of the executor associated with the object.
56 typedef Executor executor_type;
57
58 /// Rebinds the handle type to another executor.
59 template <typename Executor1>
60 struct rebind_executor
61 {
62 /// The handle type when rebound to the specified executor.
63 typedef basic_object_handle<Executor1> other;
64 };
65
66 /// The native representation of a handle.
67#if defined(GENERATING_DOCUMENTATION)
68 typedef implementation_defined native_handle_type;
69#else
70 typedef boost::asio::detail::win_object_handle_service::native_handle_type
71 native_handle_type;
72#endif
73
74 /// An object handle is always the lowest layer.
75 typedef basic_object_handle lowest_layer_type;
76
77 /// Construct an object handle without opening it.
78 /**
79 * This constructor creates an object handle without opening it.
80 *
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
83 * object handle.
84 */
85 explicit basic_object_handle(const executor_type& ex)
86 : impl_(0, ex)
87 {
88 }
89
90 /// Construct an object handle without opening it.
91 /**
92 * This constructor creates an object handle without opening it.
93 *
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.
97 */
98 template <typename ExecutionContext>
99 explicit basic_object_handle(ExecutionContext& context,
100 constraint_t<
101 is_convertible<ExecutionContext&, execution_context&>::value,
102 defaulted_constraint
103 > = defaulted_constraint())
104 : impl_(0, 0, context)
105 {
106 }
107
108 /// Construct an object handle on an existing native handle.
109 /**
110 * This constructor creates an object handle object to hold an existing native
111 * handle.
112 *
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
115 * object handle.
116 *
117 * @param native_handle The new underlying handle implementation.
118 *
119 * @throws boost::system::system_error Thrown on failure.
120 */
121 basic_object_handle(const executor_type& ex,
122 const native_handle_type& native_handle)
123 : impl_(0, ex)
124 {
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");
128 }
129
130 /// Construct an object handle on an existing native handle.
131 /**
132 * This constructor creates an object handle object to hold an existing native
133 * handle.
134 *
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.
138 *
139 * @param native_handle The new underlying handle implementation.
140 *
141 * @throws boost::system::system_error Thrown on failure.
142 */
143 template <typename ExecutionContext>
144 basic_object_handle(ExecutionContext& context,
145 const native_handle_type& native_handle,
146 constraint_t<
147 is_convertible<ExecutionContext&, execution_context&>::value
148 > = 0)
149 : impl_(0, 0, context)
150 {
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");
154 }
155
156 /// Move-construct an object handle from another.
157 /**
158 * This constructor moves an object handle from one object to another.
159 *
160 * @param other The other object handle object from which the move will
161 * occur.
162 *
163 * @note Following the move, the moved-from object is in the same state as if
164 * constructed using the @c basic_object_handle(const executor_type&)
165 * constructor.
166 */
167 basic_object_handle(basic_object_handle&& other)
168 : impl_(std::move(other.impl_))
169 {
170 }
171
172 /// Move-assign an object handle from another.
173 /**
174 * This assignment operator moves an object handle from one object to another.
175 *
176 * @param other The other object handle object from which the move will
177 * occur.
178 *
179 * @note Following the move, the moved-from object is in the same state as if
180 * constructed using the @c basic_object_handle(const executor_type&)
181 * constructor.
182 */
183 basic_object_handle& operator=(basic_object_handle&& other)
184 {
185 impl_ = std::move(other.impl_);
186 return *this;
187 }
188
189 // All handles have access to each other's implementations.
190 template <typename Executor1>
191 friend class basic_object_handle;
192
193 /// Move-construct an object handle from a handle of another executor type.
194 /**
195 * This constructor moves an object handle from one object to another.
196 *
197 * @param other The other object handle object from which the move will
198 * occur.
199 *
200 * @note Following the move, the moved-from object is in the same state as if
201 * constructed using the @c basic_object_handle(const executor_type&)
202 * constructor.
203 */
204 template<typename Executor1>
205 basic_object_handle(basic_object_handle<Executor1>&& other,
206 constraint_t<
207 is_convertible<Executor1, Executor>::value,
208 defaulted_constraint
209 > = defaulted_constraint())
210 : impl_(std::move(other.impl_))
211 {
212 }
213
214 /// Move-assign an object handle from a handle of another executor type.
215 /**
216 * This assignment operator moves an object handle from one object to another.
217 *
218 * @param other The other object handle object from which the move will
219 * occur.
220 *
221 * @note Following the move, the moved-from object is in the same state as if
222 * constructed using the @c basic_object_handle(const executor_type&)
223 * constructor.
224 */
225 template<typename Executor1>
226 constraint_t<
227 is_convertible<Executor1, Executor>::value,
228 basic_object_handle&
229 > operator=(basic_object_handle<Executor1>&& other)
230 {
231 impl_ = std::move(other.impl_);
232 return *this;
233 }
234
235 /// Get the executor associated with the object.
236 const executor_type& get_executor() noexcept
237 {
238 return impl_.get_executor();
239 }
240
241 /// Get a reference to the lowest layer.
242 /**
243 * This function returns a reference to the lowest layer in a stack of
244 * layers. Since an object handle cannot contain any further layers, it simply
245 * returns a reference to itself.
246 *
247 * @return A reference to the lowest layer in the stack of layers. Ownership
248 * is not transferred to the caller.
249 */
250 lowest_layer_type& lowest_layer()
251 {
252 return *this;
253 }
254
255 /// Get a const reference to the lowest layer.
256 /**
257 * This function returns a const reference to the lowest layer in a stack of
258 * layers. Since an object handle cannot contain any further layers, it simply
259 * returns a reference to itself.
260 *
261 * @return A const reference to the lowest layer in the stack of layers.
262 * Ownership is not transferred to the caller.
263 */
264 const lowest_layer_type& lowest_layer() const
265 {
266 return *this;
267 }
268
269 /// Assign an existing native handle to the handle.
270 /*
271 * This function opens the handle to hold an existing native handle.
272 *
273 * @param handle A native handle.
274 *
275 * @throws boost::system::system_error Thrown on failure.
276 */
277 void assign(const native_handle_type& handle)
278 {
279 boost::system::error_code ec;
280 impl_.get_service().assign(impl_.get_implementation(), handle, ec);
281 boost::asio::detail::throw_error(ec, "assign");
282 }
283
284 /// Assign an existing native handle to the handle.
285 /*
286 * This function opens the handle to hold an existing native handle.
287 *
288 * @param handle A native handle.
289 *
290 * @param ec Set to indicate what error occurred, if any.
291 */
292 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
293 boost::system::error_code& ec)
294 {
295 impl_.get_service().assign(impl_.get_implementation(), handle, ec);
296 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
297 }
298
299 /// Determine whether the handle is open.
300 bool is_open() const
301 {
302 return impl_.get_service().is_open(impl_.get_implementation());
303 }
304
305 /// Close the handle.
306 /**
307 * This function is used to close the handle. Any asynchronous read or write
308 * operations will be cancelled immediately, and will complete with the
309 * boost::asio::error::operation_aborted error.
310 *
311 * @throws boost::system::system_error Thrown on failure.
312 */
313 void close()
314 {
315 boost::system::error_code ec;
316 impl_.get_service().close(impl_.get_implementation(), ec);
317 boost::asio::detail::throw_error(ec, "close");
318 }
319
320 /// Close the handle.
321 /**
322 * This function is used to close the handle. Any asynchronous read or write
323 * operations will be cancelled immediately, and will complete with the
324 * boost::asio::error::operation_aborted error.
325 *
326 * @param ec Set to indicate what error occurred, if any.
327 */
328 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
329 {
330 impl_.get_service().close(impl_.get_implementation(), ec);
331 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
332 }
333
334 /// Get the native handle representation.
335 /**
336 * This function may be used to obtain the underlying representation of the
337 * handle. This is intended to allow access to native handle functionality
338 * that is not otherwise provided.
339 */
340 native_handle_type native_handle()
341 {
342 return impl_.get_service().native_handle(impl_.get_implementation());
343 }
344
345 /// Cancel all asynchronous operations associated with the handle.
346 /**
347 * This function causes all outstanding asynchronous read or write operations
348 * to finish immediately, and the handlers for cancelled operations will be
349 * passed the boost::asio::error::operation_aborted error.
350 *
351 * @throws boost::system::system_error Thrown on failure.
352 */
353 void cancel()
354 {
355 boost::system::error_code ec;
356 impl_.get_service().cancel(impl_.get_implementation(), ec);
357 boost::asio::detail::throw_error(ec, "cancel");
358 }
359
360 /// Cancel all asynchronous operations associated with the handle.
361 /**
362 * This function causes all outstanding asynchronous read or write operations
363 * to finish immediately, and the handlers for cancelled operations will be
364 * passed the boost::asio::error::operation_aborted error.
365 *
366 * @param ec Set to indicate what error occurred, if any.
367 */
368 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
369 {
370 impl_.get_service().cancel(impl_.get_implementation(), ec);
371 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
372 }
373
374 /// Perform a blocking wait on the object handle.
375 /**
376 * This function is used to wait for the object handle to be set to the
377 * signalled state. This function blocks and does not return until the object
378 * handle has been set to the signalled state.
379 *
380 * @throws boost::system::system_error Thrown on failure.
381 */
382 void wait()
383 {
384 boost::system::error_code ec;
385 impl_.get_service().wait(impl_.get_implementation(), ec);
386 boost::asio::detail::throw_error(ec, "wait");
387 }
388
389 /// Perform a blocking wait on the object handle.
390 /**
391 * This function is used to wait for the object handle to be set to the
392 * signalled state. This function blocks and does not return until the object
393 * handle has been set to the signalled state.
394 *
395 * @param ec Set to indicate what error occurred, if any.
396 */
397 void wait(boost::system::error_code& ec)
398 {
399 impl_.get_service().wait(impl_.get_implementation(), ec);
400 }
401
402 /// Start an asynchronous wait on the object handle.
403 /**
404 * This function is be used to initiate an asynchronous wait against the
405 * object handle. It is an initiating function for an @ref
406 * asynchronous_operation, and always returns immediately.
407 *
408 * @param token The @ref completion_token that will be used to produce a
409 * completion handler, which will be called when the wait completes.
410 * Potential completion tokens include @ref use_future, @ref use_awaitable,
411 * @ref yield_context, or a function object with the correct completion
412 * signature. The function signature of the completion handler must be:
413 * @code void handler(
414 * const boost::system::error_code& error // Result of operation.
415 * ); @endcode
416 * Regardless of whether the asynchronous operation completes immediately or
417 * not, the completion handler will not be invoked from within this function.
418 * On immediate completion, invocation of the handler will be performed in a
419 * manner equivalent to using boost::asio::post().
420 *
421 * @par Completion Signature
422 * @code void(boost::system::error_code) @endcode
423 */
424 template <
425 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
426 WaitToken = default_completion_token_t<executor_type>>
427 auto async_wait(
428 WaitToken&& token = default_completion_token_t<executor_type>())
429 -> decltype(
430 async_initiate<WaitToken, void (boost::system::error_code)>(
431 declval<initiate_async_wait>(), token))
432 {
433 return async_initiate<WaitToken, void (boost::system::error_code)>(
434 initiate_async_wait(this), token);
435 }
436
437private:
438 // Disallow copying and assignment.
439 basic_object_handle(const basic_object_handle&) = delete;
440 basic_object_handle& operator=(const basic_object_handle&) = delete;
441
442 class initiate_async_wait
443 {
444 public:
445 typedef Executor executor_type;
446
447 explicit initiate_async_wait(basic_object_handle* self)
448 : self_(self)
449 {
450 }
451
452 const executor_type& get_executor() const noexcept
453 {
454 return self_->get_executor();
455 }
456
457 template <typename WaitHandler>
458 void operator()(WaitHandler&& handler) const
459 {
460 // If you get an error on the following line it means that your handler
461 // does not meet the documented type requirements for a WaitHandler.
462 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
463
464 detail::non_const_lvalue<WaitHandler> handler2(handler);
465 self_->impl_.get_service().async_wait(
466 self_->impl_.get_implementation(),
467 handler2.value, self_->impl_.get_executor());
468 }
469
470 private:
471 basic_object_handle* self_;
472 };
473
474 boost::asio::detail::io_object_impl<
475 boost::asio::detail::win_object_handle_service, Executor> impl_;
476};
477
478} // namespace windows
479} // namespace asio
480} // namespace boost
481
482#include <boost/asio/detail/pop_options.hpp>
483
484#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
485 // || defined(GENERATING_DOCUMENTATION)
486
487#endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
488

source code of boost/libs/asio/include/boost/asio/windows/basic_object_handle.hpp