Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / asio / windows / basic_object_handle.hpp
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
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 <boost/asio/async_result.hpp>
25 #include <boost/asio/detail/io_object_impl.hpp>
26 #include <boost/asio/detail/throw_error.hpp>
27 #include <boost/asio/detail/win_object_handle_service.hpp>
28 #include <boost/asio/error.hpp>
29 #include <boost/asio/execution_context.hpp>
30 #include <boost/asio/executor.hpp>
31
32 #if defined(BOOST_ASIO_HAS_MOVE)
33 # include <utility>
34 #endif // defined(BOOST_ASIO_HAS_MOVE)
35
36 #include <boost/asio/detail/push_options.hpp>
37
38 namespace boost {
39 namespace asio {
40 namespace windows {
41
42 /// Provides object-oriented handle functionality.
43 /**
44  * The windows::basic_object_handle class provides asynchronous and blocking
45  * object-oriented handle functionality.
46  *
47  * @par Thread Safety
48  * @e Distinct @e objects: Safe.@n
49  * @e Shared @e objects: Unsafe.
50  */
51 template <typename Executor = executor>
52 class basic_object_handle
53 {
54 public:
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_(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       typename enable_if<
101         is_convertible<ExecutionContext&, execution_context&>::value,
102         basic_object_handle
103       >::type* = 0)
104     : impl_(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_(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       typename enable_if<
147         is_convertible<ExecutionContext&, execution_context&>::value
148       >::type* = 0)
149     : impl_(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 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
157   /// Move-construct an object handle from another.
158   /**
159    * This constructor moves an object handle from one object to another.
160    *
161    * @param other The other object handle object from which the move will
162    * occur.
163    *
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&)
166    * constructor.
167    */
168   basic_object_handle(basic_object_handle&& other)
169     : impl_(std::move(other.impl_))
170   {
171   }
172
173   /// Move-assign an object handle from another.
174   /**
175    * This assignment operator moves an object handle from one object to another.
176    *
177    * @param other The other object handle object from which the move will
178    * occur.
179    *
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&)
182    * constructor.
183    */
184   basic_object_handle& operator=(basic_object_handle&& other)
185   {
186     impl_ = std::move(other.impl_);
187     return *this;
188   }
189 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
190
191   /// Get the executor associated with the object.
192   executor_type get_executor() BOOST_ASIO_NOEXCEPT
193   {
194     return impl_.get_executor();
195   }
196
197   /// Get a reference to the lowest layer.
198   /**
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.
202    *
203    * @return A reference to the lowest layer in the stack of layers. Ownership
204    * is not transferred to the caller.
205    */
206   lowest_layer_type& lowest_layer()
207   {
208     return *this;
209   }
210
211   /// Get a const reference to the lowest layer.
212   /**
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.
216    *
217    * @return A const reference to the lowest layer in the stack of layers.
218    * Ownership is not transferred to the caller.
219    */
220   const lowest_layer_type& lowest_layer() const
221   {
222     return *this;
223   }
224
225   /// Assign an existing native handle to the handle.
226   /*
227    * This function opens the handle to hold an existing native handle.
228    *
229    * @param handle A native handle.
230    *
231    * @throws boost::system::system_error Thrown on failure.
232    */
233   void assign(const native_handle_type& handle)
234   {
235     boost::system::error_code ec;
236     impl_.get_service().assign(impl_.get_implementation(), handle, ec);
237     boost::asio::detail::throw_error(ec, "assign");
238   }
239
240   /// Assign an existing native handle to the handle.
241   /*
242    * This function opens the handle to hold an existing native handle.
243    *
244    * @param handle A native handle.
245    *
246    * @param ec Set to indicate what error occurred, if any.
247    */
248   BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
249       boost::system::error_code& ec)
250   {
251     impl_.get_service().assign(impl_.get_implementation(), handle, ec);
252     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
253   }
254
255   /// Determine whether the handle is open.
256   bool is_open() const
257   {
258     return impl_.get_service().is_open(impl_.get_implementation());
259   }
260
261   /// Close the handle.
262   /**
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.
266    *
267    * @throws boost::system::system_error Thrown on failure.
268    */
269   void close()
270   {
271     boost::system::error_code ec;
272     impl_.get_service().close(impl_.get_implementation(), ec);
273     boost::asio::detail::throw_error(ec, "close");
274   }
275
276   /// Close the handle.
277   /**
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.
281    *
282    * @param ec Set to indicate what error occurred, if any.
283    */
284   BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
285   {
286     impl_.get_service().close(impl_.get_implementation(), ec);
287     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
288   }
289
290   /// Get the native handle representation.
291   /**
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.
295    */
296   native_handle_type native_handle()
297   {
298     return impl_.get_service().native_handle(impl_.get_implementation());
299   }
300
301   /// Cancel all asynchronous operations associated with the handle.
302   /**
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.
306    *
307    * @throws boost::system::system_error Thrown on failure.
308    */
309   void cancel()
310   {
311     boost::system::error_code ec;
312     impl_.get_service().cancel(impl_.get_implementation(), ec);
313     boost::asio::detail::throw_error(ec, "cancel");
314   }
315
316   /// Cancel all asynchronous operations associated with the handle.
317   /**
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.
321    *
322    * @param ec Set to indicate what error occurred, if any.
323    */
324   BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
325   {
326     impl_.get_service().cancel(impl_.get_implementation(), ec);
327     BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
328   }
329
330   /// Perform a blocking wait on the object handle.
331   /**
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.
335    *
336    * @throws boost::system::system_error Thrown on failure.
337    */
338   void wait()
339   {
340     boost::system::error_code ec;
341     impl_.get_service().wait(impl_.get_implementation(), ec);
342     boost::asio::detail::throw_error(ec, "wait");
343   }
344
345   /// Perform a blocking wait on the object handle.
346   /**
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.
350    *
351    * @param ec Set to indicate what error occurred, if any.
352    */
353   void wait(boost::system::error_code& ec)
354   {
355     impl_.get_service().wait(impl_.get_implementation(), ec);
356   }
357
358   /// Start an asynchronous wait on the object handle.
359   /**
360    * This function is be used to initiate an asynchronous wait against the
361    * object handle. It always returns immediately.
362    *
363    * @param handler The handler to be called when the object handle is set to
364    * the signalled state. Copies will be made of the handler as required. The
365    * function signature of the handler must be:
366    * @code void handler(
367    *   const boost::system::error_code& error // Result of operation.
368    * ); @endcode
369    * Regardless of whether the asynchronous operation completes immediately or
370    * not, the handler will not be invoked from within this function. On
371    * immediate completion, invocation of the handler will be performed in a
372    * manner equivalent to using boost::asio::post().
373    */
374   template <
375       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
376         WaitHandler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
377   BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,
378       void (boost::system::error_code))
379   async_wait(
380       BOOST_ASIO_MOVE_ARG(WaitHandler) handler
381         BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
382   {
383     return async_initiate<WaitHandler, void (boost::system::error_code)>(
384         initiate_async_wait(this), handler);
385   }
386
387 private:
388   // Disallow copying and assignment.
389   basic_object_handle(const basic_object_handle&) BOOST_ASIO_DELETED;
390   basic_object_handle& operator=(const basic_object_handle&) BOOST_ASIO_DELETED;
391
392   class initiate_async_wait
393   {
394   public:
395     typedef Executor executor_type;
396
397     explicit initiate_async_wait(basic_object_handle* self)
398       : self_(self)
399     {
400     }
401
402     executor_type get_executor() const BOOST_ASIO_NOEXCEPT
403     {
404       return self_->get_executor();
405     }
406
407     template <typename WaitHandler>
408     void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler) const
409     {
410       // If you get an error on the following line it means that your handler
411       // does not meet the documented type requirements for a WaitHandler.
412       BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
413
414       detail::non_const_lvalue<WaitHandler> handler2(handler);
415       self_->impl_.get_service().async_wait(
416           self_->impl_.get_implementation(), handler2.value,
417           self_->impl_.get_implementation_executor());
418     }
419
420   private:
421     basic_object_handle* self_;
422   };
423
424   boost::asio::detail::io_object_impl<
425     boost::asio::detail::win_object_handle_service, Executor> impl_;
426 };
427
428 } // namespace windows
429 } // namespace asio
430 } // namespace boost
431
432 #include <boost/asio/detail/pop_options.hpp>
433
434 #endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
435        //   || defined(GENERATING_DOCUMENTATION)
436
437 #endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP