2 // basic_stream_file.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_BASIC_STREAM_FILE_HPP
12 #define BOOST_ASIO_BASIC_STREAM_FILE_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
20 #if defined(BOOST_ASIO_HAS_FILE) \
21 || defined(GENERATING_DOCUMENTATION)
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>
31 #include <boost/asio/detail/push_options.hpp>
36 #if !defined(BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL)
37 #define BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL
39 // Forward declaration with defaulted arguments.
40 template <typename Executor = any_io_executor>
41 class basic_stream_file;
43 #endif // !defined(BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL)
45 /// Provides stream-oriented file functionality.
47 * The basic_stream_file class template provides asynchronous and blocking
48 * stream-oriented file functionality.
51 * @e Distinct @e objects: Safe.@n
52 * @e Shared @e objects: Unsafe.
55 * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
57 template <typename Executor>
58 class basic_stream_file
59 : public basic_file<Executor>
62 /// The type of the executor associated with the object.
63 typedef Executor executor_type;
65 /// Rebinds the file type to another executor.
66 template <typename Executor1>
67 struct rebind_executor
69 /// The file type when rebound to the specified executor.
70 typedef basic_stream_file<Executor1> other;
73 /// The native representation of a file.
74 #if defined(GENERATING_DOCUMENTATION)
75 typedef implementation_defined native_handle_type;
77 typedef typename basic_file<Executor>::native_handle_type native_handle_type;
80 /// Construct a basic_stream_file without opening it.
82 * This constructor initialises a file without opening it. The file needs to
83 * be opened before data can be read from or or written to it.
85 * @param ex The I/O executor that the file will use, by default, to
86 * dispatch handlers for any asynchronous operations performed on the file.
88 explicit basic_stream_file(const executor_type& ex)
89 : basic_file<Executor>(ex)
91 this->impl_.get_service().set_is_stream(
92 this->impl_.get_implementation(), true);
95 /// Construct a basic_stream_file without opening it.
97 * This constructor initialises a file without opening it. The file needs to
98 * be opened before data can be read from or or written to it.
100 * @param context An execution context which provides the I/O executor that
101 * the file will use, by default, to dispatch handlers for any asynchronous
102 * operations performed on the file.
104 template <typename ExecutionContext>
105 explicit basic_stream_file(ExecutionContext& context,
107 is_convertible<ExecutionContext&, execution_context&>::value,
109 >::type = defaulted_constraint())
110 : basic_file<Executor>(context)
112 this->impl_.get_service().set_is_stream(
113 this->impl_.get_implementation(), true);
116 /// Construct and open a basic_stream_file.
118 * This constructor initialises and opens a file.
120 * @param ex The I/O executor that the file will use, by default, to
121 * dispatch handlers for any asynchronous operations performed on the file.
123 * @param path The path name identifying the file to be opened.
125 * @param open_flags A set of flags that determine how the file should be
128 * @throws boost::system::system_error Thrown on failure.
130 basic_stream_file(const executor_type& ex,
131 const char* path, file_base::flags open_flags)
132 : basic_file<Executor>(ex)
134 boost::system::error_code ec;
135 this->impl_.get_service().set_is_stream(
136 this->impl_.get_implementation(), true);
137 this->impl_.get_service().open(
138 this->impl_.get_implementation(),
139 path, open_flags, ec);
140 boost::asio::detail::throw_error(ec, "open");
143 /// Construct and open a basic_stream_file.
145 * This constructor initialises and opens a file.
147 * @param context An execution context which provides the I/O executor that
148 * the file will use, by default, to dispatch handlers for any asynchronous
149 * operations performed on the file.
151 * @param path The path name identifying the file to be opened.
153 * @param open_flags A set of flags that determine how the file should be
156 * @throws boost::system::system_error Thrown on failure.
158 template <typename ExecutionContext>
159 basic_stream_file(ExecutionContext& context,
160 const char* path, file_base::flags open_flags,
162 is_convertible<ExecutionContext&, execution_context&>::value,
164 >::type = defaulted_constraint())
165 : basic_file<Executor>(context)
167 boost::system::error_code ec;
168 this->impl_.get_service().set_is_stream(
169 this->impl_.get_implementation(), true);
170 this->impl_.get_service().open(
171 this->impl_.get_implementation(),
172 path, open_flags, ec);
173 boost::asio::detail::throw_error(ec, "open");
176 /// Construct and open a basic_stream_file.
178 * This constructor initialises and opens a file.
180 * @param ex The I/O executor that the file will use, by default, to
181 * dispatch handlers for any asynchronous operations performed on the file.
183 * @param path The path name identifying the file to be opened.
185 * @param open_flags A set of flags that determine how the file should be
188 * @throws boost::system::system_error Thrown on failure.
190 basic_stream_file(const executor_type& ex,
191 const std::string& path, file_base::flags open_flags)
192 : basic_file<Executor>(ex)
194 boost::system::error_code ec;
195 this->impl_.get_service().set_is_stream(
196 this->impl_.get_implementation(), true);
197 this->impl_.get_service().open(
198 this->impl_.get_implementation(),
199 path.c_str(), open_flags, ec);
200 boost::asio::detail::throw_error(ec, "open");
203 /// Construct and open a basic_stream_file.
205 * This constructor initialises and opens a file.
207 * @param context An execution context which provides the I/O executor that
208 * the file will use, by default, to dispatch handlers for any asynchronous
209 * operations performed on the file.
211 * @param path The path name identifying the file to be opened.
213 * @param open_flags A set of flags that determine how the file should be
216 * @throws boost::system::system_error Thrown on failure.
218 template <typename ExecutionContext>
219 basic_stream_file(ExecutionContext& context,
220 const std::string& path, file_base::flags open_flags,
222 is_convertible<ExecutionContext&, execution_context&>::value,
224 >::type = defaulted_constraint())
225 : basic_file<Executor>(context)
227 boost::system::error_code ec;
228 this->impl_.get_service().set_is_stream(
229 this->impl_.get_implementation(), true);
230 this->impl_.get_service().open(
231 this->impl_.get_implementation(),
232 path.c_str(), open_flags, ec);
233 boost::asio::detail::throw_error(ec, "open");
236 /// Construct a basic_stream_file on an existing native file.
238 * This constructor initialises a stream file object to hold an existing
241 * @param ex The I/O executor that the file will use, by default, to
242 * dispatch handlers for any asynchronous operations performed on the file.
244 * @param native_file The new underlying file implementation.
246 * @throws boost::system::system_error Thrown on failure.
248 basic_stream_file(const executor_type& ex,
249 const native_handle_type& native_file)
250 : basic_file<Executor>(ex, native_file)
252 this->impl_.get_service().set_is_stream(
253 this->impl_.get_implementation(), true);
256 /// Construct a basic_stream_file on an existing native file.
258 * This constructor initialises a stream file object to hold an existing
261 * @param context An execution context which provides the I/O executor that
262 * the file will use, by default, to dispatch handlers for any asynchronous
263 * operations performed on the file.
265 * @param native_file The new underlying file implementation.
267 * @throws boost::system::system_error Thrown on failure.
269 template <typename ExecutionContext>
270 basic_stream_file(ExecutionContext& context,
271 const native_handle_type& native_file,
273 is_convertible<ExecutionContext&, execution_context&>::value,
275 >::type = defaulted_constraint())
276 : basic_file<Executor>(context, native_file)
278 this->impl_.get_service().set_is_stream(
279 this->impl_.get_implementation(), true);
282 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
283 /// Move-construct a basic_stream_file from another.
285 * This constructor moves a stream file from one object to another.
287 * @param other The other basic_stream_file object from which the move
290 * @note Following the move, the moved-from object is in the same state as if
291 * constructed using the @c basic_stream_file(const executor_type&)
294 basic_stream_file(basic_stream_file&& other) BOOST_ASIO_NOEXCEPT
295 : basic_file<Executor>(std::move(other))
299 /// Move-assign a basic_stream_file from another.
301 * This assignment operator moves a stream file from one object to another.
303 * @param other The other basic_stream_file object from which the move
306 * @note Following the move, the moved-from object is in the same state as if
307 * constructed using the @c basic_stream_file(const executor_type&)
310 basic_stream_file& operator=(basic_stream_file&& other)
312 basic_file<Executor>::operator=(std::move(other));
316 /// Move-construct a basic_stream_file from a file of another executor
319 * This constructor moves a stream file from one object to another.
321 * @param other The other basic_stream_file object from which the move
324 * @note Following the move, the moved-from object is in the same state as if
325 * constructed using the @c basic_stream_file(const executor_type&)
328 template <typename Executor1>
329 basic_stream_file(basic_stream_file<Executor1>&& other,
331 is_convertible<Executor1, Executor>::value,
333 >::type = defaulted_constraint())
334 : basic_file<Executor>(std::move(other))
338 /// Move-assign a basic_stream_file from a file of another executor type.
340 * This assignment operator moves a stream file from one object to another.
342 * @param other The other basic_stream_file object from which the move
345 * @note Following the move, the moved-from object is in the same state as if
346 * constructed using the @c basic_stream_file(const executor_type&)
349 template <typename Executor1>
351 is_convertible<Executor1, Executor>::value,
353 >::type operator=(basic_stream_file<Executor1>&& other)
355 basic_file<Executor>::operator=(std::move(other));
358 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
360 /// Destroys the file.
362 * This function destroys the file, cancelling any outstanding asynchronous
363 * operations associated with the file as if by calling @c cancel.
369 /// Seek to a position in the file.
371 * This function updates the current position in the file.
373 * @param offset The requested position in the file, relative to @c whence.
375 * @param whence One of @c seek_set, @c seek_cur or @c seek_end.
377 * @returns The new position relative to the beginning of the file.
379 * @throws boost::system::system_error Thrown on failure.
381 uint64_t seek(int64_t offset, file_base::seek_basis whence)
383 boost::system::error_code ec;
384 uint64_t n = this->impl_.get_service().seek(
385 this->impl_.get_implementation(), offset, whence, ec);
386 boost::asio::detail::throw_error(ec, "seek");
390 /// Seek to a position in the file.
392 * This function updates the current position in the file.
394 * @param offset The requested position in the file, relative to @c whence.
396 * @param whence One of @c seek_set, @c seek_cur or @c seek_end.
398 * @param ec Set to indicate what error occurred, if any.
400 * @returns The new position relative to the beginning of the file.
402 uint64_t seek(int64_t offset, file_base::seek_basis whence,
403 boost::system::error_code& ec)
405 return this->impl_.get_service().seek(
406 this->impl_.get_implementation(), offset, whence, ec);
409 /// Write some data to the file.
411 * This function is used to write data to the stream file. The function call
412 * will block until one or more bytes of the data has been written
413 * successfully, or until an error occurs.
415 * @param buffers One or more data buffers to be written to the file.
417 * @returns The number of bytes written.
419 * @throws boost::system::system_error Thrown on failure. An error code of
420 * boost::asio::error::eof indicates that the end of the file was reached.
422 * @note The write_some operation may not transmit all of the data to the
423 * peer. Consider using the @ref write function if you need to ensure that
424 * all data is written before the blocking operation completes.
427 * To write a single data buffer use the @ref buffer function as follows:
429 * file.write_some(boost::asio::buffer(data, size));
431 * See the @ref buffer documentation for information on writing multiple
432 * buffers in one go, and how to use it with arrays, boost::array or
435 template <typename ConstBufferSequence>
436 std::size_t write_some(const ConstBufferSequence& buffers)
438 boost::system::error_code ec;
439 std::size_t s = this->impl_.get_service().write_some(
440 this->impl_.get_implementation(), buffers, ec);
441 boost::asio::detail::throw_error(ec, "write_some");
445 /// Write some data to the file.
447 * This function is used to write data to the stream file. The function call
448 * will block until one or more bytes of the data has been written
449 * successfully, or until an error occurs.
451 * @param buffers One or more data buffers to be written to the file.
453 * @param ec Set to indicate what error occurred, if any.
455 * @returns The number of bytes written. Returns 0 if an error occurred.
457 * @note The write_some operation may not transmit all of the data to the
458 * peer. Consider using the @ref write function if you need to ensure that
459 * all data is written before the blocking operation completes.
461 template <typename ConstBufferSequence>
462 std::size_t write_some(const ConstBufferSequence& buffers,
463 boost::system::error_code& ec)
465 return this->impl_.get_service().write_some(
466 this->impl_.get_implementation(), buffers, ec);
469 /// Start an asynchronous write.
471 * This function is used to asynchronously write data to the stream file.
472 * It is an initiating function for an @ref asynchronous_operation, and always
473 * returns immediately.
475 * @param buffers One or more data buffers to be written to the file.
476 * Although the buffers object may be copied as necessary, ownership of the
477 * underlying memory blocks is retained by the caller, which must guarantee
478 * that they remain valid until the completion handler is called.
480 * @param token The @ref completion_token that will be used to produce a
481 * completion handler, which will be called when the write completes.
482 * Potential completion tokens include @ref use_future, @ref use_awaitable,
483 * @ref yield_context, or a function object with the correct completion
484 * signature. The function signature of the completion handler must be:
485 * @code void handler(
486 * const boost::system::error_code& error, // Result of operation.
487 * std::size_t bytes_transferred // Number of bytes written.
489 * Regardless of whether the asynchronous operation completes immediately or
490 * not, the completion handler will not be invoked from within this function.
491 * On immediate completion, invocation of the handler will be performed in a
492 * manner equivalent to using boost::asio::post().
494 * @par Completion Signature
495 * @code void(boost::system::error_code, std::size_t) @endcode
497 * @note The write operation may not transmit all of the data to the peer.
498 * Consider using the @ref async_write function if you need to ensure that all
499 * data is written before the asynchronous operation completes.
502 * To write a single data buffer use the @ref buffer function as follows:
504 * file.async_write_some(boost::asio::buffer(data, size), handler);
506 * See the @ref buffer documentation for information on writing multiple
507 * buffers in one go, and how to use it with arrays, boost::array or
510 * @par Per-Operation Cancellation
511 * On POSIX or Windows operating systems, this asynchronous operation supports
512 * cancellation for the following boost::asio::cancellation_type values:
514 * @li @c cancellation_type::terminal
516 * @li @c cancellation_type::partial
518 * @li @c cancellation_type::total
520 template <typename ConstBufferSequence,
521 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
522 std::size_t)) WriteToken
523 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
524 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteToken,
525 void (boost::system::error_code, std::size_t))
526 async_write_some(const ConstBufferSequence& buffers,
527 BOOST_ASIO_MOVE_ARG(WriteToken) token
528 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
530 return async_initiate<WriteToken,
531 void (boost::system::error_code, std::size_t)>(
532 initiate_async_write_some(this), token, buffers);
535 /// Read some data from the file.
537 * This function is used to read data from the stream file. The function
538 * call will block until one or more bytes of data has been read successfully,
539 * or until an error occurs.
541 * @param buffers One or more buffers into which the data will be read.
543 * @returns The number of bytes read.
545 * @throws boost::system::system_error Thrown on failure. An error code of
546 * boost::asio::error::eof indicates that the end of the file was reached.
548 * @note The read_some operation may not read all of the requested number of
549 * bytes. Consider using the @ref read function if you need to ensure that
550 * the requested amount of data is read before the blocking operation
554 * To read into a single data buffer use the @ref buffer function as follows:
556 * file.read_some(boost::asio::buffer(data, size));
558 * See the @ref buffer documentation for information on reading into multiple
559 * buffers in one go, and how to use it with arrays, boost::array or
562 template <typename MutableBufferSequence>
563 std::size_t read_some(const MutableBufferSequence& buffers)
565 boost::system::error_code ec;
566 std::size_t s = this->impl_.get_service().read_some(
567 this->impl_.get_implementation(), buffers, ec);
568 boost::asio::detail::throw_error(ec, "read_some");
572 /// Read some data from the file.
574 * This function is used to read data from the stream file. The function
575 * call will block until one or more bytes of data has been read successfully,
576 * or until an error occurs.
578 * @param buffers One or more buffers into which the data will be read.
580 * @param ec Set to indicate what error occurred, if any.
582 * @returns The number of bytes read. Returns 0 if an error occurred.
584 * @note The read_some operation may not read all of the requested number of
585 * bytes. Consider using the @ref read function if you need to ensure that
586 * the requested amount of data is read before the blocking operation
589 template <typename MutableBufferSequence>
590 std::size_t read_some(const MutableBufferSequence& buffers,
591 boost::system::error_code& ec)
593 return this->impl_.get_service().read_some(
594 this->impl_.get_implementation(), buffers, ec);
597 /// Start an asynchronous read.
599 * This function is used to asynchronously read data from the stream file.
600 * It is an initiating function for an @ref asynchronous_operation, and always
601 * returns immediately.
603 * @param buffers One or more buffers into which the data will be read.
604 * Although the buffers object may be copied as necessary, ownership of the
605 * underlying memory blocks is retained by the caller, which must guarantee
606 * that they remain valid until the completion handler is called.
608 * @param token The @ref completion_token that will be used to produce a
609 * completion handler, which will be called when the read completes.
610 * Potential completion tokens include @ref use_future, @ref use_awaitable,
611 * @ref yield_context, or a function object with the correct completion
612 * signature. The function signature of the completion handler must be:
613 * @code void handler(
614 * const boost::system::error_code& error, // Result of operation.
615 * std::size_t bytes_transferred // Number of bytes read.
617 * Regardless of whether the asynchronous operation completes immediately or
618 * not, the completion handler will not be invoked from within this function.
619 * On immediate completion, invocation of the handler will be performed in a
620 * manner equivalent to using boost::asio::post().
622 * @par Completion Signature
623 * @code void(boost::system::error_code, std::size_t) @endcode
625 * @note The read operation may not read all of the requested number of bytes.
626 * Consider using the @ref async_read function if you need to ensure that the
627 * requested amount of data is read before the asynchronous operation
631 * To read into a single data buffer use the @ref buffer function as follows:
633 * file.async_read_some(boost::asio::buffer(data, size), handler);
635 * See the @ref buffer documentation for information on reading into multiple
636 * buffers in one go, and how to use it with arrays, boost::array or
639 * @par Per-Operation Cancellation
640 * On POSIX or Windows operating systems, this asynchronous operation supports
641 * cancellation for the following boost::asio::cancellation_type values:
643 * @li @c cancellation_type::terminal
645 * @li @c cancellation_type::partial
647 * @li @c cancellation_type::total
649 template <typename MutableBufferSequence,
650 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
651 std::size_t)) ReadToken
652 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
653 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
654 void (boost::system::error_code, std::size_t))
655 async_read_some(const MutableBufferSequence& buffers,
656 BOOST_ASIO_MOVE_ARG(ReadToken) token
657 BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
659 return async_initiate<ReadToken,
660 void (boost::system::error_code, std::size_t)>(
661 initiate_async_read_some(this), token, buffers);
665 // Disallow copying and assignment.
666 basic_stream_file(const basic_stream_file&) BOOST_ASIO_DELETED;
667 basic_stream_file& operator=(const basic_stream_file&) BOOST_ASIO_DELETED;
669 class initiate_async_write_some
672 typedef Executor executor_type;
674 explicit initiate_async_write_some(basic_stream_file* self)
679 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
681 return self_->get_executor();
684 template <typename WriteHandler, typename ConstBufferSequence>
685 void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
686 const ConstBufferSequence& buffers) const
688 // If you get an error on the following line it means that your handler
689 // does not meet the documented type requirements for a WriteHandler.
690 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
692 detail::non_const_lvalue<WriteHandler> handler2(handler);
693 self_->impl_.get_service().async_write_some(
694 self_->impl_.get_implementation(), buffers,
695 handler2.value, self_->impl_.get_executor());
699 basic_stream_file* self_;
702 class initiate_async_read_some
705 typedef Executor executor_type;
707 explicit initiate_async_read_some(basic_stream_file* self)
712 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
714 return self_->get_executor();
717 template <typename ReadHandler, typename MutableBufferSequence>
718 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
719 const MutableBufferSequence& buffers) const
721 // If you get an error on the following line it means that your handler
722 // does not meet the documented type requirements for a ReadHandler.
723 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
725 detail::non_const_lvalue<ReadHandler> handler2(handler);
726 self_->impl_.get_service().async_read_some(
727 self_->impl_.get_implementation(), buffers,
728 handler2.value, self_->impl_.get_executor());
732 basic_stream_file* self_;
739 #include <boost/asio/detail/pop_options.hpp>
741 #endif // defined(BOOST_ASIO_HAS_FILE)
742 // || defined(GENERATING_DOCUMENTATION)
744 #endif // BOOST_ASIO_BASIC_STREAM_FILE_HPP