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