basic_stream_file.hpp 26 KB

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