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