|
||||
File indexing completed on 2025-01-18 09:29:03
0001 // 0002 // windows/basic_random_access_handle.hpp 0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0004 // 0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) 0006 // 0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0009 // 0010 0011 #ifndef BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP 0012 #define BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP 0013 0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 0015 # pragma once 0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 0017 0018 #include <boost/asio/detail/config.hpp> 0019 #include <boost/asio/windows/basic_overlapped_handle.hpp> 0020 0021 #if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ 0022 || defined(GENERATING_DOCUMENTATION) 0023 0024 #include <boost/asio/detail/push_options.hpp> 0025 0026 namespace boost { 0027 namespace asio { 0028 namespace windows { 0029 0030 /// Provides random-access handle functionality. 0031 /** 0032 * The windows::basic_random_access_handle class provides asynchronous and 0033 * blocking random-access handle functionality. 0034 * 0035 * @par Thread Safety 0036 * @e Distinct @e objects: Safe.@n 0037 * @e Shared @e objects: Unsafe. 0038 */ 0039 template <typename Executor = any_io_executor> 0040 class basic_random_access_handle 0041 : public basic_overlapped_handle<Executor> 0042 { 0043 private: 0044 class initiate_async_write_some_at; 0045 class initiate_async_read_some_at; 0046 0047 public: 0048 /// The type of the executor associated with the object. 0049 typedef Executor executor_type; 0050 0051 /// Rebinds the handle type to another executor. 0052 template <typename Executor1> 0053 struct rebind_executor 0054 { 0055 /// The handle type when rebound to the specified executor. 0056 typedef basic_random_access_handle<Executor1> other; 0057 }; 0058 0059 /// The native representation of a handle. 0060 #if defined(GENERATING_DOCUMENTATION) 0061 typedef implementation_defined native_handle_type; 0062 #else 0063 typedef boost::asio::detail::win_iocp_handle_service::native_handle_type 0064 native_handle_type; 0065 #endif 0066 0067 /// Construct a random-access handle without opening it. 0068 /** 0069 * This constructor creates a random-access handle without opening it. 0070 * 0071 * @param ex The I/O executor that the random-access handle will use, by 0072 * default, to dispatch handlers for any asynchronous operations performed on 0073 * the random-access handle. 0074 */ 0075 explicit basic_random_access_handle(const executor_type& ex) 0076 : basic_overlapped_handle<Executor>(ex) 0077 { 0078 } 0079 0080 /// Construct a random-access handle without opening it. 0081 /** 0082 * This constructor creates a random-access handle without opening it. The 0083 * handle needs to be opened or assigned before data can be written to or read 0084 * from it. 0085 * 0086 * @param context An execution context which provides the I/O executor that 0087 * the random-access handle will use, by default, to dispatch handlers for any 0088 * asynchronous operations performed on the random-access handle. 0089 */ 0090 template <typename ExecutionContext> 0091 explicit basic_random_access_handle(ExecutionContext& context, 0092 constraint_t< 0093 is_convertible<ExecutionContext&, execution_context&>::value, 0094 defaulted_constraint 0095 > = defaulted_constraint()) 0096 : basic_overlapped_handle<Executor>(context) 0097 { 0098 } 0099 0100 /// Construct a random-access handle on an existing native handle. 0101 /** 0102 * This constructor creates a random-access handle object to hold an existing 0103 * native handle. 0104 * 0105 * @param ex The I/O executor that the random-access handle will use, by 0106 * default, to dispatch handlers for any asynchronous operations performed on 0107 * the random-access handle. 0108 * 0109 * @param handle The new underlying handle implementation. 0110 * 0111 * @throws boost::system::system_error Thrown on failure. 0112 */ 0113 basic_random_access_handle(const executor_type& ex, 0114 const native_handle_type& handle) 0115 : basic_overlapped_handle<Executor>(ex, handle) 0116 { 0117 } 0118 0119 /// Construct a random-access handle on an existing native handle. 0120 /** 0121 * This constructor creates a random-access handle object to hold an existing 0122 * native handle. 0123 * 0124 * @param context An execution context which provides the I/O executor that 0125 * the random-access handle will use, by default, to dispatch handlers for any 0126 * asynchronous operations performed on the random-access handle. 0127 * 0128 * @param handle The new underlying handle implementation. 0129 * 0130 * @throws boost::system::system_error Thrown on failure. 0131 */ 0132 template <typename ExecutionContext> 0133 basic_random_access_handle(ExecutionContext& context, 0134 const native_handle_type& handle, 0135 constraint_t< 0136 is_convertible<ExecutionContext&, execution_context&>::value 0137 > = 0) 0138 : basic_overlapped_handle<Executor>(context, handle) 0139 { 0140 } 0141 0142 /// Move-construct a random-access handle from another. 0143 /** 0144 * This constructor moves a random-access handle from one object to another. 0145 * 0146 * @param other The other random-access handle object from which the 0147 * move will occur. 0148 * 0149 * @note Following the move, the moved-from object is in the same state as if 0150 * constructed using the @c basic_random_access_handle(const executor_type&) 0151 * constructor. 0152 */ 0153 basic_random_access_handle(basic_random_access_handle&& other) 0154 : basic_overlapped_handle<Executor>(std::move(other)) 0155 { 0156 } 0157 0158 /// Move-assign a random-access handle from another. 0159 /** 0160 * This assignment operator moves a random-access handle from one object to 0161 * another. 0162 * 0163 * @param other The other random-access handle object from which the 0164 * move will occur. 0165 * 0166 * @note Following the move, the moved-from object is in the same state as if 0167 * constructed using the @c basic_random_access_handle(const executor_type&) 0168 * constructor. 0169 */ 0170 basic_random_access_handle& operator=(basic_random_access_handle&& other) 0171 { 0172 basic_overlapped_handle<Executor>::operator=(std::move(other)); 0173 return *this; 0174 } 0175 0176 /// Move-construct a random-access handle from a handle of another executor 0177 /// type. 0178 /** 0179 * This constructor moves a random-access handle from one object to another. 0180 * 0181 * @param other The other random-access handle object from which the 0182 * move will occur. 0183 * 0184 * @note Following the move, the moved-from object is in the same state as if 0185 * constructed using the @c basic_random_access_handle(const executor_type&) 0186 * constructor. 0187 */ 0188 template<typename Executor1> 0189 basic_random_access_handle(basic_random_access_handle<Executor1>&& other, 0190 constraint_t< 0191 is_convertible<Executor1, Executor>::value, 0192 defaulted_constraint 0193 > = defaulted_constraint()) 0194 : basic_overlapped_handle<Executor>(std::move(other)) 0195 { 0196 } 0197 0198 /// Move-assign a random-access handle from a handle of another executor 0199 /// type. 0200 /** 0201 * This assignment operator moves a random-access handle from one object to 0202 * another. 0203 * 0204 * @param other The other random-access handle object from which the 0205 * move will occur. 0206 * 0207 * @note Following the move, the moved-from object is in the same state as if 0208 * constructed using the @c basic_random_access_handle(const executor_type&) 0209 * constructor. 0210 */ 0211 template<typename Executor1> 0212 constraint_t< 0213 is_convertible<Executor1, Executor>::value, 0214 basic_random_access_handle& 0215 > operator=(basic_random_access_handle<Executor1>&& other) 0216 { 0217 basic_overlapped_handle<Executor>::operator=(std::move(other)); 0218 return *this; 0219 } 0220 0221 /// Write some data to the handle at the specified offset. 0222 /** 0223 * This function is used to write data to the random-access handle. The 0224 * function call will block until one or more bytes of the data has been 0225 * written successfully, or until an error occurs. 0226 * 0227 * @param offset The offset at which the data will be written. 0228 * 0229 * @param buffers One or more data buffers to be written to the handle. 0230 * 0231 * @returns The number of bytes written. 0232 * 0233 * @throws boost::system::system_error Thrown on failure. An error code of 0234 * boost::asio::error::eof indicates that the connection was closed by the 0235 * peer. 0236 * 0237 * @note The write_some_at operation may not write all of the data. Consider 0238 * using the @ref write_at function if you need to ensure that all data is 0239 * written before the blocking operation completes. 0240 * 0241 * @par Example 0242 * To write a single data buffer use the @ref buffer function as follows: 0243 * @code 0244 * handle.write_some_at(42, boost::asio::buffer(data, size)); 0245 * @endcode 0246 * See the @ref buffer documentation for information on writing multiple 0247 * buffers in one go, and how to use it with arrays, boost::array or 0248 * std::vector. 0249 */ 0250 template <typename ConstBufferSequence> 0251 std::size_t write_some_at(uint64_t offset, 0252 const ConstBufferSequence& buffers) 0253 { 0254 boost::system::error_code ec; 0255 std::size_t s = this->impl_.get_service().write_some_at( 0256 this->impl_.get_implementation(), offset, buffers, ec); 0257 boost::asio::detail::throw_error(ec, "write_some_at"); 0258 return s; 0259 } 0260 0261 /// Write some data to the handle at the specified offset. 0262 /** 0263 * This function is used to write data to the random-access handle. The 0264 * function call will block until one or more bytes of the data has been 0265 * written successfully, or until an error occurs. 0266 * 0267 * @param offset The offset at which the data will be written. 0268 * 0269 * @param buffers One or more data buffers to be written to the handle. 0270 * 0271 * @param ec Set to indicate what error occurred, if any. 0272 * 0273 * @returns The number of bytes written. Returns 0 if an error occurred. 0274 * 0275 * @note The write_some operation may not transmit all of the data to the 0276 * peer. Consider using the @ref write_at function if you need to ensure that 0277 * all data is written before the blocking operation completes. 0278 */ 0279 template <typename ConstBufferSequence> 0280 std::size_t write_some_at(uint64_t offset, 0281 const ConstBufferSequence& buffers, boost::system::error_code& ec) 0282 { 0283 return this->impl_.get_service().write_some_at( 0284 this->impl_.get_implementation(), offset, buffers, ec); 0285 } 0286 0287 /// Start an asynchronous write at the specified offset. 0288 /** 0289 * This function is used to asynchronously write data to the random-access 0290 * handle. It is an initiating function for an @ref asynchronous_operation, 0291 * and always returns immediately. 0292 * 0293 * @param offset The offset at which the data will be written. 0294 * 0295 * @param buffers One or more data buffers to be written to the handle. 0296 * Although the buffers object may be copied as necessary, ownership of the 0297 * underlying memory blocks is retained by the caller, which must guarantee 0298 * that they remain valid until the completion handler is called. 0299 * 0300 * @param token The @ref completion_token that will be used to produce a 0301 * completion handler, which will be called when the write completes. 0302 * Potential completion tokens include @ref use_future, @ref use_awaitable, 0303 * @ref yield_context, or a function object with the correct completion 0304 * signature. The function signature of the completion handler must be: 0305 * @code void handler( 0306 * const boost::system::error_code& error, // Result of operation. 0307 * std::size_t bytes_transferred // Number of bytes written. 0308 * ); @endcode 0309 * Regardless of whether the asynchronous operation completes immediately or 0310 * not, the completion handler will not be invoked from within this function. 0311 * On immediate completion, invocation of the handler will be performed in a 0312 * manner equivalent to using boost::asio::post(). 0313 * 0314 * @par Completion Signature 0315 * @code void(boost::system::error_code, std::size_t) @endcode 0316 * 0317 * @note The write operation may not transmit all of the data to the peer. 0318 * Consider using the @ref async_write_at function if you need to ensure that 0319 * all data is written before the asynchronous operation completes. 0320 * 0321 * @par Example 0322 * To write a single data buffer use the @ref buffer function as follows: 0323 * @code 0324 * handle.async_write_some_at(42, boost::asio::buffer(data, size), handler); 0325 * @endcode 0326 * See the @ref buffer documentation for information on writing multiple 0327 * buffers in one go, and how to use it with arrays, boost::array or 0328 * std::vector. 0329 * 0330 * @par Per-Operation Cancellation 0331 * This asynchronous operation supports cancellation for the following 0332 * boost::asio::cancellation_type values: 0333 * 0334 * @li @c cancellation_type::terminal 0335 * 0336 * @li @c cancellation_type::partial 0337 * 0338 * @li @c cancellation_type::total 0339 */ 0340 template <typename ConstBufferSequence, 0341 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 0342 std::size_t)) WriteToken = default_completion_token_t<executor_type>> 0343 auto async_write_some_at(uint64_t offset, const ConstBufferSequence& buffers, 0344 WriteToken&& token = default_completion_token_t<executor_type>()) 0345 -> decltype( 0346 async_initiate<WriteToken, 0347 void (boost::system::error_code, std::size_t)>( 0348 declval<initiate_async_write_some_at>(), token, offset, buffers)) 0349 { 0350 return async_initiate<WriteToken, 0351 void (boost::system::error_code, std::size_t)>( 0352 initiate_async_write_some_at(this), token, offset, buffers); 0353 } 0354 0355 /// Read some data from the handle at the specified offset. 0356 /** 0357 * This function is used to read data from the random-access handle. The 0358 * function call will block until one or more bytes of data has been read 0359 * successfully, or until an error occurs. 0360 * 0361 * @param offset The offset at which the data will be read. 0362 * 0363 * @param buffers One or more buffers into which the data will be read. 0364 * 0365 * @returns The number of bytes read. 0366 * 0367 * @throws boost::system::system_error Thrown on failure. An error code of 0368 * boost::asio::error::eof indicates that the connection was closed by the 0369 * peer. 0370 * 0371 * @note The read_some operation may not read all of the requested number of 0372 * bytes. Consider using the @ref read_at function if you need to ensure that 0373 * the requested amount of data is read before the blocking operation 0374 * completes. 0375 * 0376 * @par Example 0377 * To read into a single data buffer use the @ref buffer function as follows: 0378 * @code 0379 * handle.read_some_at(42, boost::asio::buffer(data, size)); 0380 * @endcode 0381 * See the @ref buffer documentation for information on reading into multiple 0382 * buffers in one go, and how to use it with arrays, boost::array or 0383 * std::vector. 0384 */ 0385 template <typename MutableBufferSequence> 0386 std::size_t read_some_at(uint64_t offset, 0387 const MutableBufferSequence& buffers) 0388 { 0389 boost::system::error_code ec; 0390 std::size_t s = this->impl_.get_service().read_some_at( 0391 this->impl_.get_implementation(), offset, buffers, ec); 0392 boost::asio::detail::throw_error(ec, "read_some_at"); 0393 return s; 0394 } 0395 0396 /// Read some data from the handle at the specified offset. 0397 /** 0398 * This function is used to read data from the random-access handle. The 0399 * function call will block until one or more bytes of data has been read 0400 * successfully, or until an error occurs. 0401 * 0402 * @param offset The offset at which the data will be read. 0403 * 0404 * @param buffers One or more buffers into which the data will be read. 0405 * 0406 * @param ec Set to indicate what error occurred, if any. 0407 * 0408 * @returns The number of bytes read. Returns 0 if an error occurred. 0409 * 0410 * @note The read_some operation may not read all of the requested number of 0411 * bytes. Consider using the @ref read_at function if you need to ensure that 0412 * the requested amount of data is read before the blocking operation 0413 * completes. 0414 */ 0415 template <typename MutableBufferSequence> 0416 std::size_t read_some_at(uint64_t offset, 0417 const MutableBufferSequence& buffers, boost::system::error_code& ec) 0418 { 0419 return this->impl_.get_service().read_some_at( 0420 this->impl_.get_implementation(), offset, buffers, ec); 0421 } 0422 0423 /// Start an asynchronous read at the specified offset. 0424 /** 0425 * This function is used to asynchronously read data from the random-access 0426 * handle. It is an initiating function for an @ref asynchronous_operation, 0427 * and always returns immediately. 0428 * 0429 * @param offset The offset at which the data will be read. 0430 * 0431 * @param buffers One or more buffers into which the data will be read. 0432 * Although the buffers object may be copied as necessary, ownership of the 0433 * underlying memory blocks is retained by the caller, which must guarantee 0434 * that they remain valid until the completion handler is called. 0435 * 0436 * @param token The @ref completion_token that will be used to produce a 0437 * completion handler, which will be called when the read completes. 0438 * Potential completion tokens include @ref use_future, @ref use_awaitable, 0439 * @ref yield_context, or a function object with the correct completion 0440 * signature. The function signature of the completion handler must be: 0441 * @code void handler( 0442 * const boost::system::error_code& error, // Result of operation. 0443 * std::size_t bytes_transferred // Number of bytes read. 0444 * ); @endcode 0445 * Regardless of whether the asynchronous operation completes immediately or 0446 * not, the completion handler will not be invoked from within this function. 0447 * On immediate completion, invocation of the handler will be performed in a 0448 * manner equivalent to using boost::asio::post(). 0449 * 0450 * @par Completion Signature 0451 * @code void(boost::system::error_code, std::size_t) @endcode 0452 * 0453 * @note The read operation may not read all of the requested number of bytes. 0454 * Consider using the @ref async_read_at function if you need to ensure that 0455 * the requested amount of data is read before the asynchronous operation 0456 * completes. 0457 * 0458 * @par Example 0459 * To read into a single data buffer use the @ref buffer function as follows: 0460 * @code 0461 * handle.async_read_some_at(42, boost::asio::buffer(data, size), handler); 0462 * @endcode 0463 * See the @ref buffer documentation for information on reading into multiple 0464 * buffers in one go, and how to use it with arrays, boost::array or 0465 * std::vector. 0466 * 0467 * @par Per-Operation Cancellation 0468 * This asynchronous operation supports cancellation for the following 0469 * boost::asio::cancellation_type values: 0470 * 0471 * @li @c cancellation_type::terminal 0472 * 0473 * @li @c cancellation_type::partial 0474 * 0475 * @li @c cancellation_type::total 0476 */ 0477 template <typename MutableBufferSequence, 0478 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, 0479 std::size_t)) ReadToken = default_completion_token_t<executor_type>> 0480 auto async_read_some_at(uint64_t offset, const MutableBufferSequence& buffers, 0481 ReadToken&& token = default_completion_token_t<executor_type>()) 0482 -> decltype( 0483 async_initiate<ReadToken, 0484 void (boost::system::error_code, std::size_t)>( 0485 declval<initiate_async_read_some_at>(), token, offset, buffers)) 0486 { 0487 return async_initiate<ReadToken, 0488 void (boost::system::error_code, std::size_t)>( 0489 initiate_async_read_some_at(this), token, offset, buffers); 0490 } 0491 0492 private: 0493 class initiate_async_write_some_at 0494 { 0495 public: 0496 typedef Executor executor_type; 0497 0498 explicit initiate_async_write_some_at(basic_random_access_handle* self) 0499 : self_(self) 0500 { 0501 } 0502 0503 const executor_type& get_executor() const noexcept 0504 { 0505 return self_->get_executor(); 0506 } 0507 0508 template <typename WriteHandler, typename ConstBufferSequence> 0509 void operator()(WriteHandler&& handler, 0510 uint64_t offset, const ConstBufferSequence& buffers) const 0511 { 0512 // If you get an error on the following line it means that your handler 0513 // does not meet the documented type requirements for a WriteHandler. 0514 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 0515 0516 detail::non_const_lvalue<WriteHandler> handler2(handler); 0517 self_->impl_.get_service().async_write_some_at( 0518 self_->impl_.get_implementation(), offset, buffers, 0519 handler2.value, self_->impl_.get_executor()); 0520 } 0521 0522 private: 0523 basic_random_access_handle* self_; 0524 }; 0525 0526 class initiate_async_read_some_at 0527 { 0528 public: 0529 typedef Executor executor_type; 0530 0531 explicit initiate_async_read_some_at(basic_random_access_handle* self) 0532 : self_(self) 0533 { 0534 } 0535 0536 const executor_type& get_executor() const noexcept 0537 { 0538 return self_->get_executor(); 0539 } 0540 0541 template <typename ReadHandler, typename MutableBufferSequence> 0542 void operator()(ReadHandler&& handler, 0543 uint64_t offset, const MutableBufferSequence& buffers) const 0544 { 0545 // If you get an error on the following line it means that your handler 0546 // does not meet the documented type requirements for a ReadHandler. 0547 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 0548 0549 detail::non_const_lvalue<ReadHandler> handler2(handler); 0550 self_->impl_.get_service().async_read_some_at( 0551 self_->impl_.get_implementation(), offset, buffers, 0552 handler2.value, self_->impl_.get_executor()); 0553 } 0554 0555 private: 0556 basic_random_access_handle* self_; 0557 }; 0558 }; 0559 0560 } // namespace windows 0561 } // namespace asio 0562 } // namespace boost 0563 0564 #include <boost/asio/detail/pop_options.hpp> 0565 0566 #endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) 0567 // || defined(GENERATING_DOCUMENTATION) 0568 0569 #endif // BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_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 |