Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:06

0001 //
0002 // basic_stream_file.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_BASIC_STREAM_FILE_HPP
0012 #define BOOST_ASIO_BASIC_STREAM_FILE_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if defined(BOOST_ASIO_HAS_FILE) \
0021   || defined(GENERATING_DOCUMENTATION)
0022 
0023 #include <cstddef>
0024 #include <boost/asio/async_result.hpp>
0025 #include <boost/asio/basic_file.hpp>
0026 #include <boost/asio/detail/handler_type_requirements.hpp>
0027 #include <boost/asio/detail/non_const_lvalue.hpp>
0028 #include <boost/asio/detail/throw_error.hpp>
0029 #include <boost/asio/error.hpp>
0030 
0031 #include <boost/asio/detail/push_options.hpp>
0032 
0033 namespace boost {
0034 namespace asio {
0035 
0036 #if !defined(BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL)
0037 #define BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL
0038 
0039 // Forward declaration with defaulted arguments.
0040 template <typename Executor = any_io_executor>
0041 class basic_stream_file;
0042 
0043 #endif // !defined(BOOST_ASIO_BASIC_STREAM_FILE_FWD_DECL)
0044 
0045 /// Provides stream-oriented file functionality.
0046 /**
0047  * The basic_stream_file class template provides asynchronous and blocking
0048  * stream-oriented file functionality.
0049  *
0050  * @par Thread Safety
0051  * @e Distinct @e objects: Safe.@n
0052  * @e Shared @e objects: Unsafe.
0053  *
0054  * @par Concepts:
0055  * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
0056  */
0057 template <typename Executor>
0058 class basic_stream_file
0059   : public basic_file<Executor>
0060 {
0061 private:
0062   class initiate_async_write_some;
0063   class initiate_async_read_some;
0064 
0065 public:
0066   /// The type of the executor associated with the object.
0067   typedef Executor executor_type;
0068 
0069   /// Rebinds the file type to another executor.
0070   template <typename Executor1>
0071   struct rebind_executor
0072   {
0073     /// The file type when rebound to the specified executor.
0074     typedef basic_stream_file<Executor1> other;
0075   };
0076 
0077   /// The native representation of a file.
0078 #if defined(GENERATING_DOCUMENTATION)
0079   typedef implementation_defined native_handle_type;
0080 #else
0081   typedef typename basic_file<Executor>::native_handle_type native_handle_type;
0082 #endif
0083 
0084   /// Construct a basic_stream_file without opening it.
0085   /**
0086    * This constructor initialises a file without opening it. The file needs to
0087    * be opened before data can be read from or or written to it.
0088    *
0089    * @param ex The I/O executor that the file will use, by default, to
0090    * dispatch handlers for any asynchronous operations performed on the file.
0091    */
0092   explicit basic_stream_file(const executor_type& ex)
0093     : basic_file<Executor>(ex)
0094   {
0095     this->impl_.get_service().set_is_stream(
0096         this->impl_.get_implementation(), true);
0097   }
0098 
0099   /// Construct a basic_stream_file without opening it.
0100   /**
0101    * This constructor initialises a file without opening it. The file needs to
0102    * be opened before data can be read from or or written to it.
0103    *
0104    * @param context An execution context which provides the I/O executor that
0105    * the file will use, by default, to dispatch handlers for any asynchronous
0106    * operations performed on the file.
0107    */
0108   template <typename ExecutionContext>
0109   explicit basic_stream_file(ExecutionContext& context,
0110       constraint_t<
0111         is_convertible<ExecutionContext&, execution_context&>::value,
0112         defaulted_constraint
0113       > = defaulted_constraint())
0114     : basic_file<Executor>(context)
0115   {
0116     this->impl_.get_service().set_is_stream(
0117         this->impl_.get_implementation(), true);
0118   }
0119 
0120   /// Construct and open a basic_stream_file.
0121   /**
0122    * This constructor initialises and opens a file.
0123    *
0124    * @param ex The I/O executor that the file will use, by default, to
0125    * dispatch handlers for any asynchronous operations performed on the file.
0126    *
0127    * @param path The path name identifying the file to be opened.
0128    *
0129    * @param open_flags A set of flags that determine how the file should be
0130    * opened.
0131    *
0132    * @throws boost::system::system_error Thrown on failure.
0133    */
0134   basic_stream_file(const executor_type& ex,
0135       const char* path, file_base::flags open_flags)
0136     : basic_file<Executor>(ex)
0137   {
0138     boost::system::error_code ec;
0139     this->impl_.get_service().set_is_stream(
0140         this->impl_.get_implementation(), true);
0141     this->impl_.get_service().open(
0142         this->impl_.get_implementation(),
0143         path, open_flags, ec);
0144     boost::asio::detail::throw_error(ec, "open");
0145   }
0146 
0147   /// Construct and open a basic_stream_file.
0148   /**
0149    * This constructor initialises and opens a file.
0150    *
0151    * @param context An execution context which provides the I/O executor that
0152    * the file will use, by default, to dispatch handlers for any asynchronous
0153    * operations performed on the file.
0154    *
0155    * @param path The path name identifying the file to be opened.
0156    *
0157    * @param open_flags A set of flags that determine how the file should be
0158    * opened.
0159    *
0160    * @throws boost::system::system_error Thrown on failure.
0161    */
0162   template <typename ExecutionContext>
0163   basic_stream_file(ExecutionContext& context,
0164       const char* path, file_base::flags open_flags,
0165       constraint_t<
0166         is_convertible<ExecutionContext&, execution_context&>::value,
0167         defaulted_constraint
0168       > = defaulted_constraint())
0169     : basic_file<Executor>(context)
0170   {
0171     boost::system::error_code ec;
0172     this->impl_.get_service().set_is_stream(
0173         this->impl_.get_implementation(), true);
0174     this->impl_.get_service().open(
0175         this->impl_.get_implementation(),
0176         path, open_flags, ec);
0177     boost::asio::detail::throw_error(ec, "open");
0178   }
0179 
0180   /// Construct and open a basic_stream_file.
0181   /**
0182    * This constructor initialises and opens a file.
0183    *
0184    * @param ex The I/O executor that the file will use, by default, to
0185    * dispatch handlers for any asynchronous operations performed on the file.
0186    *
0187    * @param path The path name identifying the file to be opened.
0188    *
0189    * @param open_flags A set of flags that determine how the file should be
0190    * opened.
0191    *
0192    * @throws boost::system::system_error Thrown on failure.
0193    */
0194   basic_stream_file(const executor_type& ex,
0195       const std::string& path, file_base::flags open_flags)
0196     : basic_file<Executor>(ex)
0197   {
0198     boost::system::error_code ec;
0199     this->impl_.get_service().set_is_stream(
0200         this->impl_.get_implementation(), true);
0201     this->impl_.get_service().open(
0202         this->impl_.get_implementation(),
0203         path.c_str(), open_flags, ec);
0204     boost::asio::detail::throw_error(ec, "open");
0205   }
0206 
0207   /// Construct and open a basic_stream_file.
0208   /**
0209    * This constructor initialises and opens a file.
0210    *
0211    * @param context An execution context which provides the I/O executor that
0212    * the file will use, by default, to dispatch handlers for any asynchronous
0213    * operations performed on the file.
0214    *
0215    * @param path The path name identifying the file to be opened.
0216    *
0217    * @param open_flags A set of flags that determine how the file should be
0218    * opened.
0219    *
0220    * @throws boost::system::system_error Thrown on failure.
0221    */
0222   template <typename ExecutionContext>
0223   basic_stream_file(ExecutionContext& context,
0224       const std::string& path, file_base::flags open_flags,
0225       constraint_t<
0226         is_convertible<ExecutionContext&, execution_context&>::value,
0227         defaulted_constraint
0228       > = defaulted_constraint())
0229     : basic_file<Executor>(context)
0230   {
0231     boost::system::error_code ec;
0232     this->impl_.get_service().set_is_stream(
0233         this->impl_.get_implementation(), true);
0234     this->impl_.get_service().open(
0235         this->impl_.get_implementation(),
0236         path.c_str(), open_flags, ec);
0237     boost::asio::detail::throw_error(ec, "open");
0238   }
0239 
0240   /// Construct a basic_stream_file on an existing native file.
0241   /**
0242    * This constructor initialises a stream file object to hold an existing
0243    * native file.
0244    *
0245    * @param ex The I/O executor that the file will use, by default, to
0246    * dispatch handlers for any asynchronous operations performed on the file.
0247    *
0248    * @param native_file The new underlying file implementation.
0249    *
0250    * @throws boost::system::system_error Thrown on failure.
0251    */
0252   basic_stream_file(const executor_type& ex,
0253       const native_handle_type& native_file)
0254     : basic_file<Executor>(ex, native_file)
0255   {
0256     this->impl_.get_service().set_is_stream(
0257         this->impl_.get_implementation(), true);
0258   }
0259 
0260   /// Construct a basic_stream_file on an existing native file.
0261   /**
0262    * This constructor initialises a stream file object to hold an existing
0263    * native file.
0264    *
0265    * @param context An execution context which provides the I/O executor that
0266    * the file will use, by default, to dispatch handlers for any asynchronous
0267    * operations performed on the file.
0268    *
0269    * @param native_file The new underlying file implementation.
0270    *
0271    * @throws boost::system::system_error Thrown on failure.
0272    */
0273   template <typename ExecutionContext>
0274   basic_stream_file(ExecutionContext& context,
0275       const native_handle_type& native_file,
0276       constraint_t<
0277         is_convertible<ExecutionContext&, execution_context&>::value,
0278         defaulted_constraint
0279       > = defaulted_constraint())
0280     : basic_file<Executor>(context, native_file)
0281   {
0282     this->impl_.get_service().set_is_stream(
0283         this->impl_.get_implementation(), true);
0284   }
0285 
0286   /// Move-construct a basic_stream_file from another.
0287   /**
0288    * This constructor moves a stream file from one object to another.
0289    *
0290    * @param other The other basic_stream_file object from which the move
0291    * will occur.
0292    *
0293    * @note Following the move, the moved-from object is in the same state as if
0294    * constructed using the @c basic_stream_file(const executor_type&)
0295    * constructor.
0296    */
0297   basic_stream_file(basic_stream_file&& other) noexcept
0298     : basic_file<Executor>(std::move(other))
0299   {
0300   }
0301 
0302   /// Move-assign a basic_stream_file from another.
0303   /**
0304    * This assignment operator moves a stream file from one object to another.
0305    *
0306    * @param other The other basic_stream_file object from which the move
0307    * will occur.
0308    *
0309    * @note Following the move, the moved-from object is in the same state as if
0310    * constructed using the @c basic_stream_file(const executor_type&)
0311    * constructor.
0312    */
0313   basic_stream_file& operator=(basic_stream_file&& other)
0314   {
0315     basic_file<Executor>::operator=(std::move(other));
0316     return *this;
0317   }
0318 
0319   /// Move-construct a basic_stream_file from a file of another executor
0320   /// type.
0321   /**
0322    * This constructor moves a stream file from one object to another.
0323    *
0324    * @param other The other basic_stream_file object from which the move
0325    * will occur.
0326    *
0327    * @note Following the move, the moved-from object is in the same state as if
0328    * constructed using the @c basic_stream_file(const executor_type&)
0329    * constructor.
0330    */
0331   template <typename Executor1>
0332   basic_stream_file(basic_stream_file<Executor1>&& other,
0333       constraint_t<
0334         is_convertible<Executor1, Executor>::value,
0335         defaulted_constraint
0336       > = defaulted_constraint())
0337     : basic_file<Executor>(std::move(other))
0338   {
0339   }
0340 
0341   /// Move-assign a basic_stream_file from a file of another executor type.
0342   /**
0343    * This assignment operator moves a stream file from one object to another.
0344    *
0345    * @param other The other basic_stream_file object from which the move
0346    * will occur.
0347    *
0348    * @note Following the move, the moved-from object is in the same state as if
0349    * constructed using the @c basic_stream_file(const executor_type&)
0350    * constructor.
0351    */
0352   template <typename Executor1>
0353   constraint_t<
0354     is_convertible<Executor1, Executor>::value,
0355     basic_stream_file&
0356   > operator=(basic_stream_file<Executor1>&& other)
0357   {
0358     basic_file<Executor>::operator=(std::move(other));
0359     return *this;
0360   }
0361 
0362   /// Destroys the file.
0363   /**
0364    * This function destroys the file, cancelling any outstanding asynchronous
0365    * operations associated with the file as if by calling @c cancel.
0366    */
0367   ~basic_stream_file()
0368   {
0369   }
0370 
0371   /// Seek to a position in the file.
0372   /**
0373    * This function updates the current position in the file.
0374    *
0375    * @param offset The requested position in the file, relative to @c whence.
0376    *
0377    * @param whence One of @c seek_set, @c seek_cur or @c seek_end.
0378    *
0379    * @returns The new position relative to the beginning of the file.
0380    *
0381    * @throws boost::system::system_error Thrown on failure.
0382    */
0383   uint64_t seek(int64_t offset, file_base::seek_basis whence)
0384   {
0385     boost::system::error_code ec;
0386     uint64_t n = this->impl_.get_service().seek(
0387         this->impl_.get_implementation(), offset, whence, ec);
0388     boost::asio::detail::throw_error(ec, "seek");
0389     return n;
0390   }
0391 
0392   /// Seek to a position in the file.
0393   /**
0394    * This function updates the current position in the file.
0395    *
0396    * @param offset The requested position in the file, relative to @c whence.
0397    *
0398    * @param whence One of @c seek_set, @c seek_cur or @c seek_end.
0399    *
0400    * @param ec Set to indicate what error occurred, if any.
0401    *
0402    * @returns The new position relative to the beginning of the file.
0403    */
0404   uint64_t seek(int64_t offset, file_base::seek_basis whence,
0405       boost::system::error_code& ec)
0406   {
0407     return this->impl_.get_service().seek(
0408         this->impl_.get_implementation(), offset, whence, ec);
0409   }
0410 
0411   /// Write some data to the file.
0412   /**
0413    * This function is used to write data to the stream file. The function call
0414    * will block until one or more bytes of the data has been written
0415    * successfully, or until an error occurs.
0416    *
0417    * @param buffers One or more data buffers to be written to the file.
0418    *
0419    * @returns The number of bytes written.
0420    *
0421    * @throws boost::system::system_error Thrown on failure. An error code of
0422    * boost::asio::error::eof indicates that the end of the file was reached.
0423    *
0424    * @note The write_some operation may not transmit all of the data to the
0425    * peer. Consider using the @ref write function if you need to ensure that
0426    * all data is written before the blocking operation completes.
0427    *
0428    * @par Example
0429    * To write a single data buffer use the @ref buffer function as follows:
0430    * @code
0431    * file.write_some(boost::asio::buffer(data, size));
0432    * @endcode
0433    * See the @ref buffer documentation for information on writing multiple
0434    * buffers in one go, and how to use it with arrays, boost::array or
0435    * std::vector.
0436    */
0437   template <typename ConstBufferSequence>
0438   std::size_t write_some(const ConstBufferSequence& buffers)
0439   {
0440     boost::system::error_code ec;
0441     std::size_t s = this->impl_.get_service().write_some(
0442         this->impl_.get_implementation(), buffers, ec);
0443     boost::asio::detail::throw_error(ec, "write_some");
0444     return s;
0445   }
0446 
0447   /// Write some data to the file.
0448   /**
0449    * This function is used to write data to the stream file. The function call
0450    * will block until one or more bytes of the data has been written
0451    * successfully, or until an error occurs.
0452    *
0453    * @param buffers One or more data buffers to be written to the file.
0454    *
0455    * @param ec Set to indicate what error occurred, if any.
0456    *
0457    * @returns The number of bytes written. Returns 0 if an error occurred.
0458    *
0459    * @note The write_some operation may not transmit all of the data to the
0460    * peer. Consider using the @ref write function if you need to ensure that
0461    * all data is written before the blocking operation completes.
0462    */
0463   template <typename ConstBufferSequence>
0464   std::size_t write_some(const ConstBufferSequence& buffers,
0465       boost::system::error_code& ec)
0466   {
0467     return this->impl_.get_service().write_some(
0468         this->impl_.get_implementation(), buffers, ec);
0469   }
0470 
0471   /// Start an asynchronous write.
0472   /**
0473    * This function is used to asynchronously write data to the stream file.
0474    * It is an initiating function for an @ref asynchronous_operation, and always
0475    * returns immediately.
0476    *
0477    * @param buffers One or more data buffers to be written to the file.
0478    * Although the buffers object may be copied as necessary, ownership of the
0479    * underlying memory blocks is retained by the caller, which must guarantee
0480    * that they remain valid until the completion handler is called.
0481    *
0482    * @param token The @ref completion_token that will be used to produce a
0483    * completion handler, which will be called when the write completes.
0484    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0485    * @ref yield_context, or a function object with the correct completion
0486    * signature. The function signature of the completion handler must be:
0487    * @code void handler(
0488    *   const boost::system::error_code& error, // Result of operation.
0489    *   std::size_t bytes_transferred // Number of bytes written.
0490    * ); @endcode
0491    * Regardless of whether the asynchronous operation completes immediately or
0492    * not, the completion handler will not be invoked from within this function.
0493    * On immediate completion, invocation of the handler will be performed in a
0494    * manner equivalent to using boost::asio::post().
0495    *
0496    * @par Completion Signature
0497    * @code void(boost::system::error_code, std::size_t) @endcode
0498    *
0499    * @note The write operation may not transmit all of the data to the peer.
0500    * Consider using the @ref async_write function if you need to ensure that all
0501    * data is written before the asynchronous operation completes.
0502    *
0503    * @par Example
0504    * To write a single data buffer use the @ref buffer function as follows:
0505    * @code
0506    * file.async_write_some(boost::asio::buffer(data, size), handler);
0507    * @endcode
0508    * See the @ref buffer documentation for information on writing multiple
0509    * buffers in one go, and how to use it with arrays, boost::array or
0510    * std::vector.
0511    *
0512    * @par Per-Operation Cancellation
0513    * On POSIX or Windows operating systems, this asynchronous operation supports
0514    * cancellation for the following boost::asio::cancellation_type values:
0515    *
0516    * @li @c cancellation_type::terminal
0517    *
0518    * @li @c cancellation_type::partial
0519    *
0520    * @li @c cancellation_type::total
0521    */
0522   template <typename ConstBufferSequence,
0523       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0524         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0525   auto async_write_some(const ConstBufferSequence& buffers,
0526       WriteToken&& token = default_completion_token_t<executor_type>())
0527     -> decltype(
0528       async_initiate<WriteToken,
0529         void (boost::system::error_code, std::size_t)>(
0530           declval<initiate_async_write_some>(), token, buffers))
0531   {
0532     return async_initiate<WriteToken,
0533       void (boost::system::error_code, std::size_t)>(
0534         initiate_async_write_some(this), token, buffers);
0535   }
0536 
0537   /// Read some data from the file.
0538   /**
0539    * This function is used to read data from the stream file. The function
0540    * call will block until one or more bytes of data has been read successfully,
0541    * or until an error occurs.
0542    *
0543    * @param buffers One or more buffers into which the data will be read.
0544    *
0545    * @returns The number of bytes read.
0546    *
0547    * @throws boost::system::system_error Thrown on failure. An error code of
0548    * boost::asio::error::eof indicates that the end of the file was reached.
0549    *
0550    * @note The read_some operation may not read all of the requested number of
0551    * bytes. Consider using the @ref read function if you need to ensure that
0552    * the requested amount of data is read before the blocking operation
0553    * completes.
0554    *
0555    * @par Example
0556    * To read into a single data buffer use the @ref buffer function as follows:
0557    * @code
0558    * file.read_some(boost::asio::buffer(data, size));
0559    * @endcode
0560    * See the @ref buffer documentation for information on reading into multiple
0561    * buffers in one go, and how to use it with arrays, boost::array or
0562    * std::vector.
0563    */
0564   template <typename MutableBufferSequence>
0565   std::size_t read_some(const MutableBufferSequence& buffers)
0566   {
0567     boost::system::error_code ec;
0568     std::size_t s = this->impl_.get_service().read_some(
0569         this->impl_.get_implementation(), buffers, ec);
0570     boost::asio::detail::throw_error(ec, "read_some");
0571     return s;
0572   }
0573 
0574   /// Read some data from the file.
0575   /**
0576    * This function is used to read data from the stream file. The function
0577    * call will block until one or more bytes of data has been read successfully,
0578    * or until an error occurs.
0579    *
0580    * @param buffers One or more buffers into which the data will be read.
0581    *
0582    * @param ec Set to indicate what error occurred, if any.
0583    *
0584    * @returns The number of bytes read. Returns 0 if an error occurred.
0585    *
0586    * @note The read_some operation may not read all of the requested number of
0587    * bytes. Consider using the @ref read function if you need to ensure that
0588    * the requested amount of data is read before the blocking operation
0589    * completes.
0590    */
0591   template <typename MutableBufferSequence>
0592   std::size_t read_some(const MutableBufferSequence& buffers,
0593       boost::system::error_code& ec)
0594   {
0595     return this->impl_.get_service().read_some(
0596         this->impl_.get_implementation(), buffers, ec);
0597   }
0598 
0599   /// Start an asynchronous read.
0600   /**
0601    * This function is used to asynchronously read data from the stream file.
0602    * It is an initiating function for an @ref asynchronous_operation, and always
0603    * returns immediately.
0604    *
0605    * @param buffers One or more buffers into which the data will be read.
0606    * Although the buffers object may be copied as necessary, ownership of the
0607    * underlying memory blocks is retained by the caller, which must guarantee
0608    * that they remain valid until the completion handler is called.
0609    *
0610    * @param token The @ref completion_token that will be used to produce a
0611    * completion handler, which will be called when the read completes.
0612    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0613    * @ref yield_context, or a function object with the correct completion
0614    * signature. The function signature of the completion handler must be:
0615    * @code void handler(
0616    *   const boost::system::error_code& error, // Result of operation.
0617    *   std::size_t bytes_transferred // Number of bytes read.
0618    * ); @endcode
0619    * Regardless of whether the asynchronous operation completes immediately or
0620    * not, the completion handler will not be invoked from within this function.
0621    * On immediate completion, invocation of the handler will be performed in a
0622    * manner equivalent to using boost::asio::post().
0623    *
0624    * @par Completion Signature
0625    * @code void(boost::system::error_code, std::size_t) @endcode
0626    *
0627    * @note The read operation may not read all of the requested number of bytes.
0628    * Consider using the @ref async_read function if you need to ensure that the
0629    * requested amount of data is read before the asynchronous operation
0630    * completes.
0631    *
0632    * @par Example
0633    * To read into a single data buffer use the @ref buffer function as follows:
0634    * @code
0635    * file.async_read_some(boost::asio::buffer(data, size), handler);
0636    * @endcode
0637    * See the @ref buffer documentation for information on reading into multiple
0638    * buffers in one go, and how to use it with arrays, boost::array or
0639    * std::vector.
0640    *
0641    * @par Per-Operation Cancellation
0642    * On POSIX or Windows operating systems, this asynchronous operation supports
0643    * cancellation for the following boost::asio::cancellation_type values:
0644    *
0645    * @li @c cancellation_type::terminal
0646    *
0647    * @li @c cancellation_type::partial
0648    *
0649    * @li @c cancellation_type::total
0650    */
0651   template <typename MutableBufferSequence,
0652       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0653         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0654   auto async_read_some(const MutableBufferSequence& buffers,
0655       ReadToken&& token = default_completion_token_t<executor_type>())
0656     -> decltype(
0657       async_initiate<ReadToken,
0658         void (boost::system::error_code, std::size_t)>(
0659           declval<initiate_async_read_some>(), token, buffers))
0660   {
0661     return async_initiate<ReadToken,
0662       void (boost::system::error_code, std::size_t)>(
0663         initiate_async_read_some(this), token, buffers);
0664   }
0665 
0666 private:
0667   // Disallow copying and assignment.
0668   basic_stream_file(const basic_stream_file&) = delete;
0669   basic_stream_file& operator=(const basic_stream_file&) = delete;
0670 
0671   class initiate_async_write_some
0672   {
0673   public:
0674     typedef Executor executor_type;
0675 
0676     explicit initiate_async_write_some(basic_stream_file* self)
0677       : self_(self)
0678     {
0679     }
0680 
0681     const executor_type& get_executor() const noexcept
0682     {
0683       return self_->get_executor();
0684     }
0685 
0686     template <typename WriteHandler, typename ConstBufferSequence>
0687     void operator()(WriteHandler&& handler,
0688         const ConstBufferSequence& buffers) const
0689     {
0690       // If you get an error on the following line it means that your handler
0691       // does not meet the documented type requirements for a WriteHandler.
0692       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0693 
0694       detail::non_const_lvalue<WriteHandler> handler2(handler);
0695       self_->impl_.get_service().async_write_some(
0696           self_->impl_.get_implementation(), buffers,
0697           handler2.value, self_->impl_.get_executor());
0698     }
0699 
0700   private:
0701     basic_stream_file* self_;
0702   };
0703 
0704   class initiate_async_read_some
0705   {
0706   public:
0707     typedef Executor executor_type;
0708 
0709     explicit initiate_async_read_some(basic_stream_file* self)
0710       : self_(self)
0711     {
0712     }
0713 
0714     const executor_type& get_executor() const noexcept
0715     {
0716       return self_->get_executor();
0717     }
0718 
0719     template <typename ReadHandler, typename MutableBufferSequence>
0720     void operator()(ReadHandler&& handler,
0721         const MutableBufferSequence& buffers) const
0722     {
0723       // If you get an error on the following line it means that your handler
0724       // does not meet the documented type requirements for a ReadHandler.
0725       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0726 
0727       detail::non_const_lvalue<ReadHandler> handler2(handler);
0728       self_->impl_.get_service().async_read_some(
0729           self_->impl_.get_implementation(), buffers,
0730           handler2.value, self_->impl_.get_executor());
0731     }
0732 
0733   private:
0734     basic_stream_file* self_;
0735   };
0736 };
0737 
0738 } // namespace asio
0739 } // namespace boost
0740 
0741 #include <boost/asio/detail/pop_options.hpp>
0742 
0743 #endif // defined(BOOST_ASIO_HAS_FILE)
0744        //   || defined(GENERATING_DOCUMENTATION)
0745 
0746 #endif // BOOST_ASIO_BASIC_STREAM_FILE_HPP