basic_stream_file.hpp 26 KB

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