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