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

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