]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/impl/read_at.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / impl / read_at.hpp
CommitLineData
7c673cae
FG
1//
2// impl/read_at.hpp
3// ~~~~~~~~~~~~~~~~
4//
1e59de90 5// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7c673cae
FG
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_IMPL_READ_AT_HPP
12#define BOOST_ASIO_IMPL_READ_AT_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <algorithm>
1e59de90 19#include <boost/asio/associator.hpp>
7c673cae
FG
20#include <boost/asio/buffer.hpp>
21#include <boost/asio/completion_condition.hpp>
22#include <boost/asio/detail/array_fwd.hpp>
1e59de90 23#include <boost/asio/detail/base_from_cancellation_state.hpp>
7c673cae
FG
24#include <boost/asio/detail/base_from_completion_cond.hpp>
25#include <boost/asio/detail/bind_handler.hpp>
26#include <boost/asio/detail/consuming_buffers.hpp>
27#include <boost/asio/detail/dependent_type.hpp>
28#include <boost/asio/detail/handler_alloc_helpers.hpp>
29#include <boost/asio/detail/handler_cont_helpers.hpp>
30#include <boost/asio/detail/handler_invoke_helpers.hpp>
20effc67 31#include <boost/asio/detail/handler_tracking.hpp>
7c673cae 32#include <boost/asio/detail/handler_type_requirements.hpp>
92f5a8d4 33#include <boost/asio/detail/non_const_lvalue.hpp>
7c673cae
FG
34#include <boost/asio/detail/throw_error.hpp>
35#include <boost/asio/error.hpp>
36
37#include <boost/asio/detail/push_options.hpp>
38
39namespace boost {
40namespace asio {
41
b32b8144
FG
42namespace detail
43{
44 template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
45 typename MutableBufferIterator, typename CompletionCondition>
46 std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d,
47 uint64_t offset, const MutableBufferSequence& buffers,
48 const MutableBufferIterator&, CompletionCondition completion_condition,
49 boost::system::error_code& ec)
50 {
51 ec = boost::system::error_code();
52 boost::asio::detail::consuming_buffers<mutable_buffer,
53 MutableBufferSequence, MutableBufferIterator> tmp(buffers);
54 while (!tmp.empty())
55 {
56 if (std::size_t max_size = detail::adapt_completion_condition_result(
57 completion_condition(ec, tmp.total_consumed())))
58 {
59 tmp.consume(d.read_some_at(offset + tmp.total_consumed(),
60 tmp.prepare(max_size), ec));
61 }
62 else
63 break;
64 }
20effc67 65 return tmp.total_consumed();
b32b8144
FG
66 }
67} // namespace detail
68
7c673cae
FG
69template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
70 typename CompletionCondition>
71std::size_t read_at(SyncRandomAccessReadDevice& d,
72 uint64_t offset, const MutableBufferSequence& buffers,
73 CompletionCondition completion_condition, boost::system::error_code& ec)
74{
b32b8144 75 return detail::read_at_buffer_sequence(d, offset, buffers,
92f5a8d4
TL
76 boost::asio::buffer_sequence_begin(buffers),
77 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
7c673cae
FG
78}
79
80template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
81inline std::size_t read_at(SyncRandomAccessReadDevice& d,
82 uint64_t offset, const MutableBufferSequence& buffers)
83{
84 boost::system::error_code ec;
85 std::size_t bytes_transferred = read_at(
86 d, offset, buffers, transfer_all(), ec);
87 boost::asio::detail::throw_error(ec, "read_at");
88 return bytes_transferred;
89}
90
91template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
92inline std::size_t read_at(SyncRandomAccessReadDevice& d,
93 uint64_t offset, const MutableBufferSequence& buffers,
94 boost::system::error_code& ec)
95{
96 return read_at(d, offset, buffers, transfer_all(), ec);
97}
98
99template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
100 typename CompletionCondition>
101inline std::size_t read_at(SyncRandomAccessReadDevice& d,
102 uint64_t offset, const MutableBufferSequence& buffers,
103 CompletionCondition completion_condition)
104{
105 boost::system::error_code ec;
92f5a8d4
TL
106 std::size_t bytes_transferred = read_at(d, offset, buffers,
107 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
7c673cae
FG
108 boost::asio::detail::throw_error(ec, "read_at");
109 return bytes_transferred;
110}
111
b32b8144 112#if !defined(BOOST_ASIO_NO_EXTENSIONS)
7c673cae
FG
113#if !defined(BOOST_ASIO_NO_IOSTREAM)
114
115template <typename SyncRandomAccessReadDevice, typename Allocator,
116 typename CompletionCondition>
117std::size_t read_at(SyncRandomAccessReadDevice& d,
118 uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
119 CompletionCondition completion_condition, boost::system::error_code& ec)
120{
121 ec = boost::system::error_code();
122 std::size_t total_transferred = 0;
123 std::size_t max_size = detail::adapt_completion_condition_result(
124 completion_condition(ec, total_transferred));
125 std::size_t bytes_available = read_size_helper(b, max_size);
126 while (bytes_available > 0)
127 {
128 std::size_t bytes_transferred = d.read_some_at(
129 offset + total_transferred, b.prepare(bytes_available), ec);
130 b.commit(bytes_transferred);
131 total_transferred += bytes_transferred;
132 max_size = detail::adapt_completion_condition_result(
133 completion_condition(ec, total_transferred));
134 bytes_available = read_size_helper(b, max_size);
135 }
136 return total_transferred;
137}
138
139template <typename SyncRandomAccessReadDevice, typename Allocator>
140inline std::size_t read_at(SyncRandomAccessReadDevice& d,
141 uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
142{
143 boost::system::error_code ec;
144 std::size_t bytes_transferred = read_at(
145 d, offset, b, transfer_all(), ec);
146 boost::asio::detail::throw_error(ec, "read_at");
147 return bytes_transferred;
148}
149
150template <typename SyncRandomAccessReadDevice, typename Allocator>
151inline std::size_t read_at(SyncRandomAccessReadDevice& d,
152 uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
153 boost::system::error_code& ec)
154{
155 return read_at(d, offset, b, transfer_all(), ec);
156}
157
158template <typename SyncRandomAccessReadDevice, typename Allocator,
159 typename CompletionCondition>
160inline std::size_t read_at(SyncRandomAccessReadDevice& d,
161 uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
162 CompletionCondition completion_condition)
163{
164 boost::system::error_code ec;
92f5a8d4
TL
165 std::size_t bytes_transferred = read_at(d, offset, b,
166 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);
7c673cae
FG
167 boost::asio::detail::throw_error(ec, "read_at");
168 return bytes_transferred;
169}
170
171#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
b32b8144 172#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
7c673cae
FG
173
174namespace detail
175{
176 template <typename AsyncRandomAccessReadDevice,
b32b8144
FG
177 typename MutableBufferSequence, typename MutableBufferIterator,
178 typename CompletionCondition, typename ReadHandler>
7c673cae 179 class read_at_op
1e59de90
TL
180 : public base_from_cancellation_state<ReadHandler>,
181 base_from_completion_cond<CompletionCondition>
7c673cae
FG
182 {
183 public:
184 read_at_op(AsyncRandomAccessReadDevice& device,
185 uint64_t offset, const MutableBufferSequence& buffers,
92f5a8d4 186 CompletionCondition& completion_condition, ReadHandler& handler)
1e59de90
TL
187 : base_from_cancellation_state<ReadHandler>(
188 handler, enable_partial_cancellation()),
189 base_from_completion_cond<CompletionCondition>(completion_condition),
7c673cae
FG
190 device_(device),
191 offset_(offset),
192 buffers_(buffers),
193 start_(0),
7c673cae
FG
194 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
195 {
196 }
197
198#if defined(BOOST_ASIO_HAS_MOVE)
199 read_at_op(const read_at_op& other)
1e59de90
TL
200 : base_from_cancellation_state<ReadHandler>(other),
201 base_from_completion_cond<CompletionCondition>(other),
7c673cae
FG
202 device_(other.device_),
203 offset_(other.offset_),
204 buffers_(other.buffers_),
205 start_(other.start_),
7c673cae
FG
206 handler_(other.handler_)
207 {
208 }
209
210 read_at_op(read_at_op&& other)
1e59de90
TL
211 : base_from_cancellation_state<ReadHandler>(
212 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
213 ReadHandler>)(other)),
214 base_from_completion_cond<CompletionCondition>(
215 BOOST_ASIO_MOVE_CAST(base_from_completion_cond<
92f5a8d4 216 CompletionCondition>)(other)),
7c673cae
FG
217 device_(other.device_),
218 offset_(other.offset_),
92f5a8d4 219 buffers_(BOOST_ASIO_MOVE_CAST(buffers_type)(other.buffers_)),
7c673cae 220 start_(other.start_),
7c673cae
FG
221 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
222 {
223 }
224#endif // defined(BOOST_ASIO_HAS_MOVE)
225
1e59de90 226 void operator()(boost::system::error_code ec,
7c673cae
FG
227 std::size_t bytes_transferred, int start = 0)
228 {
b32b8144 229 std::size_t max_size;
7c673cae
FG
230 switch (start_ = start)
231 {
232 case 1:
b32b8144 233 max_size = this->check_for_completion(ec, buffers_.total_consumed());
1e59de90 234 for (;;)
7c673cae 235 {
20effc67
TL
236 {
237 BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
238 device_.async_read_some_at(
239 offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
240 BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
241 }
7c673cae 242 return; default:
7c673cae 243 buffers_.consume(bytes_transferred);
b32b8144 244 if ((!ec && bytes_transferred == 0) || buffers_.empty())
7c673cae 245 break;
b32b8144 246 max_size = this->check_for_completion(ec, buffers_.total_consumed());
1e59de90
TL
247 if (max_size == 0)
248 break;
249 if (this->cancelled() != cancellation_type::none)
250 {
251 ec = boost::asio::error::operation_aborted;
252 break;
253 }
254 }
7c673cae 255
1e59de90
TL
256 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(
257 static_cast<const boost::system::error_code&>(ec),
258 static_cast<const std::size_t&>(buffers_.total_consumed()));
7c673cae
FG
259 }
260 }
261
262 //private:
92f5a8d4
TL
263 typedef boost::asio::detail::consuming_buffers<mutable_buffer,
264 MutableBufferSequence, MutableBufferIterator> buffers_type;
265
7c673cae
FG
266 AsyncRandomAccessReadDevice& device_;
267 uint64_t offset_;
92f5a8d4 268 buffers_type buffers_;
7c673cae 269 int start_;
7c673cae
FG
270 ReadHandler handler_;
271 };
272
273 template <typename AsyncRandomAccessReadDevice,
b32b8144 274 typename MutableBufferSequence, typename MutableBufferIterator,
7c673cae 275 typename CompletionCondition, typename ReadHandler>
20effc67
TL
276 inline asio_handler_allocate_is_deprecated
277 asio_handler_allocate(std::size_t size,
7c673cae 278 read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
b32b8144 279 MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
7c673cae 280 {
20effc67
TL
281#if defined(BOOST_ASIO_NO_DEPRECATED)
282 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
283 return asio_handler_allocate_is_no_longer_used();
284#else // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
285 return boost_asio_handler_alloc_helpers::allocate(
286 size, this_handler->handler_);
20effc67 287#endif // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
288 }
289
290 template <typename AsyncRandomAccessReadDevice,
b32b8144
FG
291 typename MutableBufferSequence, typename MutableBufferIterator,
292 typename CompletionCondition, typename ReadHandler>
20effc67
TL
293 inline asio_handler_deallocate_is_deprecated
294 asio_handler_deallocate(void* pointer, std::size_t size,
7c673cae 295 read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
b32b8144 296 MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
7c673cae
FG
297 {
298 boost_asio_handler_alloc_helpers::deallocate(
299 pointer, size, this_handler->handler_);
20effc67
TL
300#if defined(BOOST_ASIO_NO_DEPRECATED)
301 return asio_handler_deallocate_is_no_longer_used();
302#endif // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
303 }
304
305 template <typename AsyncRandomAccessReadDevice,
b32b8144
FG
306 typename MutableBufferSequence, typename MutableBufferIterator,
307 typename CompletionCondition, typename ReadHandler>
7c673cae
FG
308 inline bool asio_handler_is_continuation(
309 read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
b32b8144 310 MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
7c673cae
FG
311 {
312 return this_handler->start_ == 0 ? true
313 : boost_asio_handler_cont_helpers::is_continuation(
314 this_handler->handler_);
315 }
316
317 template <typename Function, typename AsyncRandomAccessReadDevice,
b32b8144
FG
318 typename MutableBufferSequence, typename MutableBufferIterator,
319 typename CompletionCondition, typename ReadHandler>
20effc67
TL
320 inline asio_handler_invoke_is_deprecated
321 asio_handler_invoke(Function& function,
7c673cae 322 read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
b32b8144 323 MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
7c673cae
FG
324 {
325 boost_asio_handler_invoke_helpers::invoke(
326 function, this_handler->handler_);
20effc67
TL
327#if defined(BOOST_ASIO_NO_DEPRECATED)
328 return asio_handler_invoke_is_no_longer_used();
329#endif // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
330 }
331
332 template <typename Function, typename AsyncRandomAccessReadDevice,
b32b8144
FG
333 typename MutableBufferSequence, typename MutableBufferIterator,
334 typename CompletionCondition, typename ReadHandler>
20effc67
TL
335 inline asio_handler_invoke_is_deprecated
336 asio_handler_invoke(const Function& function,
7c673cae 337 read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
b32b8144 338 MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
7c673cae
FG
339 {
340 boost_asio_handler_invoke_helpers::invoke(
341 function, this_handler->handler_);
20effc67
TL
342#if defined(BOOST_ASIO_NO_DEPRECATED)
343 return asio_handler_invoke_is_no_longer_used();
344#endif // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
345 }
346
347 template <typename AsyncRandomAccessReadDevice,
b32b8144
FG
348 typename MutableBufferSequence, typename MutableBufferIterator,
349 typename CompletionCondition, typename ReadHandler>
350 inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,
7c673cae 351 uint64_t offset, const MutableBufferSequence& buffers,
92f5a8d4 352 const MutableBufferIterator&, CompletionCondition& completion_condition,
b32b8144 353 ReadHandler& handler)
7c673cae 354 {
b32b8144
FG
355 detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
356 MutableBufferIterator, CompletionCondition, ReadHandler>(
357 d, offset, buffers, completion_condition, handler)(
358 boost::system::error_code(), 0, 1);
7c673cae 359 }
92f5a8d4
TL
360
361 template <typename AsyncRandomAccessReadDevice>
362 class initiate_async_read_at_buffer_sequence
363 {
364 public:
365 typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
366
367 explicit initiate_async_read_at_buffer_sequence(
368 AsyncRandomAccessReadDevice& device)
369 : device_(device)
370 {
371 }
372
373 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
374 {
375 return device_.get_executor();
376 }
377
378 template <typename ReadHandler, typename MutableBufferSequence,
379 typename CompletionCondition>
380 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
381 uint64_t offset, const MutableBufferSequence& buffers,
382 BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
383 {
384 // If you get an error on the following line it means that your handler
385 // does not meet the documented type requirements for a ReadHandler.
386 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
387
388 non_const_lvalue<ReadHandler> handler2(handler);
389 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
390 start_read_at_buffer_sequence_op(device_, offset, buffers,
391 boost::asio::buffer_sequence_begin(buffers),
392 completion_cond2.value, handler2.value);
393 }
394
395 private:
396 AsyncRandomAccessReadDevice& device_;
397 };
7c673cae
FG
398} // namespace detail
399
b32b8144
FG
400#if !defined(GENERATING_DOCUMENTATION)
401
1e59de90
TL
402template <template <typename, typename> class Associator,
403 typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
404 typename MutableBufferIterator, typename CompletionCondition,
405 typename ReadHandler, typename DefaultCandidate>
406struct associator<Associator,
b32b8144 407 detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
1e59de90
TL
408 MutableBufferIterator, CompletionCondition, ReadHandler>,
409 DefaultCandidate>
410 : Associator<ReadHandler, DefaultCandidate>
b32b8144 411{
1e59de90 412 static typename Associator<ReadHandler, DefaultCandidate>::type get(
b32b8144 413 const detail::read_at_op<AsyncRandomAccessReadDevice,
1e59de90
TL
414 MutableBufferSequence, MutableBufferIterator,
415 CompletionCondition, ReadHandler>& h,
416 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
b32b8144 417 {
1e59de90 418 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
b32b8144
FG
419 }
420};
421
422#endif // !defined(GENERATING_DOCUMENTATION)
423
92f5a8d4
TL
424template <typename AsyncRandomAccessReadDevice,
425 typename MutableBufferSequence, typename CompletionCondition,
426 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1e59de90
TL
427 std::size_t)) ReadToken>
428inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
7c673cae
FG
429 void (boost::system::error_code, std::size_t))
430async_read_at(AsyncRandomAccessReadDevice& d,
431 uint64_t offset, const MutableBufferSequence& buffers,
432 CompletionCondition completion_condition,
1e59de90 433 BOOST_ASIO_MOVE_ARG(ReadToken) token)
7c673cae 434{
1e59de90 435 return async_initiate<ReadToken,
92f5a8d4
TL
436 void (boost::system::error_code, std::size_t)>(
437 detail::initiate_async_read_at_buffer_sequence<
438 AsyncRandomAccessReadDevice>(d),
1e59de90 439 token, offset, buffers,
92f5a8d4 440 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
7c673cae
FG
441}
442
443template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
92f5a8d4 444 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1e59de90
TL
445 std::size_t)) ReadToken>
446inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
7c673cae
FG
447 void (boost::system::error_code, std::size_t))
448async_read_at(AsyncRandomAccessReadDevice& d,
449 uint64_t offset, const MutableBufferSequence& buffers,
1e59de90 450 BOOST_ASIO_MOVE_ARG(ReadToken) token)
7c673cae 451{
1e59de90 452 return async_initiate<ReadToken,
92f5a8d4
TL
453 void (boost::system::error_code, std::size_t)>(
454 detail::initiate_async_read_at_buffer_sequence<
455 AsyncRandomAccessReadDevice>(d),
1e59de90 456 token, offset, buffers, transfer_all());
7c673cae
FG
457}
458
b32b8144 459#if !defined(BOOST_ASIO_NO_EXTENSIONS)
7c673cae
FG
460#if !defined(BOOST_ASIO_NO_IOSTREAM)
461
462namespace detail
463{
464 template <typename AsyncRandomAccessReadDevice, typename Allocator,
465 typename CompletionCondition, typename ReadHandler>
466 class read_at_streambuf_op
1e59de90
TL
467 : public base_from_cancellation_state<ReadHandler>,
468 base_from_completion_cond<CompletionCondition>
7c673cae
FG
469 {
470 public:
471 read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
472 uint64_t offset, basic_streambuf<Allocator>& streambuf,
92f5a8d4 473 CompletionCondition& completion_condition, ReadHandler& handler)
1e59de90
TL
474 : base_from_cancellation_state<ReadHandler>(
475 handler, enable_partial_cancellation()),
476 base_from_completion_cond<CompletionCondition>(completion_condition),
7c673cae
FG
477 device_(device),
478 offset_(offset),
479 streambuf_(streambuf),
480 start_(0),
481 total_transferred_(0),
482 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
483 {
484 }
485
486#if defined(BOOST_ASIO_HAS_MOVE)
487 read_at_streambuf_op(const read_at_streambuf_op& other)
1e59de90
TL
488 : base_from_cancellation_state<ReadHandler>(other),
489 base_from_completion_cond<CompletionCondition>(other),
7c673cae
FG
490 device_(other.device_),
491 offset_(other.offset_),
492 streambuf_(other.streambuf_),
493 start_(other.start_),
494 total_transferred_(other.total_transferred_),
495 handler_(other.handler_)
496 {
497 }
498
499 read_at_streambuf_op(read_at_streambuf_op&& other)
1e59de90
TL
500 : base_from_cancellation_state<ReadHandler>(
501 BOOST_ASIO_MOVE_CAST(base_from_cancellation_state<
502 ReadHandler>)(other)),
503 base_from_completion_cond<CompletionCondition>(
504 BOOST_ASIO_MOVE_CAST(base_from_completion_cond<
92f5a8d4 505 CompletionCondition>)(other)),
7c673cae
FG
506 device_(other.device_),
507 offset_(other.offset_),
508 streambuf_(other.streambuf_),
509 start_(other.start_),
510 total_transferred_(other.total_transferred_),
511 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
512 {
513 }
514#endif // defined(BOOST_ASIO_HAS_MOVE)
515
1e59de90 516 void operator()(boost::system::error_code ec,
7c673cae
FG
517 std::size_t bytes_transferred, int start = 0)
518 {
519 std::size_t max_size, bytes_available;
520 switch (start_ = start)
521 {
522 case 1:
523 max_size = this->check_for_completion(ec, total_transferred_);
524 bytes_available = read_size_helper(streambuf_, max_size);
525 for (;;)
526 {
20effc67
TL
527 {
528 BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));
529 device_.async_read_some_at(offset_ + total_transferred_,
530 streambuf_.prepare(bytes_available),
531 BOOST_ASIO_MOVE_CAST(read_at_streambuf_op)(*this));
532 }
7c673cae
FG
533 return; default:
534 total_transferred_ += bytes_transferred;
535 streambuf_.commit(bytes_transferred);
536 max_size = this->check_for_completion(ec, total_transferred_);
537 bytes_available = read_size_helper(streambuf_, max_size);
538 if ((!ec && bytes_transferred == 0) || bytes_available == 0)
539 break;
1e59de90
TL
540 if (this->cancelled() != cancellation_type::none)
541 {
542 ec = boost::asio::error::operation_aborted;
543 break;
544 }
7c673cae
FG
545 }
546
1e59de90
TL
547 BOOST_ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(
548 static_cast<const boost::system::error_code&>(ec),
549 static_cast<const std::size_t&>(total_transferred_));
7c673cae
FG
550 }
551 }
552
553 //private:
554 AsyncRandomAccessReadDevice& device_;
555 uint64_t offset_;
556 boost::asio::basic_streambuf<Allocator>& streambuf_;
557 int start_;
558 std::size_t total_transferred_;
559 ReadHandler handler_;
560 };
561
562 template <typename AsyncRandomAccessReadDevice, typename Allocator,
563 typename CompletionCondition, typename ReadHandler>
20effc67
TL
564 inline asio_handler_allocate_is_deprecated
565 asio_handler_allocate(std::size_t size,
7c673cae
FG
566 read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
567 CompletionCondition, ReadHandler>* this_handler)
568 {
20effc67
TL
569#if defined(BOOST_ASIO_NO_DEPRECATED)
570 boost_asio_handler_alloc_helpers::allocate(size, this_handler->handler_);
571 return asio_handler_allocate_is_no_longer_used();
572#else // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
573 return boost_asio_handler_alloc_helpers::allocate(
574 size, this_handler->handler_);
20effc67 575#endif // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
576 }
577
578 template <typename AsyncRandomAccessReadDevice, typename Allocator,
579 typename CompletionCondition, typename ReadHandler>
20effc67
TL
580 inline asio_handler_deallocate_is_deprecated
581 asio_handler_deallocate(void* pointer, std::size_t size,
7c673cae
FG
582 read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
583 CompletionCondition, ReadHandler>* this_handler)
584 {
585 boost_asio_handler_alloc_helpers::deallocate(
586 pointer, size, this_handler->handler_);
20effc67
TL
587#if defined(BOOST_ASIO_NO_DEPRECATED)
588 return asio_handler_deallocate_is_no_longer_used();
589#endif // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
590 }
591
592 template <typename AsyncRandomAccessReadDevice, typename Allocator,
593 typename CompletionCondition, typename ReadHandler>
594 inline bool asio_handler_is_continuation(
595 read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
596 CompletionCondition, ReadHandler>* this_handler)
597 {
598 return this_handler->start_ == 0 ? true
599 : boost_asio_handler_cont_helpers::is_continuation(
600 this_handler->handler_);
601 }
602
603 template <typename Function, typename AsyncRandomAccessReadDevice,
604 typename Allocator, typename CompletionCondition, typename ReadHandler>
20effc67
TL
605 inline asio_handler_invoke_is_deprecated
606 asio_handler_invoke(Function& function,
7c673cae
FG
607 read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
608 CompletionCondition, ReadHandler>* this_handler)
609 {
610 boost_asio_handler_invoke_helpers::invoke(
611 function, this_handler->handler_);
20effc67
TL
612#if defined(BOOST_ASIO_NO_DEPRECATED)
613 return asio_handler_invoke_is_no_longer_used();
614#endif // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae
FG
615 }
616
617 template <typename Function, typename AsyncRandomAccessReadDevice,
618 typename Allocator, typename CompletionCondition, typename ReadHandler>
20effc67
TL
619 inline asio_handler_invoke_is_deprecated
620 asio_handler_invoke(const Function& function,
7c673cae
FG
621 read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
622 CompletionCondition, ReadHandler>* this_handler)
623 {
624 boost_asio_handler_invoke_helpers::invoke(
625 function, this_handler->handler_);
20effc67
TL
626#if defined(BOOST_ASIO_NO_DEPRECATED)
627 return asio_handler_invoke_is_no_longer_used();
628#endif // defined(BOOST_ASIO_NO_DEPRECATED)
7c673cae 629 }
92f5a8d4
TL
630
631 template <typename AsyncRandomAccessReadDevice>
632 class initiate_async_read_at_streambuf
633 {
634 public:
635 typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;
636
637 explicit initiate_async_read_at_streambuf(
638 AsyncRandomAccessReadDevice& device)
639 : device_(device)
640 {
641 }
642
643 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
644 {
645 return device_.get_executor();
646 }
647
648 template <typename ReadHandler,
649 typename Allocator, typename CompletionCondition>
650 void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
651 uint64_t offset, basic_streambuf<Allocator>* b,
652 BOOST_ASIO_MOVE_ARG(CompletionCondition) completion_cond) const
653 {
654 // If you get an error on the following line it means that your handler
655 // does not meet the documented type requirements for a ReadHandler.
656 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
657
658 non_const_lvalue<ReadHandler> handler2(handler);
659 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
660 read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
661 CompletionCondition, typename decay<ReadHandler>::type>(
662 device_, offset, *b, completion_cond2.value, handler2.value)(
663 boost::system::error_code(), 0, 1);
664 }
665
666 private:
667 AsyncRandomAccessReadDevice& device_;
668 };
7c673cae
FG
669} // namespace detail
670
b32b8144
FG
671#if !defined(GENERATING_DOCUMENTATION)
672
1e59de90
TL
673template <template <typename, typename> class Associator,
674 typename AsyncRandomAccessReadDevice, typename Executor,
675 typename CompletionCondition, typename ReadHandler,
676 typename DefaultCandidate>
677struct associator<Associator,
b32b8144
FG
678 detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
679 Executor, CompletionCondition, ReadHandler>,
1e59de90
TL
680 DefaultCandidate>
681 : Associator<ReadHandler, DefaultCandidate>
b32b8144 682{
1e59de90 683 static typename Associator<ReadHandler, DefaultCandidate>::type get(
b32b8144
FG
684 const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
685 Executor, CompletionCondition, ReadHandler>& h,
1e59de90 686 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
b32b8144 687 {
1e59de90 688 return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);
b32b8144
FG
689 }
690};
691
692#endif // !defined(GENERATING_DOCUMENTATION)
693
92f5a8d4
TL
694template <typename AsyncRandomAccessReadDevice,
695 typename Allocator, typename CompletionCondition,
696 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1e59de90
TL
697 std::size_t)) ReadToken>
698inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
7c673cae
FG
699 void (boost::system::error_code, std::size_t))
700async_read_at(AsyncRandomAccessReadDevice& d,
701 uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
702 CompletionCondition completion_condition,
1e59de90 703 BOOST_ASIO_MOVE_ARG(ReadToken) token)
7c673cae 704{
1e59de90 705 return async_initiate<ReadToken,
92f5a8d4
TL
706 void (boost::system::error_code, std::size_t)>(
707 detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
1e59de90 708 token, offset, &b,
92f5a8d4 709 BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition));
7c673cae
FG
710}
711
712template <typename AsyncRandomAccessReadDevice, typename Allocator,
92f5a8d4 713 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1e59de90
TL
714 std::size_t)) ReadToken>
715inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadToken,
7c673cae
FG
716 void (boost::system::error_code, std::size_t))
717async_read_at(AsyncRandomAccessReadDevice& d,
718 uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
1e59de90 719 BOOST_ASIO_MOVE_ARG(ReadToken) token)
7c673cae 720{
1e59de90 721 return async_initiate<ReadToken,
92f5a8d4
TL
722 void (boost::system::error_code, std::size_t)>(
723 detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),
1e59de90 724 token, offset, &b, transfer_all());
7c673cae
FG
725}
726
727#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
b32b8144 728#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
7c673cae
FG
729
730} // namespace asio
731} // namespace boost
732
733#include <boost/asio/detail/pop_options.hpp>
734
735#endif // BOOST_ASIO_IMPL_READ_AT_HPP