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 ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP 13 #define 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 "asio/detail/config.hpp" 20 21 #if defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE) \ 22 || defined(GENERATING_DOCUMENTATION) 23 24 #include "asio/async_result.hpp" 25 #include "asio/detail/io_object_impl.hpp" 26 #include "asio/detail/throw_error.hpp" 27 #include "asio/detail/win_object_handle_service.hpp" 28 #include "asio/error.hpp" 29 #include "asio/execution_context.hpp" 30 #include "asio/executor.hpp" 31 32 #if defined(ASIO_HAS_MOVE) 33 # include <utility> 34 #endif // defined(ASIO_HAS_MOVE) 35 36 #include "asio/detail/push_options.hpp" 37 38 namespace asio { 39 namespace windows { 40 41 /// Provides object-oriented handle functionality. 42 /** 43 * The windows::basic_object_handle class provides asynchronous and blocking 44 * object-oriented handle functionality. 45 * 46 * @par Thread Safety 47 * @e Distinct @e objects: Safe.@n 48 * @e Shared @e objects: Unsafe. 49 */ 50 template <typename Executor = executor> 51 class basic_object_handle 52 { 53 public: 54 /// The type of the executor associated with the object. 55 typedef Executor executor_type; 56 57 /// The native representation of a handle. 58 #if defined(GENERATING_DOCUMENTATION) 59 typedef implementation_defined native_handle_type; 60 #else 61 typedef asio::detail::win_object_handle_service::native_handle_type 62 native_handle_type; 63 #endif 64 65 /// An object handle is always the lowest layer. 66 typedef basic_object_handle lowest_layer_type; 67 68 /// Construct an object handle without opening it. 69 /** 70 * This constructor creates an object handle without opening it. 71 * 72 * @param ex The I/O executor that the object handle will use, by default, to 73 * dispatch handlers for any asynchronous operations performed on the 74 * object handle. 75 */ basic_object_handle(const executor_type & ex)76 explicit basic_object_handle(const executor_type& ex) 77 : impl_(ex) 78 { 79 } 80 81 /// Construct an object handle without opening it. 82 /** 83 * This constructor creates an object handle without opening it. 84 * 85 * @param context An execution context which provides the I/O executor that 86 * the object handle will use, by default, to dispatch handlers for any 87 * asynchronous operations performed on the object handle. 88 */ 89 template <typename ExecutionContext> basic_object_handle(ExecutionContext & context,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value,basic_object_handle>::type * =0)90 explicit basic_object_handle(ExecutionContext& context, 91 typename enable_if< 92 is_convertible<ExecutionContext&, execution_context&>::value, 93 basic_object_handle 94 >::type* = 0) 95 : impl_(context) 96 { 97 } 98 99 /// Construct an object handle on an existing native handle. 100 /** 101 * This constructor creates an object handle object to hold an existing native 102 * handle. 103 * 104 * @param ex The I/O executor that the object handle will use, by default, to 105 * dispatch handlers for any asynchronous operations performed on the 106 * object handle. 107 * 108 * @param native_handle The new underlying handle implementation. 109 * 110 * @throws asio::system_error Thrown on failure. 111 */ basic_object_handle(const executor_type & ex,const native_handle_type & native_handle)112 basic_object_handle(const executor_type& ex, 113 const native_handle_type& native_handle) 114 : impl_(ex) 115 { 116 asio::error_code ec; 117 impl_.get_service().assign(impl_.get_implementation(), native_handle, ec); 118 asio::detail::throw_error(ec, "assign"); 119 } 120 121 /// Construct an object handle on an existing native handle. 122 /** 123 * This constructor creates an object handle object to hold an existing native 124 * handle. 125 * 126 * @param context An execution context which provides the I/O executor that 127 * the object handle will use, by default, to dispatch handlers for any 128 * asynchronous operations performed on the object handle. 129 * 130 * @param native_handle The new underlying handle implementation. 131 * 132 * @throws asio::system_error Thrown on failure. 133 */ 134 template <typename ExecutionContext> basic_object_handle(ExecutionContext & context,const native_handle_type & native_handle,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)135 basic_object_handle(ExecutionContext& context, 136 const native_handle_type& native_handle, 137 typename enable_if< 138 is_convertible<ExecutionContext&, execution_context&>::value 139 >::type* = 0) 140 : impl_(context) 141 { 142 asio::error_code ec; 143 impl_.get_service().assign(impl_.get_implementation(), native_handle, ec); 144 asio::detail::throw_error(ec, "assign"); 145 } 146 147 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 148 /// Move-construct an object handle from another. 149 /** 150 * This constructor moves an object handle from one object to another. 151 * 152 * @param other The other object handle object from which the move will 153 * occur. 154 * 155 * @note Following the move, the moved-from object is in the same state as if 156 * constructed using the @c basic_object_handle(const executor_type&) 157 * constructor. 158 */ basic_object_handle(basic_object_handle && other)159 basic_object_handle(basic_object_handle&& other) 160 : impl_(std::move(other.impl_)) 161 { 162 } 163 164 /// Move-assign an object handle from another. 165 /** 166 * This assignment operator moves an object handle from one object to another. 167 * 168 * @param other The other object handle object from which the move will 169 * occur. 170 * 171 * @note Following the move, the moved-from object is in the same state as if 172 * constructed using the @c basic_object_handle(const executor_type&) 173 * constructor. 174 */ operator =(basic_object_handle && other)175 basic_object_handle& operator=(basic_object_handle&& other) 176 { 177 impl_ = std::move(other.impl_); 178 return *this; 179 } 180 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 181 182 /// Get the executor associated with the object. get_executor()183 executor_type get_executor() ASIO_NOEXCEPT 184 { 185 return impl_.get_executor(); 186 } 187 188 /// Get a reference to the lowest layer. 189 /** 190 * This function returns a reference to the lowest layer in a stack of 191 * layers. Since an object handle cannot contain any further layers, it simply 192 * returns a reference to itself. 193 * 194 * @return A reference to the lowest layer in the stack of layers. Ownership 195 * is not transferred to the caller. 196 */ lowest_layer()197 lowest_layer_type& lowest_layer() 198 { 199 return *this; 200 } 201 202 /// Get a const reference to the lowest layer. 203 /** 204 * This function returns a const reference to the lowest layer in a stack of 205 * layers. Since an object handle cannot contain any further layers, it simply 206 * returns a reference to itself. 207 * 208 * @return A const reference to the lowest layer in the stack of layers. 209 * Ownership is not transferred to the caller. 210 */ lowest_layer() const211 const lowest_layer_type& lowest_layer() const 212 { 213 return *this; 214 } 215 216 /// Assign an existing native handle to the handle. 217 /* 218 * This function opens the handle to hold an existing native handle. 219 * 220 * @param handle A native handle. 221 * 222 * @throws asio::system_error Thrown on failure. 223 */ assign(const native_handle_type & handle)224 void assign(const native_handle_type& handle) 225 { 226 asio::error_code ec; 227 impl_.get_service().assign(impl_.get_implementation(), handle, ec); 228 asio::detail::throw_error(ec, "assign"); 229 } 230 231 /// Assign an existing native handle to the handle. 232 /* 233 * This function opens the handle to hold an existing native handle. 234 * 235 * @param handle A native handle. 236 * 237 * @param ec Set to indicate what error occurred, if any. 238 */ assign(const native_handle_type & handle,asio::error_code & ec)239 ASIO_SYNC_OP_VOID assign(const native_handle_type& handle, 240 asio::error_code& ec) 241 { 242 impl_.get_service().assign(impl_.get_implementation(), handle, ec); 243 ASIO_SYNC_OP_VOID_RETURN(ec); 244 } 245 246 /// Determine whether the handle is open. is_open() const247 bool is_open() const 248 { 249 return impl_.get_service().is_open(impl_.get_implementation()); 250 } 251 252 /// Close the handle. 253 /** 254 * This function is used to close the handle. Any asynchronous read or write 255 * operations will be cancelled immediately, and will complete with the 256 * asio::error::operation_aborted error. 257 * 258 * @throws asio::system_error Thrown on failure. 259 */ close()260 void close() 261 { 262 asio::error_code ec; 263 impl_.get_service().close(impl_.get_implementation(), ec); 264 asio::detail::throw_error(ec, "close"); 265 } 266 267 /// Close the handle. 268 /** 269 * This function is used to close the handle. Any asynchronous read or write 270 * operations will be cancelled immediately, and will complete with the 271 * asio::error::operation_aborted error. 272 * 273 * @param ec Set to indicate what error occurred, if any. 274 */ close(asio::error_code & ec)275 ASIO_SYNC_OP_VOID close(asio::error_code& ec) 276 { 277 impl_.get_service().close(impl_.get_implementation(), ec); 278 ASIO_SYNC_OP_VOID_RETURN(ec); 279 } 280 281 /// Get the native handle representation. 282 /** 283 * This function may be used to obtain the underlying representation of the 284 * handle. This is intended to allow access to native handle functionality 285 * that is not otherwise provided. 286 */ native_handle()287 native_handle_type native_handle() 288 { 289 return impl_.get_service().native_handle(impl_.get_implementation()); 290 } 291 292 /// Cancel all asynchronous operations associated with the handle. 293 /** 294 * This function causes all outstanding asynchronous read or write operations 295 * to finish immediately, and the handlers for cancelled operations will be 296 * passed the asio::error::operation_aborted error. 297 * 298 * @throws asio::system_error Thrown on failure. 299 */ cancel()300 void cancel() 301 { 302 asio::error_code ec; 303 impl_.get_service().cancel(impl_.get_implementation(), ec); 304 asio::detail::throw_error(ec, "cancel"); 305 } 306 307 /// Cancel all asynchronous operations associated with the handle. 308 /** 309 * This function causes all outstanding asynchronous read or write operations 310 * to finish immediately, and the handlers for cancelled operations will be 311 * passed the asio::error::operation_aborted error. 312 * 313 * @param ec Set to indicate what error occurred, if any. 314 */ cancel(asio::error_code & ec)315 ASIO_SYNC_OP_VOID cancel(asio::error_code& ec) 316 { 317 impl_.get_service().cancel(impl_.get_implementation(), ec); 318 ASIO_SYNC_OP_VOID_RETURN(ec); 319 } 320 321 /// Perform a blocking wait on the object handle. 322 /** 323 * This function is used to wait for the object handle to be set to the 324 * signalled state. This function blocks and does not return until the object 325 * handle has been set to the signalled state. 326 * 327 * @throws asio::system_error Thrown on failure. 328 */ wait()329 void wait() 330 { 331 asio::error_code ec; 332 impl_.get_service().wait(impl_.get_implementation(), ec); 333 asio::detail::throw_error(ec, "wait"); 334 } 335 336 /// Perform a blocking wait on the object handle. 337 /** 338 * This function is used to wait for the object handle to be set to the 339 * signalled state. This function blocks and does not return until the object 340 * handle has been set to the signalled state. 341 * 342 * @param ec Set to indicate what error occurred, if any. 343 */ wait(asio::error_code & ec)344 void wait(asio::error_code& ec) 345 { 346 impl_.get_service().wait(impl_.get_implementation(), ec); 347 } 348 349 /// Start an asynchronous wait on the object handle. 350 /** 351 * This function is be used to initiate an asynchronous wait against the 352 * object handle. It always returns immediately. 353 * 354 * @param handler The handler to be called when the object handle is set to 355 * the signalled state. Copies will be made of the handler as required. The 356 * function signature of the handler must be: 357 * @code void handler( 358 * const asio::error_code& error // Result of operation. 359 * ); @endcode 360 * Regardless of whether the asynchronous operation completes immediately or 361 * not, the handler will not be invoked from within this function. On 362 * immediate completion, invocation of the handler will be performed in a 363 * manner equivalent to using asio::post(). 364 */ 365 template <typename WaitHandler> ASIO_INITFN_RESULT_TYPE(WaitHandler,void (asio::error_code))366 ASIO_INITFN_RESULT_TYPE(WaitHandler, 367 void (asio::error_code)) 368 async_wait(ASIO_MOVE_ARG(WaitHandler) handler) 369 { 370 asio::async_completion<WaitHandler, 371 void (asio::error_code)> init(handler); 372 373 impl_.get_service().async_wait(impl_.get_implementation(), 374 init.completion_handler, impl_.get_implementation_executor()); 375 376 return init.result.get(); 377 } 378 379 private: 380 // Disallow copying and assignment. 381 basic_object_handle(const basic_object_handle&) ASIO_DELETED; 382 basic_object_handle& operator=(const basic_object_handle&) ASIO_DELETED; 383 384 asio::detail::io_object_impl< 385 asio::detail::win_object_handle_service, Executor> impl_; 386 }; 387 388 } // namespace windows 389 } // namespace asio 390 391 #include "asio/detail/pop_options.hpp" 392 393 #endif // defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE) 394 // || defined(GENERATING_DOCUMENTATION) 395 396 #endif // ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP 397