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