|
||||
File indexing completed on 2025-01-18 09:29:03
0001 // 0002 // windows/basic_object_handle.hpp 0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0004 // 0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) 0006 // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) 0007 // 0008 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0010 // 0011 0012 #ifndef BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP 0013 #define BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP 0014 0015 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 0016 # pragma once 0017 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 0018 0019 #include <boost/asio/detail/config.hpp> 0020 0021 #if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \ 0022 || defined(GENERATING_DOCUMENTATION) 0023 0024 #include <utility> 0025 #include <boost/asio/any_io_executor.hpp> 0026 #include <boost/asio/async_result.hpp> 0027 #include <boost/asio/detail/io_object_impl.hpp> 0028 #include <boost/asio/detail/throw_error.hpp> 0029 #include <boost/asio/detail/win_object_handle_service.hpp> 0030 #include <boost/asio/error.hpp> 0031 #include <boost/asio/execution_context.hpp> 0032 0033 #include <boost/asio/detail/push_options.hpp> 0034 0035 namespace boost { 0036 namespace asio { 0037 namespace windows { 0038 0039 /// Provides object-oriented handle functionality. 0040 /** 0041 * The windows::basic_object_handle class provides asynchronous and blocking 0042 * object-oriented handle functionality. 0043 * 0044 * @par Thread Safety 0045 * @e Distinct @e objects: Safe.@n 0046 * @e Shared @e objects: Unsafe. 0047 */ 0048 template <typename Executor = any_io_executor> 0049 class basic_object_handle 0050 { 0051 private: 0052 class initiate_async_wait; 0053 0054 public: 0055 /// The type of the executor associated with the object. 0056 typedef Executor executor_type; 0057 0058 /// Rebinds the handle type to another executor. 0059 template <typename Executor1> 0060 struct rebind_executor 0061 { 0062 /// The handle type when rebound to the specified executor. 0063 typedef basic_object_handle<Executor1> other; 0064 }; 0065 0066 /// The native representation of a handle. 0067 #if defined(GENERATING_DOCUMENTATION) 0068 typedef implementation_defined native_handle_type; 0069 #else 0070 typedef boost::asio::detail::win_object_handle_service::native_handle_type 0071 native_handle_type; 0072 #endif 0073 0074 /// An object handle is always the lowest layer. 0075 typedef basic_object_handle lowest_layer_type; 0076 0077 /// Construct an object handle without opening it. 0078 /** 0079 * This constructor creates an object handle without opening it. 0080 * 0081 * @param ex The I/O executor that the object handle will use, by default, to 0082 * dispatch handlers for any asynchronous operations performed on the 0083 * object handle. 0084 */ 0085 explicit basic_object_handle(const executor_type& ex) 0086 : impl_(0, ex) 0087 { 0088 } 0089 0090 /// Construct an object handle without opening it. 0091 /** 0092 * This constructor creates an object handle without opening it. 0093 * 0094 * @param context An execution context which provides the I/O executor that 0095 * the object handle will use, by default, to dispatch handlers for any 0096 * asynchronous operations performed on the object handle. 0097 */ 0098 template <typename ExecutionContext> 0099 explicit basic_object_handle(ExecutionContext& context, 0100 constraint_t< 0101 is_convertible<ExecutionContext&, execution_context&>::value, 0102 defaulted_constraint 0103 > = defaulted_constraint()) 0104 : impl_(0, 0, context) 0105 { 0106 } 0107 0108 /// Construct an object handle on an existing native handle. 0109 /** 0110 * This constructor creates an object handle object to hold an existing native 0111 * handle. 0112 * 0113 * @param ex The I/O executor that the object handle will use, by default, to 0114 * dispatch handlers for any asynchronous operations performed on the 0115 * object handle. 0116 * 0117 * @param native_handle The new underlying handle implementation. 0118 * 0119 * @throws boost::system::system_error Thrown on failure. 0120 */ 0121 basic_object_handle(const executor_type& ex, 0122 const native_handle_type& native_handle) 0123 : impl_(0, ex) 0124 { 0125 boost::system::error_code ec; 0126 impl_.get_service().assign(impl_.get_implementation(), native_handle, ec); 0127 boost::asio::detail::throw_error(ec, "assign"); 0128 } 0129 0130 /// Construct an object handle on an existing native handle. 0131 /** 0132 * This constructor creates an object handle object to hold an existing native 0133 * handle. 0134 * 0135 * @param context An execution context which provides the I/O executor that 0136 * the object handle will use, by default, to dispatch handlers for any 0137 * asynchronous operations performed on the object handle. 0138 * 0139 * @param native_handle The new underlying handle implementation. 0140 * 0141 * @throws boost::system::system_error Thrown on failure. 0142 */ 0143 template <typename ExecutionContext> 0144 basic_object_handle(ExecutionContext& context, 0145 const native_handle_type& native_handle, 0146 constraint_t< 0147 is_convertible<ExecutionContext&, execution_context&>::value 0148 > = 0) 0149 : impl_(0, 0, context) 0150 { 0151 boost::system::error_code ec; 0152 impl_.get_service().assign(impl_.get_implementation(), native_handle, ec); 0153 boost::asio::detail::throw_error(ec, "assign"); 0154 } 0155 0156 /// Move-construct an object handle from another. 0157 /** 0158 * This constructor moves an object handle from one object to another. 0159 * 0160 * @param other The other object handle object from which the move will 0161 * occur. 0162 * 0163 * @note Following the move, the moved-from object is in the same state as if 0164 * constructed using the @c basic_object_handle(const executor_type&) 0165 * constructor. 0166 */ 0167 basic_object_handle(basic_object_handle&& other) 0168 : impl_(std::move(other.impl_)) 0169 { 0170 } 0171 0172 /// Move-assign an object handle from another. 0173 /** 0174 * This assignment operator moves an object handle from one object to another. 0175 * 0176 * @param other The other object handle object from which the move will 0177 * occur. 0178 * 0179 * @note Following the move, the moved-from object is in the same state as if 0180 * constructed using the @c basic_object_handle(const executor_type&) 0181 * constructor. 0182 */ 0183 basic_object_handle& operator=(basic_object_handle&& other) 0184 { 0185 impl_ = std::move(other.impl_); 0186 return *this; 0187 } 0188 0189 // All handles have access to each other's implementations. 0190 template <typename Executor1> 0191 friend class basic_object_handle; 0192 0193 /// Move-construct an object handle from a handle of another executor type. 0194 /** 0195 * This constructor moves an object handle from one object to another. 0196 * 0197 * @param other The other object handle object from which the move will 0198 * occur. 0199 * 0200 * @note Following the move, the moved-from object is in the same state as if 0201 * constructed using the @c basic_object_handle(const executor_type&) 0202 * constructor. 0203 */ 0204 template<typename Executor1> 0205 basic_object_handle(basic_object_handle<Executor1>&& other, 0206 constraint_t< 0207 is_convertible<Executor1, Executor>::value, 0208 defaulted_constraint 0209 > = defaulted_constraint()) 0210 : impl_(std::move(other.impl_)) 0211 { 0212 } 0213 0214 /// Move-assign an object handle from a handle of another executor type. 0215 /** 0216 * This assignment operator moves an object handle from one object to another. 0217 * 0218 * @param other The other object handle object from which the move will 0219 * occur. 0220 * 0221 * @note Following the move, the moved-from object is in the same state as if 0222 * constructed using the @c basic_object_handle(const executor_type&) 0223 * constructor. 0224 */ 0225 template<typename Executor1> 0226 constraint_t< 0227 is_convertible<Executor1, Executor>::value, 0228 basic_object_handle& 0229 > operator=(basic_object_handle<Executor1>&& other) 0230 { 0231 impl_ = std::move(other.impl_); 0232 return *this; 0233 } 0234 0235 /// Get the executor associated with the object. 0236 const executor_type& get_executor() noexcept 0237 { 0238 return impl_.get_executor(); 0239 } 0240 0241 /// Get a reference to the lowest layer. 0242 /** 0243 * This function returns a reference to the lowest layer in a stack of 0244 * layers. Since an object handle cannot contain any further layers, it simply 0245 * returns a reference to itself. 0246 * 0247 * @return A reference to the lowest layer in the stack of layers. Ownership 0248 * is not transferred to the caller. 0249 */ 0250 lowest_layer_type& lowest_layer() 0251 { 0252 return *this; 0253 } 0254 0255 /// Get a const reference to the lowest layer. 0256 /** 0257 * This function returns a const reference to the lowest layer in a stack of 0258 * layers. Since an object handle cannot contain any further layers, it simply 0259 * returns a reference to itself. 0260 * 0261 * @return A const reference to the lowest layer in the stack of layers. 0262 * Ownership is not transferred to the caller. 0263 */ 0264 const lowest_layer_type& lowest_layer() const 0265 { 0266 return *this; 0267 } 0268 0269 /// Assign an existing native handle to the handle. 0270 /* 0271 * This function opens the handle to hold an existing native handle. 0272 * 0273 * @param handle A native handle. 0274 * 0275 * @throws boost::system::system_error Thrown on failure. 0276 */ 0277 void assign(const native_handle_type& handle) 0278 { 0279 boost::system::error_code ec; 0280 impl_.get_service().assign(impl_.get_implementation(), handle, ec); 0281 boost::asio::detail::throw_error(ec, "assign"); 0282 } 0283 0284 /// Assign an existing native handle to the handle. 0285 /* 0286 * This function opens the handle to hold an existing native handle. 0287 * 0288 * @param handle A native handle. 0289 * 0290 * @param ec Set to indicate what error occurred, if any. 0291 */ 0292 BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle, 0293 boost::system::error_code& ec) 0294 { 0295 impl_.get_service().assign(impl_.get_implementation(), handle, ec); 0296 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0297 } 0298 0299 /// Determine whether the handle is open. 0300 bool is_open() const 0301 { 0302 return impl_.get_service().is_open(impl_.get_implementation()); 0303 } 0304 0305 /// Close the handle. 0306 /** 0307 * This function is used to close the handle. Any asynchronous read or write 0308 * operations will be cancelled immediately, and will complete with the 0309 * boost::asio::error::operation_aborted error. 0310 * 0311 * @throws boost::system::system_error Thrown on failure. 0312 */ 0313 void close() 0314 { 0315 boost::system::error_code ec; 0316 impl_.get_service().close(impl_.get_implementation(), ec); 0317 boost::asio::detail::throw_error(ec, "close"); 0318 } 0319 0320 /// Close the handle. 0321 /** 0322 * This function is used to close the handle. Any asynchronous read or write 0323 * operations will be cancelled immediately, and will complete with the 0324 * boost::asio::error::operation_aborted error. 0325 * 0326 * @param ec Set to indicate what error occurred, if any. 0327 */ 0328 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 0329 { 0330 impl_.get_service().close(impl_.get_implementation(), ec); 0331 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0332 } 0333 0334 /// Get the native handle representation. 0335 /** 0336 * This function may be used to obtain the underlying representation of the 0337 * handle. This is intended to allow access to native handle functionality 0338 * that is not otherwise provided. 0339 */ 0340 native_handle_type native_handle() 0341 { 0342 return impl_.get_service().native_handle(impl_.get_implementation()); 0343 } 0344 0345 /// Cancel all asynchronous operations associated with the handle. 0346 /** 0347 * This function causes all outstanding asynchronous read or write operations 0348 * to finish immediately, and the handlers for cancelled operations will be 0349 * passed the boost::asio::error::operation_aborted error. 0350 * 0351 * @throws boost::system::system_error Thrown on failure. 0352 */ 0353 void cancel() 0354 { 0355 boost::system::error_code ec; 0356 impl_.get_service().cancel(impl_.get_implementation(), ec); 0357 boost::asio::detail::throw_error(ec, "cancel"); 0358 } 0359 0360 /// Cancel all asynchronous operations associated with the handle. 0361 /** 0362 * This function causes all outstanding asynchronous read or write operations 0363 * to finish immediately, and the handlers for cancelled operations will be 0364 * passed the boost::asio::error::operation_aborted error. 0365 * 0366 * @param ec Set to indicate what error occurred, if any. 0367 */ 0368 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) 0369 { 0370 impl_.get_service().cancel(impl_.get_implementation(), ec); 0371 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 0372 } 0373 0374 /// Perform a blocking wait on the object handle. 0375 /** 0376 * This function is used to wait for the object handle to be set to the 0377 * signalled state. This function blocks and does not return until the object 0378 * handle has been set to the signalled state. 0379 * 0380 * @throws boost::system::system_error Thrown on failure. 0381 */ 0382 void wait() 0383 { 0384 boost::system::error_code ec; 0385 impl_.get_service().wait(impl_.get_implementation(), ec); 0386 boost::asio::detail::throw_error(ec, "wait"); 0387 } 0388 0389 /// Perform a blocking wait on the object handle. 0390 /** 0391 * This function is used to wait for the object handle to be set to the 0392 * signalled state. This function blocks and does not return until the object 0393 * handle has been set to the signalled state. 0394 * 0395 * @param ec Set to indicate what error occurred, if any. 0396 */ 0397 void wait(boost::system::error_code& ec) 0398 { 0399 impl_.get_service().wait(impl_.get_implementation(), ec); 0400 } 0401 0402 /// Start an asynchronous wait on the object handle. 0403 /** 0404 * This function is be used to initiate an asynchronous wait against the 0405 * object handle. It is an initiating function for an @ref 0406 * asynchronous_operation, and always returns immediately. 0407 * 0408 * @param token The @ref completion_token that will be used to produce a 0409 * completion handler, which will be called when the wait completes. 0410 * Potential completion tokens include @ref use_future, @ref use_awaitable, 0411 * @ref yield_context, or a function object with the correct completion 0412 * signature. The function signature of the completion handler must be: 0413 * @code void handler( 0414 * const boost::system::error_code& error // Result of operation. 0415 * ); @endcode 0416 * Regardless of whether the asynchronous operation completes immediately or 0417 * not, the completion handler will not be invoked from within this function. 0418 * On immediate completion, invocation of the handler will be performed in a 0419 * manner equivalent to using boost::asio::post(). 0420 * 0421 * @par Completion Signature 0422 * @code void(boost::system::error_code) @endcode 0423 */ 0424 template < 0425 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code)) 0426 WaitToken = default_completion_token_t<executor_type>> 0427 auto async_wait( 0428 WaitToken&& token = default_completion_token_t<executor_type>()) 0429 -> decltype( 0430 async_initiate<WaitToken, void (boost::system::error_code)>( 0431 declval<initiate_async_wait>(), token)) 0432 { 0433 return async_initiate<WaitToken, void (boost::system::error_code)>( 0434 initiate_async_wait(this), token); 0435 } 0436 0437 private: 0438 // Disallow copying and assignment. 0439 basic_object_handle(const basic_object_handle&) = delete; 0440 basic_object_handle& operator=(const basic_object_handle&) = delete; 0441 0442 class initiate_async_wait 0443 { 0444 public: 0445 typedef Executor executor_type; 0446 0447 explicit initiate_async_wait(basic_object_handle* self) 0448 : self_(self) 0449 { 0450 } 0451 0452 const executor_type& get_executor() const noexcept 0453 { 0454 return self_->get_executor(); 0455 } 0456 0457 template <typename WaitHandler> 0458 void operator()(WaitHandler&& handler) const 0459 { 0460 // If you get an error on the following line it means that your handler 0461 // does not meet the documented type requirements for a WaitHandler. 0462 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 0463 0464 detail::non_const_lvalue<WaitHandler> handler2(handler); 0465 self_->impl_.get_service().async_wait( 0466 self_->impl_.get_implementation(), 0467 handler2.value, self_->impl_.get_executor()); 0468 } 0469 0470 private: 0471 basic_object_handle* self_; 0472 }; 0473 0474 boost::asio::detail::io_object_impl< 0475 boost::asio::detail::win_object_handle_service, Executor> impl_; 0476 }; 0477 0478 } // namespace windows 0479 } // namespace asio 0480 } // namespace boost 0481 0482 #include <boost/asio/detail/pop_options.hpp> 0483 0484 #endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) 0485 // || defined(GENERATING_DOCUMENTATION) 0486 0487 #endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |