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