Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:56

0001 //
0002 // impl/read_at.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_IMPL_READ_AT_HPP
0012 #define BOOST_ASIO_IMPL_READ_AT_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <algorithm>
0019 #include <boost/asio/associator.hpp>
0020 #include <boost/asio/buffer.hpp>
0021 #include <boost/asio/detail/array_fwd.hpp>
0022 #include <boost/asio/detail/base_from_cancellation_state.hpp>
0023 #include <boost/asio/detail/base_from_completion_cond.hpp>
0024 #include <boost/asio/detail/bind_handler.hpp>
0025 #include <boost/asio/detail/consuming_buffers.hpp>
0026 #include <boost/asio/detail/dependent_type.hpp>
0027 #include <boost/asio/detail/handler_cont_helpers.hpp>
0028 #include <boost/asio/detail/handler_tracking.hpp>
0029 #include <boost/asio/detail/handler_type_requirements.hpp>
0030 #include <boost/asio/detail/non_const_lvalue.hpp>
0031 #include <boost/asio/detail/throw_error.hpp>
0032 #include <boost/asio/error.hpp>
0033 
0034 #include <boost/asio/detail/push_options.hpp>
0035 
0036 namespace boost {
0037 namespace asio {
0038 
0039 namespace detail
0040 {
0041   template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
0042       typename MutableBufferIterator, typename CompletionCondition>
0043   std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d,
0044       uint64_t offset, const MutableBufferSequence& buffers,
0045       const MutableBufferIterator&, CompletionCondition completion_condition,
0046       boost::system::error_code& ec)
0047   {
0048     ec = boost::system::error_code();
0049     boost::asio::detail::consuming_buffers<mutable_buffer,
0050         MutableBufferSequence, MutableBufferIterator> tmp(buffers);
0051     while (!tmp.empty())
0052     {
0053       if (std::size_t max_size = detail::adapt_completion_condition_result(
0054             completion_condition(ec, tmp.total_consumed())))
0055       {
0056         tmp.consume(d.read_some_at(offset + tmp.total_consumed(),
0057               tmp.prepare(max_size), ec));
0058       }
0059       else
0060         break;
0061     }
0062     return tmp.total_consumed();
0063   }
0064 } // namespace detail
0065 
0066 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
0067     typename CompletionCondition>
0068 std::size_t read_at(SyncRandomAccessReadDevice& d,
0069     uint64_t offset, const MutableBufferSequence& buffers,
0070     CompletionCondition completion_condition, boost::system::error_code& ec)
0071 {
0072   return detail::read_at_buffer_sequence(d, offset, buffers,
0073       boost::asio::buffer_sequence_begin(buffers),
0074       static_cast<CompletionCondition&&>(completion_condition), ec);
0075 }
0076 
0077 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
0078 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0079     uint64_t offset, const MutableBufferSequence& buffers)
0080 {
0081   boost::system::error_code ec;
0082   std::size_t bytes_transferred = read_at(
0083       d, offset, buffers, transfer_all(), ec);
0084   boost::asio::detail::throw_error(ec, "read_at");
0085   return bytes_transferred;
0086 }
0087 
0088 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
0089 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0090     uint64_t offset, const MutableBufferSequence& buffers,
0091     boost::system::error_code& ec)
0092 {
0093   return read_at(d, offset, buffers, transfer_all(), ec);
0094 }
0095 
0096 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
0097     typename CompletionCondition>
0098 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0099     uint64_t offset, const MutableBufferSequence& buffers,
0100     CompletionCondition completion_condition)
0101 {
0102   boost::system::error_code ec;
0103   std::size_t bytes_transferred = read_at(d, offset, buffers,
0104       static_cast<CompletionCondition&&>(completion_condition), ec);
0105   boost::asio::detail::throw_error(ec, "read_at");
0106   return bytes_transferred;
0107 }
0108 
0109 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0110 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0111 
0112 template <typename SyncRandomAccessReadDevice, typename Allocator,
0113     typename CompletionCondition>
0114 std::size_t read_at(SyncRandomAccessReadDevice& d,
0115     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
0116     CompletionCondition completion_condition, boost::system::error_code& ec)
0117 {
0118   ec = boost::system::error_code();
0119   std::size_t total_transferred = 0;
0120   std::size_t max_size = detail::adapt_completion_condition_result(
0121         completion_condition(ec, total_transferred));
0122   std::size_t bytes_available = read_size_helper(b, max_size);
0123   while (bytes_available > 0)
0124   {
0125     std::size_t bytes_transferred = d.read_some_at(
0126         offset + total_transferred, b.prepare(bytes_available), ec);
0127     b.commit(bytes_transferred);
0128     total_transferred += bytes_transferred;
0129     max_size = detail::adapt_completion_condition_result(
0130           completion_condition(ec, total_transferred));
0131     bytes_available = read_size_helper(b, max_size);
0132   }
0133   return total_transferred;
0134 }
0135 
0136 template <typename SyncRandomAccessReadDevice, typename Allocator>
0137 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0138     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
0139 {
0140   boost::system::error_code ec;
0141   std::size_t bytes_transferred = read_at(
0142       d, offset, b, transfer_all(), ec);
0143   boost::asio::detail::throw_error(ec, "read_at");
0144   return bytes_transferred;
0145 }
0146 
0147 template <typename SyncRandomAccessReadDevice, typename Allocator>
0148 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0149     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
0150     boost::system::error_code& ec)
0151 {
0152   return read_at(d, offset, b, transfer_all(), ec);
0153 }
0154 
0155 template <typename SyncRandomAccessReadDevice, typename Allocator,
0156     typename CompletionCondition>
0157 inline std::size_t read_at(SyncRandomAccessReadDevice& d,
0158     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
0159     CompletionCondition completion_condition)
0160 {
0161   boost::system::error_code ec;
0162   std::size_t bytes_transferred = read_at(d, offset, b,
0163       static_cast<CompletionCondition&&>(completion_condition), ec);
0164   boost::asio::detail::throw_error(ec, "read_at");
0165   return bytes_transferred;
0166 }
0167 
0168 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0169 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0170 
0171 namespace detail
0172 {
0173   template <typename AsyncRandomAccessReadDevice,
0174       typename MutableBufferSequence, typename MutableBufferIterator,
0175       typename CompletionCondition, typename ReadHandler>
0176   class read_at_op
0177     : public base_from_cancellation_state<ReadHandler>,
0178       base_from_completion_cond<CompletionCondition>
0179   {
0180   public:
0181     read_at_op(AsyncRandomAccessReadDevice& device,
0182         uint64_t offset, const MutableBufferSequence& buffers,
0183         CompletionCondition& completion_condition, ReadHandler& handler)
0184       : base_from_cancellation_state<ReadHandler>(
0185           handler, enable_partial_cancellation()),
0186         base_from_completion_cond<CompletionCondition>(completion_condition),
0187         device_(device),
0188         offset_(offset),
0189         buffers_(buffers),
0190         start_(0),
0191         handler_(static_cast<ReadHandler&&>(handler))
0192     {
0193     }
0194 
0195     read_at_op(const read_at_op& other)
0196       : base_from_cancellation_state<ReadHandler>(other),
0197         base_from_completion_cond<CompletionCondition>(other),
0198         device_(other.device_),
0199         offset_(other.offset_),
0200         buffers_(other.buffers_),
0201         start_(other.start_),
0202         handler_(other.handler_)
0203     {
0204     }
0205 
0206     read_at_op(read_at_op&& other)
0207       : base_from_cancellation_state<ReadHandler>(
0208           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0209         base_from_completion_cond<CompletionCondition>(
0210           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0211         device_(other.device_),
0212         offset_(other.offset_),
0213         buffers_(static_cast<buffers_type&&>(other.buffers_)),
0214         start_(other.start_),
0215         handler_(static_cast<ReadHandler&&>(other.handler_))
0216     {
0217     }
0218 
0219     void operator()(boost::system::error_code ec,
0220         std::size_t bytes_transferred, int start = 0)
0221     {
0222       std::size_t max_size;
0223       switch (start_ = start)
0224       {
0225         case 1:
0226         max_size = this->check_for_completion(ec, buffers_.total_consumed());
0227         for (;;)
0228         {
0229           {
0230             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
0231             device_.async_read_some_at(
0232                 offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
0233                 static_cast<read_at_op&&>(*this));
0234           }
0235           return; default:
0236           buffers_.consume(bytes_transferred);
0237           if ((!ec && bytes_transferred == 0) || buffers_.empty())
0238             break;
0239           max_size = this->check_for_completion(ec, buffers_.total_consumed());
0240           if (max_size == 0)
0241             break;
0242           if (this->cancelled() != cancellation_type::none)
0243           {
0244             ec = boost::asio::error::operation_aborted;
0245             break;
0246           }
0247         }
0248 
0249         static_cast<ReadHandler&&>(handler_)(
0250             static_cast<const boost::system::error_code&>(ec),
0251             static_cast<const std::size_t&>(buffers_.total_consumed()));
0252       }
0253     }
0254 
0255   //private:
0256     typedef boost::asio::detail::consuming_buffers<mutable_buffer,
0257         MutableBufferSequence, MutableBufferIterator> buffers_type;
0258 
0259     AsyncRandomAccessReadDevice& device_;
0260     uint64_t offset_;
0261     buffers_type buffers_;
0262     int start_;
0263     ReadHandler handler_;
0264   };
0265 
0266   template <typename AsyncRandomAccessReadDevice,
0267       typename MutableBufferSequence, typename MutableBufferIterator,
0268       typename CompletionCondition, typename ReadHandler>
0269   inline bool asio_handler_is_continuation(
0270       read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
0271         MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
0272   {
0273     return this_handler->start_ == 0 ? true
0274       : boost_asio_handler_cont_helpers::is_continuation(
0275           this_handler->handler_);
0276   }
0277 
0278   template <typename AsyncRandomAccessReadDevice,
0279       typename MutableBufferSequence, typename MutableBufferIterator,
0280       typename CompletionCondition, typename ReadHandler>
0281   inline void start_read_at_op(AsyncRandomAccessReadDevice& d,
0282       uint64_t offset, const MutableBufferSequence& buffers,
0283       const MutableBufferIterator&, CompletionCondition& completion_condition,
0284       ReadHandler& handler)
0285   {
0286     detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
0287       MutableBufferIterator, CompletionCondition, ReadHandler>(
0288         d, offset, buffers, completion_condition, handler)(
0289           boost::system::error_code(), 0, 1);
0290   }
0291 
0292   template <typename AsyncRandomAccessReadDevice>
0293   class initiate_async_read_at
0294   {
0295   public:
0296     typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
0297 
0298     explicit initiate_async_read_at(AsyncRandomAccessReadDevice& device)
0299       : device_(device)
0300     {
0301     }
0302 
0303     executor_type get_executor() const noexcept
0304     {
0305       return device_.get_executor();
0306     }
0307 
0308     template <typename ReadHandler, typename MutableBufferSequence,
0309         typename CompletionCondition>
0310     void operator()(ReadHandler&& handler,
0311         uint64_t offset, const MutableBufferSequence& buffers,
0312         CompletionCondition&& completion_cond) const
0313     {
0314       // If you get an error on the following line it means that your handler
0315       // does not meet the documented type requirements for a ReadHandler.
0316       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0317 
0318       non_const_lvalue<ReadHandler> handler2(handler);
0319       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0320       start_read_at_op(device_, offset, buffers,
0321           boost::asio::buffer_sequence_begin(buffers),
0322           completion_cond2.value, handler2.value);
0323     }
0324 
0325   private:
0326     AsyncRandomAccessReadDevice& device_;
0327   };
0328 } // namespace detail
0329 
0330 #if !defined(GENERATING_DOCUMENTATION)
0331 
0332 template <template <typename, typename> class Associator,
0333     typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
0334     typename MutableBufferIterator, typename CompletionCondition,
0335     typename ReadHandler, typename DefaultCandidate>
0336 struct associator<Associator,
0337     detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
0338       MutableBufferIterator, CompletionCondition, ReadHandler>,
0339     DefaultCandidate>
0340   : Associator<ReadHandler, DefaultCandidate>
0341 {
0342   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0343       const detail::read_at_op<AsyncRandomAccessReadDevice,
0344         MutableBufferSequence, MutableBufferIterator,
0345         CompletionCondition, ReadHandler>& h) noexcept
0346   {
0347     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0348   }
0349 
0350   static auto get(
0351       const detail::read_at_op<AsyncRandomAccessReadDevice,
0352         MutableBufferSequence, MutableBufferIterator,
0353         CompletionCondition, ReadHandler>& h,
0354       const DefaultCandidate& c) noexcept
0355     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0356   {
0357     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0358   }
0359 };
0360 
0361 #endif // !defined(GENERATING_DOCUMENTATION)
0362 
0363 template <typename AsyncRandomAccessReadDevice,
0364     typename MutableBufferSequence, typename CompletionCondition,
0365     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0366       std::size_t)) ReadToken>
0367 inline auto async_read_at(AsyncRandomAccessReadDevice& d,
0368     uint64_t offset, const MutableBufferSequence& buffers,
0369     CompletionCondition completion_condition, ReadToken&& token)
0370   -> decltype(
0371     async_initiate<ReadToken,
0372       void (boost::system::error_code, std::size_t)>(
0373         declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice>>(),
0374         token, offset, buffers,
0375         static_cast<CompletionCondition&&>(completion_condition)))
0376 {
0377   return async_initiate<ReadToken,
0378     void (boost::system::error_code, std::size_t)>(
0379       detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),
0380       token, offset, buffers,
0381       static_cast<CompletionCondition&&>(completion_condition));
0382 }
0383 
0384 template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
0385     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0386       std::size_t)) ReadToken>
0387 inline auto async_read_at(AsyncRandomAccessReadDevice& d,
0388     uint64_t offset, const MutableBufferSequence& buffers, ReadToken&& token)
0389   -> decltype(
0390     async_initiate<ReadToken,
0391       void (boost::system::error_code, std::size_t)>(
0392         declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice>>(),
0393         token, offset, buffers, transfer_all()))
0394 {
0395   return async_initiate<ReadToken,
0396     void (boost::system::error_code, std::size_t)>(
0397       detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),
0398       token, offset, buffers, transfer_all());
0399 }
0400 
0401 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0402 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0403 
0404 namespace detail
0405 {
0406   template <typename AsyncRandomAccessReadDevice, typename Allocator,
0407       typename CompletionCondition, typename ReadHandler>
0408   class read_at_streambuf_op
0409     : public base_from_cancellation_state<ReadHandler>,
0410       base_from_completion_cond<CompletionCondition>
0411   {
0412   public:
0413     read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
0414         uint64_t offset, basic_streambuf<Allocator>& streambuf,
0415         CompletionCondition& completion_condition, ReadHandler& handler)
0416       : base_from_cancellation_state<ReadHandler>(
0417           handler, enable_partial_cancellation()),
0418         base_from_completion_cond<CompletionCondition>(completion_condition),
0419         device_(device),
0420         offset_(offset),
0421         streambuf_(streambuf),
0422         start_(0),
0423         total_transferred_(0),
0424         handler_(static_cast<ReadHandler&&>(handler))
0425     {
0426     }
0427 
0428     read_at_streambuf_op(const read_at_streambuf_op& other)
0429       : base_from_cancellation_state<ReadHandler>(other),
0430         base_from_completion_cond<CompletionCondition>(other),
0431         device_(other.device_),
0432         offset_(other.offset_),
0433         streambuf_(other.streambuf_),
0434         start_(other.start_),
0435         total_transferred_(other.total_transferred_),
0436         handler_(other.handler_)
0437     {
0438     }
0439 
0440     read_at_streambuf_op(read_at_streambuf_op&& other)
0441       : base_from_cancellation_state<ReadHandler>(
0442           static_cast<base_from_cancellation_state<ReadHandler>&&>(other)),
0443         base_from_completion_cond<CompletionCondition>(
0444           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0445         device_(other.device_),
0446         offset_(other.offset_),
0447         streambuf_(other.streambuf_),
0448         start_(other.start_),
0449         total_transferred_(other.total_transferred_),
0450         handler_(static_cast<ReadHandler&&>(other.handler_))
0451     {
0452     }
0453 
0454     void operator()(boost::system::error_code ec,
0455         std::size_t bytes_transferred, int start = 0)
0456     {
0457       std::size_t max_size, bytes_available;
0458       switch (start_ = start)
0459       {
0460         case 1:
0461         max_size = this->check_for_completion(ec, total_transferred_);
0462         bytes_available = read_size_helper(streambuf_, max_size);
0463         for (;;)
0464         {
0465           {
0466             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
0467             device_.async_read_some_at(offset_ + total_transferred_,
0468                 streambuf_.prepare(bytes_available),
0469                 static_cast<read_at_streambuf_op&&>(*this));
0470           }
0471           return; default:
0472           total_transferred_ += bytes_transferred;
0473           streambuf_.commit(bytes_transferred);
0474           max_size = this->check_for_completion(ec, total_transferred_);
0475           bytes_available = read_size_helper(streambuf_, max_size);
0476           if ((!ec && bytes_transferred == 0) || bytes_available == 0)
0477             break;
0478           if (this->cancelled() != cancellation_type::none)
0479           {
0480             ec = boost::asio::error::operation_aborted;
0481             break;
0482           }
0483         }
0484 
0485         static_cast<ReadHandler&&>(handler_)(
0486             static_cast<const boost::system::error_code&>(ec),
0487             static_cast<const std::size_t&>(total_transferred_));
0488       }
0489     }
0490 
0491   //private:
0492     AsyncRandomAccessReadDevice& device_;
0493     uint64_t offset_;
0494     boost::asio::basic_streambuf<Allocator>& streambuf_;
0495     int start_;
0496     std::size_t total_transferred_;
0497     ReadHandler handler_;
0498   };
0499 
0500   template <typename AsyncRandomAccessReadDevice, typename Allocator,
0501       typename CompletionCondition, typename ReadHandler>
0502   inline bool asio_handler_is_continuation(
0503       read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
0504         CompletionCondition, ReadHandler>* this_handler)
0505   {
0506     return this_handler->start_ == 0 ? true
0507       : boost_asio_handler_cont_helpers::is_continuation(
0508           this_handler->handler_);
0509   }
0510 
0511   template <typename AsyncRandomAccessReadDevice>
0512   class initiate_async_read_at_streambuf
0513   {
0514   public:
0515     typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
0516 
0517     explicit initiate_async_read_at_streambuf(
0518         AsyncRandomAccessReadDevice& device)
0519       : device_(device)
0520     {
0521     }
0522 
0523     executor_type get_executor() const noexcept
0524     {
0525       return device_.get_executor();
0526     }
0527 
0528     template <typename ReadHandler,
0529         typename Allocator, typename CompletionCondition>
0530     void operator()(ReadHandler&& handler,
0531         uint64_t offset, basic_streambuf<Allocator>* b,
0532         CompletionCondition&& completion_cond) const
0533     {
0534       // If you get an error on the following line it means that your handler
0535       // does not meet the documented type requirements for a ReadHandler.
0536       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
0537 
0538       non_const_lvalue<ReadHandler> handler2(handler);
0539       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0540       read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
0541         CompletionCondition, decay_t<ReadHandler>>(
0542           device_, offset, *b, completion_cond2.value, handler2.value)(
0543             boost::system::error_code(), 0, 1);
0544     }
0545 
0546   private:
0547     AsyncRandomAccessReadDevice& device_;
0548   };
0549 } // namespace detail
0550 
0551 #if !defined(GENERATING_DOCUMENTATION)
0552 
0553 template <template <typename, typename> class Associator,
0554     typename AsyncRandomAccessReadDevice, typename Executor,
0555     typename CompletionCondition, typename ReadHandler,
0556     typename DefaultCandidate>
0557 struct associator<Associator,
0558     detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
0559       Executor, CompletionCondition, ReadHandler>,
0560     DefaultCandidate>
0561   : Associator<ReadHandler, DefaultCandidate>
0562 {
0563   static typename Associator<ReadHandler, DefaultCandidate>::type get(
0564       const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
0565         Executor, CompletionCondition, ReadHandler>& h) noexcept
0566   {
0567     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);
0568   }
0569 
0570   static auto get(
0571       const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
0572         Executor, CompletionCondition, ReadHandler>& h,
0573       const DefaultCandidate& c) noexcept
0574     -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))
0575   {
0576     return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
0577   }
0578 };
0579 
0580 #endif // !defined(GENERATING_DOCUMENTATION)
0581 
0582 template <typename AsyncRandomAccessReadDevice,
0583     typename Allocator, typename CompletionCondition,
0584     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0585       std::size_t)) ReadToken>
0586 inline auto async_read_at(AsyncRandomAccessReadDevice& d,
0587     uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
0588     CompletionCondition completion_condition, ReadToken&& token)
0589   -> decltype(
0590     async_initiate<ReadToken,
0591       void (boost::system::error_code, std::size_t)>(
0592         declval<detail::initiate_async_read_at_streambuf<
0593           AsyncRandomAccessReadDevice>>(),
0594         token, offset, &b,
0595         static_cast<CompletionCondition&&>(completion_condition)))
0596 {
0597   return async_initiate<ReadToken,
0598     void (boost::system::error_code, std::size_t)>(
0599       detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
0600       token, offset, &b,
0601       static_cast<CompletionCondition&&>(completion_condition));
0602 }
0603 
0604 template <typename AsyncRandomAccessReadDevice, typename Allocator,
0605     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0606       std::size_t)) ReadToken>
0607 inline auto async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset,
0608     boost::asio::basic_streambuf<Allocator>& b, ReadToken&& token)
0609   -> decltype(
0610     async_initiate<ReadToken,
0611       void (boost::system::error_code, std::size_t)>(
0612         declval<detail::initiate_async_read_at_streambuf<
0613           AsyncRandomAccessReadDevice>>(),
0614         token, offset, &b, transfer_all()))
0615 {
0616   return async_initiate<ReadToken,
0617     void (boost::system::error_code, std::size_t)>(
0618       detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
0619       token, offset, &b, transfer_all());
0620 }
0621 
0622 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0623 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0624 
0625 } // namespace asio
0626 } // namespace boost
0627 
0628 #include <boost/asio/detail/pop_options.hpp>
0629 
0630 #endif // BOOST_ASIO_IMPL_READ_AT_HPP