basic_random_access_file.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. //
  2. // basic_random_access_file.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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. #ifndef BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_HPP
  11. #define BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #if defined(BOOST_ASIO_HAS_FILE) \
  17. || defined(GENERATING_DOCUMENTATION)
  18. #include <cstddef>
  19. #include <boost/asio/async_result.hpp>
  20. #include <boost/asio/basic_file.hpp>
  21. #include <boost/asio/detail/handler_type_requirements.hpp>
  22. #include <boost/asio/detail/non_const_lvalue.hpp>
  23. #include <boost/asio/detail/throw_error.hpp>
  24. #include <boost/asio/error.hpp>
  25. #include <boost/asio/detail/push_options.hpp>
  26. namespace boost {
  27. namespace asio {
  28. #if !defined(BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)
  29. #define BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL
  30. // Forward declaration with defaulted arguments.
  31. template <typename Executor = any_io_executor>
  32. class basic_random_access_file;
  33. #endif // !defined(BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)
  34. /// Provides random-access file functionality.
  35. /**
  36. * The basic_random_access_file class template provides asynchronous and
  37. * blocking random-access file functionality.
  38. *
  39. * @par Thread Safety
  40. * @e Distinct @e objects: Safe.@n
  41. * @e Shared @e objects: Unsafe.
  42. *
  43. * Synchronous @c read_some_at and @c write_some_at operations are thread safe
  44. * with respect to each other, if the underlying operating system calls are
  45. * also thread safe. This means that it is permitted to perform concurrent
  46. * calls to these synchronous operations on a single file object. Other
  47. * synchronous operations, such as @c open or @c close, are not thread safe.
  48. */
  49. template <typename Executor>
  50. class basic_random_access_file
  51. : public basic_file<Executor>
  52. {
  53. private:
  54. class initiate_async_write_some_at;
  55. class initiate_async_read_some_at;
  56. public:
  57. /// The type of the executor associated with the object.
  58. typedef Executor executor_type;
  59. /// Rebinds the file type to another executor.
  60. template <typename Executor1>
  61. struct rebind_executor
  62. {
  63. /// The file type when rebound to the specified executor.
  64. typedef basic_random_access_file<Executor1> other;
  65. };
  66. /// The native representation of a file.
  67. #if defined(GENERATING_DOCUMENTATION)
  68. typedef implementation_defined native_handle_type;
  69. #else
  70. typedef typename basic_file<Executor>::native_handle_type native_handle_type;
  71. #endif
  72. /// Construct a basic_random_access_file without opening it.
  73. /**
  74. * This constructor initialises a file without opening it. The file needs to
  75. * be opened before data can be read from or or written to it.
  76. *
  77. * @param ex The I/O executor that the file will use, by default, to
  78. * dispatch handlers for any asynchronous operations performed on the file.
  79. */
  80. explicit basic_random_access_file(const executor_type& ex)
  81. : basic_file<Executor>(ex)
  82. {
  83. }
  84. /// Construct a basic_random_access_file without opening it.
  85. /**
  86. * This constructor initialises a file without opening it. The file needs to
  87. * be opened before data can be read from or or written to it.
  88. *
  89. * @param context An execution context which provides the I/O executor that
  90. * the file will use, by default, to dispatch handlers for any asynchronous
  91. * operations performed on the file.
  92. */
  93. template <typename ExecutionContext>
  94. explicit basic_random_access_file(ExecutionContext& context,
  95. constraint_t<
  96. is_convertible<ExecutionContext&, execution_context&>::value,
  97. defaulted_constraint
  98. > = defaulted_constraint())
  99. : basic_file<Executor>(context)
  100. {
  101. }
  102. /// Construct and open a basic_random_access_file.
  103. /**
  104. * This constructor initialises and opens a file.
  105. *
  106. * @param ex The I/O executor that the file will use, by default, to
  107. * dispatch handlers for any asynchronous operations performed on the file.
  108. *
  109. * @param path The path name identifying the file to be opened.
  110. *
  111. * @param open_flags A set of flags that determine how the file should be
  112. * opened.
  113. *
  114. * @throws boost::system::system_error Thrown on failure.
  115. */
  116. basic_random_access_file(const executor_type& ex,
  117. const char* path, file_base::flags open_flags)
  118. : basic_file<Executor>(ex, path, open_flags)
  119. {
  120. }
  121. /// Construct and open a basic_random_access_file.
  122. /**
  123. * This constructor initialises and opens a file.
  124. *
  125. * @param context An execution context which provides the I/O executor that
  126. * the file will use, by default, to dispatch handlers for any asynchronous
  127. * operations performed on the file.
  128. *
  129. * @param path The path name identifying the file to be opened.
  130. *
  131. * @param open_flags A set of flags that determine how the file should be
  132. * opened.
  133. *
  134. * @throws boost::system::system_error Thrown on failure.
  135. */
  136. template <typename ExecutionContext>
  137. basic_random_access_file(ExecutionContext& context,
  138. const char* path, file_base::flags open_flags,
  139. constraint_t<
  140. is_convertible<ExecutionContext&, execution_context&>::value,
  141. defaulted_constraint
  142. > = defaulted_constraint())
  143. : basic_file<Executor>(context, path, open_flags)
  144. {
  145. }
  146. /// Construct and open a basic_random_access_file.
  147. /**
  148. * This constructor initialises and opens a file.
  149. *
  150. * @param ex The I/O executor that the file will use, by default, to
  151. * dispatch handlers for any asynchronous operations performed on the file.
  152. *
  153. * @param path The path name identifying the file to be opened.
  154. *
  155. * @param open_flags A set of flags that determine how the file should be
  156. * opened.
  157. *
  158. * @throws boost::system::system_error Thrown on failure.
  159. */
  160. basic_random_access_file(const executor_type& ex,
  161. const std::string& path, file_base::flags open_flags)
  162. : basic_file<Executor>(ex, path, open_flags)
  163. {
  164. }
  165. /// Construct and open a basic_random_access_file.
  166. /**
  167. * This constructor initialises and opens a file.
  168. *
  169. * @param context An execution context which provides the I/O executor that
  170. * the file will use, by default, to dispatch handlers for any asynchronous
  171. * operations performed on the file.
  172. *
  173. * @param path The path name identifying the file to be opened.
  174. *
  175. * @param open_flags A set of flags that determine how the file should be
  176. * opened.
  177. *
  178. * @throws boost::system::system_error Thrown on failure.
  179. */
  180. template <typename ExecutionContext>
  181. basic_random_access_file(ExecutionContext& context,
  182. const std::string& path, file_base::flags open_flags,
  183. constraint_t<
  184. is_convertible<ExecutionContext&, execution_context&>::value,
  185. defaulted_constraint
  186. > = defaulted_constraint())
  187. : basic_file<Executor>(context, path, open_flags)
  188. {
  189. }
  190. /// Construct a basic_random_access_file on an existing native file.
  191. /**
  192. * This constructor initialises a random-access file object to hold an
  193. * existing native file.
  194. *
  195. * @param ex The I/O executor that the file will use, by default, to
  196. * dispatch handlers for any asynchronous operations performed on the file.
  197. *
  198. * @param native_file The new underlying file implementation.
  199. *
  200. * @throws boost::system::system_error Thrown on failure.
  201. */
  202. basic_random_access_file(const executor_type& ex,
  203. const native_handle_type& native_file)
  204. : basic_file<Executor>(ex, native_file)
  205. {
  206. }
  207. /// Construct a basic_random_access_file on an existing native file.
  208. /**
  209. * This constructor initialises a random-access file object to hold an
  210. * existing native file.
  211. *
  212. * @param context An execution context which provides the I/O executor that
  213. * the file will use, by default, to dispatch handlers for any asynchronous
  214. * operations performed on the file.
  215. *
  216. * @param native_file The new underlying file implementation.
  217. *
  218. * @throws boost::system::system_error Thrown on failure.
  219. */
  220. template <typename ExecutionContext>
  221. basic_random_access_file(ExecutionContext& context,
  222. const native_handle_type& native_file,
  223. constraint_t<
  224. is_convertible<ExecutionContext&, execution_context&>::value,
  225. defaulted_constraint
  226. > = defaulted_constraint())
  227. : basic_file<Executor>(context, native_file)
  228. {
  229. }
  230. /// Move-construct a basic_random_access_file from another.
  231. /**
  232. * This constructor moves a random-access file from one object to another.
  233. *
  234. * @param other The other basic_random_access_file object from which the move
  235. * will occur.
  236. *
  237. * @note Following the move, the moved-from object is in the same state as if
  238. * constructed using the @c basic_random_access_file(const executor_type&)
  239. * constructor.
  240. */
  241. basic_random_access_file(basic_random_access_file&& other) noexcept
  242. : basic_file<Executor>(std::move(other))
  243. {
  244. }
  245. /// Move-assign a basic_random_access_file from another.
  246. /**
  247. * This assignment operator moves a random-access file from one object to
  248. * another.
  249. *
  250. * @param other The other basic_random_access_file object from which the move
  251. * will occur.
  252. *
  253. * @note Following the move, the moved-from object is in the same state as if
  254. * constructed using the @c basic_random_access_file(const executor_type&)
  255. * constructor.
  256. */
  257. basic_random_access_file& operator=(basic_random_access_file&& other)
  258. {
  259. basic_file<Executor>::operator=(std::move(other));
  260. return *this;
  261. }
  262. /// Move-construct a basic_random_access_file from a file of another executor
  263. /// type.
  264. /**
  265. * This constructor moves a random-access file from one object to another.
  266. *
  267. * @param other The other basic_random_access_file object from which the move
  268. * will occur.
  269. *
  270. * @note Following the move, the moved-from object is in the same state as if
  271. * constructed using the @c basic_random_access_file(const executor_type&)
  272. * constructor.
  273. */
  274. template <typename Executor1>
  275. basic_random_access_file(basic_random_access_file<Executor1>&& other,
  276. constraint_t<
  277. is_convertible<Executor1, Executor>::value,
  278. defaulted_constraint
  279. > = defaulted_constraint())
  280. : basic_file<Executor>(std::move(other))
  281. {
  282. }
  283. /// Move-assign a basic_random_access_file from a file of another executor
  284. /// type.
  285. /**
  286. * This assignment operator moves a random-access file from one object to
  287. * another.
  288. *
  289. * @param other The other basic_random_access_file object from which the move
  290. * will occur.
  291. *
  292. * @note Following the move, the moved-from object is in the same state as if
  293. * constructed using the @c basic_random_access_file(const executor_type&)
  294. * constructor.
  295. */
  296. template <typename Executor1>
  297. constraint_t<
  298. is_convertible<Executor1, Executor>::value,
  299. basic_random_access_file&
  300. > operator=(basic_random_access_file<Executor1>&& other)
  301. {
  302. basic_file<Executor>::operator=(std::move(other));
  303. return *this;
  304. }
  305. /// Destroys the file.
  306. /**
  307. * This function destroys the file, cancelling any outstanding asynchronous
  308. * operations associated with the file as if by calling @c cancel.
  309. */
  310. ~basic_random_access_file()
  311. {
  312. }
  313. /// Write some data to the handle at the specified offset.
  314. /**
  315. * This function is used to write data to the random-access handle. The
  316. * function call will block until one or more bytes of the data has been
  317. * written successfully, or until an error occurs.
  318. *
  319. * @param offset The offset at which the data will be written.
  320. *
  321. * @param buffers One or more data buffers to be written to the handle.
  322. *
  323. * @returns The number of bytes written.
  324. *
  325. * @throws boost::system::system_error Thrown on failure. An error code of
  326. * boost::asio::error::eof indicates that the end of the file was reached.
  327. *
  328. * @note The write_some_at operation may not write all of the data. Consider
  329. * using the @ref write_at function if you need to ensure that all data is
  330. * written before the blocking operation completes.
  331. *
  332. * @par Example
  333. * To write a single data buffer use the @ref buffer function as follows:
  334. * @code
  335. * handle.write_some_at(42, boost::asio::buffer(data, size));
  336. * @endcode
  337. * See the @ref buffer documentation for information on writing multiple
  338. * buffers in one go, and how to use it with arrays, boost::array or
  339. * std::vector.
  340. */
  341. template <typename ConstBufferSequence>
  342. std::size_t write_some_at(uint64_t offset,
  343. const ConstBufferSequence& buffers)
  344. {
  345. boost::system::error_code ec;
  346. std::size_t s = this->impl_.get_service().write_some_at(
  347. this->impl_.get_implementation(), offset, buffers, ec);
  348. boost::asio::detail::throw_error(ec, "write_some_at");
  349. return s;
  350. }
  351. /// Write some data to the handle at the specified offset.
  352. /**
  353. * This function is used to write data to the random-access handle. The
  354. * function call will block until one or more bytes of the data has been
  355. * written successfully, or until an error occurs.
  356. *
  357. * @param offset The offset at which the data will be written.
  358. *
  359. * @param buffers One or more data buffers to be written to the handle.
  360. *
  361. * @param ec Set to indicate what error occurred, if any.
  362. *
  363. * @returns The number of bytes written. Returns 0 if an error occurred.
  364. *
  365. * @note The write_some operation may not write all of the data to the
  366. * file. Consider using the @ref write_at function if you need to ensure that
  367. * all data is written before the blocking operation completes.
  368. */
  369. template <typename ConstBufferSequence>
  370. std::size_t write_some_at(uint64_t offset,
  371. const ConstBufferSequence& buffers, boost::system::error_code& ec)
  372. {
  373. return this->impl_.get_service().write_some_at(
  374. this->impl_.get_implementation(), offset, buffers, ec);
  375. }
  376. /// Start an asynchronous write at the specified offset.
  377. /**
  378. * This function is used to asynchronously write data to the random-access
  379. * handle. It is an initiating function for an @ref asynchronous_operation,
  380. * and always returns immediately.
  381. *
  382. * @param offset The offset at which the data will be written.
  383. *
  384. * @param buffers One or more data buffers to be written to the handle.
  385. * Although the buffers object may be copied as necessary, ownership of the
  386. * underlying memory blocks is retained by the caller, which must guarantee
  387. * that they remain valid until the completion handler is called.
  388. *
  389. * @param token The @ref completion_token that will be used to produce a
  390. * completion handler, which will be called when the write completes.
  391. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  392. * @ref yield_context, or a function object with the correct completion
  393. * signature. The function signature of the completion handler must be:
  394. * @code void handler(
  395. * const boost::system::error_code& error, // Result of operation.
  396. * std::size_t bytes_transferred // Number of bytes written.
  397. * ); @endcode
  398. * Regardless of whether the asynchronous operation completes immediately or
  399. * not, the completion handler will not be invoked from within this function.
  400. * On immediate completion, invocation of the handler will be performed in a
  401. * manner equivalent to using boost::asio::post().
  402. *
  403. * @par Completion Signature
  404. * @code void(boost::system::error_code, std::size_t) @endcode
  405. *
  406. * @note The write operation may not write all of the data to the file.
  407. * Consider using the @ref async_write_at function if you need to ensure that
  408. * all data is written before the asynchronous operation completes.
  409. *
  410. * @par Example
  411. * To write a single data buffer use the @ref buffer function as follows:
  412. * @code
  413. * handle.async_write_some_at(42, boost::asio::buffer(data, size), handler);
  414. * @endcode
  415. * See the @ref buffer documentation for information on writing multiple
  416. * buffers in one go, and how to use it with arrays, boost::array or
  417. * std::vector.
  418. *
  419. * @par Per-Operation Cancellation
  420. * This asynchronous operation supports cancellation for the following
  421. * boost::asio::cancellation_type values:
  422. *
  423. * @li @c cancellation_type::terminal
  424. *
  425. * @li @c cancellation_type::partial
  426. *
  427. * @li @c cancellation_type::total
  428. */
  429. template <typename ConstBufferSequence,
  430. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  431. std::size_t)) WriteToken = default_completion_token_t<executor_type>>
  432. auto async_write_some_at(uint64_t offset, const ConstBufferSequence& buffers,
  433. WriteToken&& token = default_completion_token_t<executor_type>())
  434. -> decltype(
  435. async_initiate<WriteToken,
  436. void (boost::system::error_code, std::size_t)>(
  437. declval<initiate_async_write_some_at>(), token, offset, buffers))
  438. {
  439. return async_initiate<WriteToken,
  440. void (boost::system::error_code, std::size_t)>(
  441. initiate_async_write_some_at(this), token, offset, buffers);
  442. }
  443. /// Read some data from the handle at the specified offset.
  444. /**
  445. * This function is used to read data from the random-access handle. The
  446. * function call will block until one or more bytes of data has been read
  447. * successfully, or until an error occurs.
  448. *
  449. * @param offset The offset at which the data will be read.
  450. *
  451. * @param buffers One or more buffers into which the data will be read.
  452. *
  453. * @returns The number of bytes read.
  454. *
  455. * @throws boost::system::system_error Thrown on failure. An error code of
  456. * boost::asio::error::eof indicates that the end of the file was reached.
  457. *
  458. * @note The read_some operation may not read all of the requested number of
  459. * bytes. Consider using the @ref read_at function if you need to ensure that
  460. * the requested amount of data is read before the blocking operation
  461. * completes.
  462. *
  463. * @par Example
  464. * To read into a single data buffer use the @ref buffer function as follows:
  465. * @code
  466. * handle.read_some_at(42, boost::asio::buffer(data, size));
  467. * @endcode
  468. * See the @ref buffer documentation for information on reading into multiple
  469. * buffers in one go, and how to use it with arrays, boost::array or
  470. * std::vector.
  471. */
  472. template <typename MutableBufferSequence>
  473. std::size_t read_some_at(uint64_t offset,
  474. const MutableBufferSequence& buffers)
  475. {
  476. boost::system::error_code ec;
  477. std::size_t s = this->impl_.get_service().read_some_at(
  478. this->impl_.get_implementation(), offset, buffers, ec);
  479. boost::asio::detail::throw_error(ec, "read_some_at");
  480. return s;
  481. }
  482. /// Read some data from the handle at the specified offset.
  483. /**
  484. * This function is used to read data from the random-access handle. The
  485. * function call will block until one or more bytes of data has been read
  486. * successfully, or until an error occurs.
  487. *
  488. * @param offset The offset at which the data will be read.
  489. *
  490. * @param buffers One or more buffers into which the data will be read.
  491. *
  492. * @param ec Set to indicate what error occurred, if any.
  493. *
  494. * @returns The number of bytes read. Returns 0 if an error occurred.
  495. *
  496. * @note The read_some operation may not read all of the requested number of
  497. * bytes. Consider using the @ref read_at function if you need to ensure that
  498. * the requested amount of data is read before the blocking operation
  499. * completes.
  500. */
  501. template <typename MutableBufferSequence>
  502. std::size_t read_some_at(uint64_t offset,
  503. const MutableBufferSequence& buffers, boost::system::error_code& ec)
  504. {
  505. return this->impl_.get_service().read_some_at(
  506. this->impl_.get_implementation(), offset, buffers, ec);
  507. }
  508. /// Start an asynchronous read at the specified offset.
  509. /**
  510. * This function is used to asynchronously read data from the random-access
  511. * handle. It is an initiating function for an @ref asynchronous_operation,
  512. * and always returns immediately.
  513. *
  514. * @param offset The offset at which the data will be read.
  515. *
  516. * @param buffers One or more buffers into which the data will be read.
  517. * Although the buffers object may be copied as necessary, ownership of the
  518. * underlying memory blocks is retained by the caller, which must guarantee
  519. * that they remain valid until the completion handler is called.
  520. *
  521. * @param token The @ref completion_token that will be used to produce a
  522. * completion handler, which will be called when the read completes.
  523. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  524. * @ref yield_context, or a function object with the correct completion
  525. * signature. The function signature of the completion handler must be:
  526. * @code void handler(
  527. * const boost::system::error_code& error, // Result of operation.
  528. * std::size_t bytes_transferred // Number of bytes read.
  529. * ); @endcode
  530. * Regardless of whether the asynchronous operation completes immediately or
  531. * not, the completion handler will not be invoked from within this function.
  532. * On immediate completion, invocation of the handler will be performed in a
  533. * manner equivalent to using boost::asio::post().
  534. *
  535. * @par Completion Signature
  536. * @code void(boost::system::error_code, std::size_t) @endcode
  537. *
  538. * @note The read operation may not read all of the requested number of bytes.
  539. * Consider using the @ref async_read_at function if you need to ensure that
  540. * the requested amount of data is read before the asynchronous operation
  541. * completes.
  542. *
  543. * @par Example
  544. * To read into a single data buffer use the @ref buffer function as follows:
  545. * @code
  546. * handle.async_read_some_at(42, boost::asio::buffer(data, size), handler);
  547. * @endcode
  548. * See the @ref buffer documentation for information on reading into multiple
  549. * buffers in one go, and how to use it with arrays, boost::array or
  550. * std::vector.
  551. *
  552. * @par Per-Operation Cancellation
  553. * This asynchronous operation supports cancellation for the following
  554. * boost::asio::cancellation_type values:
  555. *
  556. * @li @c cancellation_type::terminal
  557. *
  558. * @li @c cancellation_type::partial
  559. *
  560. * @li @c cancellation_type::total
  561. */
  562. template <typename MutableBufferSequence,
  563. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  564. std::size_t)) ReadToken = default_completion_token_t<executor_type>>
  565. auto async_read_some_at(uint64_t offset, const MutableBufferSequence& buffers,
  566. ReadToken&& token = default_completion_token_t<executor_type>())
  567. -> decltype(
  568. async_initiate<ReadToken,
  569. void (boost::system::error_code, std::size_t)>(
  570. declval<initiate_async_read_some_at>(), token, offset, buffers))
  571. {
  572. return async_initiate<ReadToken,
  573. void (boost::system::error_code, std::size_t)>(
  574. initiate_async_read_some_at(this), token, offset, buffers);
  575. }
  576. private:
  577. // Disallow copying and assignment.
  578. basic_random_access_file(const basic_random_access_file&) = delete;
  579. basic_random_access_file& operator=(
  580. const basic_random_access_file&) = delete;
  581. class initiate_async_write_some_at
  582. {
  583. public:
  584. typedef Executor executor_type;
  585. explicit initiate_async_write_some_at(basic_random_access_file* self)
  586. : self_(self)
  587. {
  588. }
  589. const executor_type& get_executor() const noexcept
  590. {
  591. return self_->get_executor();
  592. }
  593. template <typename WriteHandler, typename ConstBufferSequence>
  594. void operator()(WriteHandler&& handler,
  595. uint64_t offset, const ConstBufferSequence& buffers) const
  596. {
  597. // If you get an error on the following line it means that your handler
  598. // does not meet the documented type requirements for a WriteHandler.
  599. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  600. detail::non_const_lvalue<WriteHandler> handler2(handler);
  601. self_->impl_.get_service().async_write_some_at(
  602. self_->impl_.get_implementation(), offset, buffers,
  603. handler2.value, self_->impl_.get_executor());
  604. }
  605. private:
  606. basic_random_access_file* self_;
  607. };
  608. class initiate_async_read_some_at
  609. {
  610. public:
  611. typedef Executor executor_type;
  612. explicit initiate_async_read_some_at(basic_random_access_file* self)
  613. : self_(self)
  614. {
  615. }
  616. const executor_type& get_executor() const noexcept
  617. {
  618. return self_->get_executor();
  619. }
  620. template <typename ReadHandler, typename MutableBufferSequence>
  621. void operator()(ReadHandler&& handler,
  622. uint64_t offset, const MutableBufferSequence& buffers) const
  623. {
  624. // If you get an error on the following line it means that your handler
  625. // does not meet the documented type requirements for a ReadHandler.
  626. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  627. detail::non_const_lvalue<ReadHandler> handler2(handler);
  628. self_->impl_.get_service().async_read_some_at(
  629. self_->impl_.get_implementation(), offset, buffers,
  630. handler2.value, self_->impl_.get_executor());
  631. }
  632. private:
  633. basic_random_access_file* self_;
  634. };
  635. };
  636. } // namespace asio
  637. } // namespace boost
  638. #include <boost/asio/detail/pop_options.hpp>
  639. #endif // defined(BOOST_ASIO_HAS_FILE)
  640. // || defined(GENERATING_DOCUMENTATION)
  641. #endif // BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_HPP