1//
2// impl/write.hpp
3// ~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 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_HPP
12#define BOOST_ASIO_IMPL_WRITE_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/associator.hpp>
19#include <boost/asio/buffer.hpp>
20#include <boost/asio/detail/array_fwd.hpp>
21#include <boost/asio/detail/base_from_cancellation_state.hpp>
22#include <boost/asio/detail/base_from_completion_cond.hpp>
23#include <boost/asio/detail/bind_handler.hpp>
24#include <boost/asio/detail/consuming_buffers.hpp>
25#include <boost/asio/detail/dependent_type.hpp>
26#include <boost/asio/detail/handler_cont_helpers.hpp>
27#include <boost/asio/detail/handler_tracking.hpp>
28#include <boost/asio/detail/handler_type_requirements.hpp>
29#include <boost/asio/detail/non_const_lvalue.hpp>
30#include <boost/asio/detail/throw_error.hpp>
31
32#include <boost/asio/detail/push_options.hpp>
33
34namespace boost {
35namespace asio {
36
37namespace detail
38{
39 template <typename SyncWriteStream, typename ConstBufferSequence,
40 typename ConstBufferIterator, typename CompletionCondition>
41 std::size_t write(SyncWriteStream& s,
42 const ConstBufferSequence& buffers, const ConstBufferIterator&,
43 CompletionCondition completion_condition, boost::system::error_code& ec)
44 {
45 ec = boost::system::error_code();
46 boost::asio::detail::consuming_buffers<const_buffer,
47 ConstBufferSequence, ConstBufferIterator> tmp(buffers);
48 while (!tmp.empty())
49 {
50 if (std::size_t max_size = detail::adapt_completion_condition_result(
51 completion_condition(ec, tmp.total_consumed())))
52 tmp.consume(s.write_some(tmp.prepare(max_size), ec));
53 else
54 break;
55 }
56 return tmp.total_consumed();
57 }
58} // namespace detail
59
60template <typename SyncWriteStream, typename ConstBufferSequence,
61 typename CompletionCondition>
62inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
63 CompletionCondition completion_condition, boost::system::error_code& ec,
64 constraint_t<
65 is_const_buffer_sequence<ConstBufferSequence>::value
66 >)
67{
68 return detail::write(s, buffers,
69 boost::asio::buffer_sequence_begin(buffers),
70 static_cast<CompletionCondition&&>(completion_condition), ec);
71}
72
73template <typename SyncWriteStream, typename ConstBufferSequence>
74inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
75 constraint_t<
76 is_const_buffer_sequence<ConstBufferSequence>::value
77 >)
78{
79 boost::system::error_code ec;
80 std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
81 boost::asio::detail::throw_error(err: ec, location: "write");
82 return bytes_transferred;
83}
84
85template <typename SyncWriteStream, typename ConstBufferSequence>
86inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
87 boost::system::error_code& ec,
88 constraint_t<
89 is_const_buffer_sequence<ConstBufferSequence>::value
90 >)
91{
92 return write(s, buffers, transfer_all(), ec);
93}
94
95template <typename SyncWriteStream, typename ConstBufferSequence,
96 typename CompletionCondition>
97inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
98 CompletionCondition completion_condition,
99 constraint_t<
100 is_const_buffer_sequence<ConstBufferSequence>::value
101 >)
102{
103 boost::system::error_code ec;
104 std::size_t bytes_transferred = write(s, buffers,
105 static_cast<CompletionCondition&&>(completion_condition), ec);
106 boost::asio::detail::throw_error(err: ec, location: "write");
107 return bytes_transferred;
108}
109
110#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
111
112template <typename SyncWriteStream, typename DynamicBuffer_v1,
113 typename CompletionCondition>
114std::size_t write(SyncWriteStream& s,
115 DynamicBuffer_v1&& buffers,
116 CompletionCondition completion_condition, boost::system::error_code& ec,
117 constraint_t<
118 is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
119 >,
120 constraint_t<
121 !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
122 >)
123{
124 decay_t<DynamicBuffer_v1> b(
125 static_cast<DynamicBuffer_v1&&>(buffers));
126
127 std::size_t bytes_transferred = write(s, b.data(),
128 static_cast<CompletionCondition&&>(completion_condition), ec);
129 b.consume(bytes_transferred);
130 return bytes_transferred;
131}
132
133template <typename SyncWriteStream, typename DynamicBuffer_v1>
134inline std::size_t write(SyncWriteStream& s,
135 DynamicBuffer_v1&& buffers,
136 constraint_t<
137 is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
138 >,
139 constraint_t<
140 !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
141 >)
142{
143 boost::system::error_code ec;
144 std::size_t bytes_transferred = write(s,
145 static_cast<DynamicBuffer_v1&&>(buffers),
146 transfer_all(), ec);
147 boost::asio::detail::throw_error(err: ec, location: "write");
148 return bytes_transferred;
149}
150
151template <typename SyncWriteStream, typename DynamicBuffer_v1>
152inline std::size_t write(SyncWriteStream& s,
153 DynamicBuffer_v1&& buffers,
154 boost::system::error_code& ec,
155 constraint_t<
156 is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
157 >,
158 constraint_t<
159 !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
160 >)
161{
162 return write(s, static_cast<DynamicBuffer_v1&&>(buffers),
163 transfer_all(), ec);
164}
165
166template <typename SyncWriteStream, typename DynamicBuffer_v1,
167 typename CompletionCondition>
168inline std::size_t write(SyncWriteStream& s,
169 DynamicBuffer_v1&& buffers,
170 CompletionCondition completion_condition,
171 constraint_t<
172 is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
173 >,
174 constraint_t<
175 !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
176 >)
177{
178 boost::system::error_code ec;
179 std::size_t bytes_transferred = write(s,
180 static_cast<DynamicBuffer_v1&&>(buffers),
181 static_cast<CompletionCondition&&>(completion_condition), ec);
182 boost::asio::detail::throw_error(err: ec, location: "write");
183 return bytes_transferred;
184}
185
186#if !defined(BOOST_ASIO_NO_EXTENSIONS)
187#if !defined(BOOST_ASIO_NO_IOSTREAM)
188
189template <typename SyncWriteStream, typename Allocator,
190 typename CompletionCondition>
191inline std::size_t write(SyncWriteStream& s,
192 boost::asio::basic_streambuf<Allocator>& b,
193 CompletionCondition completion_condition, boost::system::error_code& ec)
194{
195 return write(s, basic_streambuf_ref<Allocator>(b),
196 static_cast<CompletionCondition&&>(completion_condition), ec);
197}
198
199template <typename SyncWriteStream, typename Allocator>
200inline std::size_t write(SyncWriteStream& s,
201 boost::asio::basic_streambuf<Allocator>& b)
202{
203 return write(s, basic_streambuf_ref<Allocator>(b));
204}
205
206template <typename SyncWriteStream, typename Allocator>
207inline std::size_t write(SyncWriteStream& s,
208 boost::asio::basic_streambuf<Allocator>& b,
209 boost::system::error_code& ec)
210{
211 return write(s, basic_streambuf_ref<Allocator>(b), ec);
212}
213
214template <typename SyncWriteStream, typename Allocator,
215 typename CompletionCondition>
216inline std::size_t write(SyncWriteStream& s,
217 boost::asio::basic_streambuf<Allocator>& b,
218 CompletionCondition completion_condition)
219{
220 return write(s, basic_streambuf_ref<Allocator>(b),
221 static_cast<CompletionCondition&&>(completion_condition));
222}
223
224#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
225#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
226#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
227
228template <typename SyncWriteStream, typename DynamicBuffer_v2,
229 typename CompletionCondition>
230std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
231 CompletionCondition completion_condition, boost::system::error_code& ec,
232 constraint_t<
233 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
234 >)
235{
236 std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),
237 static_cast<CompletionCondition&&>(completion_condition), ec);
238 buffers.consume(bytes_transferred);
239 return bytes_transferred;
240}
241
242template <typename SyncWriteStream, typename DynamicBuffer_v2>
243inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
244 constraint_t<
245 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
246 >)
247{
248 boost::system::error_code ec;
249 std::size_t bytes_transferred = write(s,
250 static_cast<DynamicBuffer_v2&&>(buffers),
251 transfer_all(), ec);
252 boost::asio::detail::throw_error(err: ec, location: "write");
253 return bytes_transferred;
254}
255
256template <typename SyncWriteStream, typename DynamicBuffer_v2>
257inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
258 boost::system::error_code& ec,
259 constraint_t<
260 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
261 >)
262{
263 return write(s, static_cast<DynamicBuffer_v2&&>(buffers),
264 transfer_all(), ec);
265}
266
267template <typename SyncWriteStream, typename DynamicBuffer_v2,
268 typename CompletionCondition>
269inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
270 CompletionCondition completion_condition,
271 constraint_t<
272 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
273 >)
274{
275 boost::system::error_code ec;
276 std::size_t bytes_transferred = write(s,
277 static_cast<DynamicBuffer_v2&&>(buffers),
278 static_cast<CompletionCondition&&>(completion_condition), ec);
279 boost::asio::detail::throw_error(err: ec, location: "write");
280 return bytes_transferred;
281}
282
283namespace detail
284{
285 template <typename AsyncWriteStream, typename ConstBufferSequence,
286 typename ConstBufferIterator, typename CompletionCondition,
287 typename WriteHandler>
288 class write_op
289 : public base_from_cancellation_state<WriteHandler>,
290 base_from_completion_cond<CompletionCondition>
291 {
292 public:
293 write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
294 CompletionCondition& completion_condition, WriteHandler& handler)
295 : base_from_cancellation_state<WriteHandler>(
296 handler, enable_partial_cancellation()),
297 base_from_completion_cond<CompletionCondition>(completion_condition),
298 stream_(stream),
299 buffers_(buffers),
300 start_(0),
301 handler_(static_cast<WriteHandler&&>(handler))
302 {
303 }
304
305 write_op(const write_op& other)
306 : base_from_cancellation_state<WriteHandler>(other),
307 base_from_completion_cond<CompletionCondition>(other),
308 stream_(other.stream_),
309 buffers_(other.buffers_),
310 start_(other.start_),
311 handler_(other.handler_)
312 {
313 }
314
315 write_op(write_op&& other)
316 : base_from_cancellation_state<WriteHandler>(
317 static_cast<base_from_cancellation_state<WriteHandler>&&>(other)),
318 base_from_completion_cond<CompletionCondition>(
319 static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
320 stream_(other.stream_),
321 buffers_(static_cast<buffers_type&&>(other.buffers_)),
322 start_(other.start_),
323 handler_(static_cast<WriteHandler&&>(other.handler_))
324 {
325 }
326
327 void operator()(boost::system::error_code ec,
328 std::size_t bytes_transferred, int start = 0)
329 {
330 std::size_t max_size;
331 switch (start_ = start)
332 {
333 case 1:
334 max_size = this->check_for_completion(ec, buffers_.total_consumed());
335 for (;;)
336 {
337 {
338 BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write"));
339 stream_.async_write_some(buffers_.prepare(max_size),
340 static_cast<write_op&&>(*this));
341 }
342 return; default:
343 buffers_.consume(bytes_transferred);
344 if ((!ec && bytes_transferred == 0) || buffers_.empty())
345 break;
346 max_size = this->check_for_completion(ec, buffers_.total_consumed());
347 if (max_size == 0)
348 break;
349 if (this->cancelled() != cancellation_type::none)
350 {
351 ec = error::operation_aborted;
352 break;
353 }
354 }
355
356 static_cast<WriteHandler&&>(handler_)(
357 static_cast<const boost::system::error_code&>(ec),
358 static_cast<const std::size_t&>(buffers_.total_consumed()));
359 }
360 }
361
362 //private:
363 typedef boost::asio::detail::consuming_buffers<const_buffer,
364 ConstBufferSequence, ConstBufferIterator> buffers_type;
365
366 AsyncWriteStream& stream_;
367 buffers_type buffers_;
368 int start_;
369 WriteHandler handler_;
370 };
371
372 template <typename AsyncWriteStream, typename ConstBufferSequence,
373 typename ConstBufferIterator, typename CompletionCondition,
374 typename WriteHandler>
375 inline bool asio_handler_is_continuation(
376 write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
377 CompletionCondition, WriteHandler>* this_handler)
378 {
379 return this_handler->start_ == 0 ? true
380 : boost_asio_handler_cont_helpers::is_continuation(
381 this_handler->handler_);
382 }
383
384 template <typename AsyncWriteStream, typename ConstBufferSequence,
385 typename ConstBufferIterator, typename CompletionCondition,
386 typename WriteHandler>
387 inline void start_write_op(AsyncWriteStream& stream,
388 const ConstBufferSequence& buffers, const ConstBufferIterator&,
389 CompletionCondition& completion_condition, WriteHandler& handler)
390 {
391 detail::write_op<AsyncWriteStream, ConstBufferSequence,
392 ConstBufferIterator, CompletionCondition, WriteHandler>(
393 stream, buffers, completion_condition, handler)(
394 boost::system::error_code(), 0, 1);
395 }
396
397 template <typename AsyncWriteStream>
398 class initiate_async_write
399 {
400 public:
401 typedef typename AsyncWriteStream::executor_type executor_type;
402
403 explicit initiate_async_write(AsyncWriteStream& stream)
404 : stream_(stream)
405 {
406 }
407
408 executor_type get_executor() const noexcept
409 {
410 return stream_.get_executor();
411 }
412
413 template <typename WriteHandler, typename ConstBufferSequence,
414 typename CompletionCondition>
415 void operator()(WriteHandler&& handler,
416 const ConstBufferSequence& buffers,
417 CompletionCondition&& completion_cond) const
418 {
419 // If you get an error on the following line it means that your handler
420 // does not meet the documented type requirements for a WriteHandler.
421 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
422
423 non_const_lvalue<WriteHandler> handler2(handler);
424 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
425 start_write_op(stream_, buffers,
426 boost::asio::buffer_sequence_begin(buffers),
427 completion_cond2.value, handler2.value);
428 }
429
430 private:
431 AsyncWriteStream& stream_;
432 };
433} // namespace detail
434
435#if !defined(GENERATING_DOCUMENTATION)
436
437template <template <typename, typename> class Associator,
438 typename AsyncWriteStream, typename ConstBufferSequence,
439 typename ConstBufferIterator, typename CompletionCondition,
440 typename WriteHandler, typename DefaultCandidate>
441struct associator<Associator,
442 detail::write_op<AsyncWriteStream, ConstBufferSequence,
443 ConstBufferIterator, CompletionCondition, WriteHandler>,
444 DefaultCandidate>
445 : Associator<WriteHandler, DefaultCandidate>
446{
447 static typename Associator<WriteHandler, DefaultCandidate>::type get(
448 const detail::write_op<AsyncWriteStream, ConstBufferSequence,
449 ConstBufferIterator, CompletionCondition, WriteHandler>& h) noexcept
450 {
451 return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
452 }
453
454 static auto get(
455 const detail::write_op<AsyncWriteStream, ConstBufferSequence,
456 ConstBufferIterator, CompletionCondition, WriteHandler>& h,
457 const DefaultCandidate& c) noexcept
458 -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
459 {
460 return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
461 }
462};
463
464#endif // !defined(GENERATING_DOCUMENTATION)
465
466template <typename AsyncWriteStream,
467 typename ConstBufferSequence, typename CompletionCondition,
468 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
469 std::size_t)) WriteToken>
470inline auto async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
471 CompletionCondition completion_condition, WriteToken&& token,
472 constraint_t<
473 is_const_buffer_sequence<ConstBufferSequence>::value
474 >)
475 -> decltype(
476 async_initiate<WriteToken,
477 void (boost::system::error_code, std::size_t)>(
478 declval<detail::initiate_async_write<AsyncWriteStream>>(),
479 token, buffers,
480 static_cast<CompletionCondition&&>(completion_condition)))
481{
482 return async_initiate<WriteToken,
483 void (boost::system::error_code, std::size_t)>(
484 detail::initiate_async_write<AsyncWriteStream>(s),
485 token, buffers,
486 static_cast<CompletionCondition&&>(completion_condition));
487}
488
489template <typename AsyncWriteStream, typename ConstBufferSequence,
490 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
491 std::size_t)) WriteToken>
492inline auto async_write(AsyncWriteStream& s,
493 const ConstBufferSequence& buffers, WriteToken&& token,
494 constraint_t<
495 is_const_buffer_sequence<ConstBufferSequence>::value
496 >)
497 -> decltype(
498 async_initiate<WriteToken,
499 void (boost::system::error_code, std::size_t)>(
500 declval<detail::initiate_async_write<AsyncWriteStream>>(),
501 token, buffers, transfer_all()))
502{
503 return async_initiate<WriteToken,
504 void (boost::system::error_code, std::size_t)>(
505 detail::initiate_async_write<AsyncWriteStream>(s),
506 token, buffers, transfer_all());
507}
508
509#if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
510
511namespace detail
512{
513 template <typename AsyncWriteStream, typename DynamicBuffer_v1,
514 typename CompletionCondition, typename WriteHandler>
515 class write_dynbuf_v1_op
516 {
517 public:
518 template <typename BufferSequence>
519 write_dynbuf_v1_op(AsyncWriteStream& stream,
520 BufferSequence&& buffers,
521 CompletionCondition& completion_condition, WriteHandler& handler)
522 : stream_(stream),
523 buffers_(static_cast<BufferSequence&&>(buffers)),
524 completion_condition_(
525 static_cast<CompletionCondition&&>(completion_condition)),
526 handler_(static_cast<WriteHandler&&>(handler))
527 {
528 }
529
530 write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
531 : stream_(other.stream_),
532 buffers_(other.buffers_),
533 completion_condition_(other.completion_condition_),
534 handler_(other.handler_)
535 {
536 }
537
538 write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
539 : stream_(other.stream_),
540 buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
541 completion_condition_(
542 static_cast<CompletionCondition&&>(
543 other.completion_condition_)),
544 handler_(static_cast<WriteHandler&&>(other.handler_))
545 {
546 }
547
548 void operator()(const boost::system::error_code& ec,
549 std::size_t bytes_transferred, int start = 0)
550 {
551 switch (start)
552 {
553 case 1:
554 async_write(stream_, buffers_.data(),
555 static_cast<CompletionCondition&&>(completion_condition_),
556 static_cast<write_dynbuf_v1_op&&>(*this));
557 return; default:
558 buffers_.consume(bytes_transferred);
559 static_cast<WriteHandler&&>(handler_)(ec,
560 static_cast<const std::size_t&>(bytes_transferred));
561 }
562 }
563
564 //private:
565 AsyncWriteStream& stream_;
566 DynamicBuffer_v1 buffers_;
567 CompletionCondition completion_condition_;
568 WriteHandler handler_;
569 };
570
571 template <typename AsyncWriteStream, typename DynamicBuffer_v1,
572 typename CompletionCondition, typename WriteHandler>
573 inline bool asio_handler_is_continuation(
574 write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
575 CompletionCondition, WriteHandler>* this_handler)
576 {
577 return boost_asio_handler_cont_helpers::is_continuation(
578 this_handler->handler_);
579 }
580
581 template <typename AsyncWriteStream>
582 class initiate_async_write_dynbuf_v1
583 {
584 public:
585 typedef typename AsyncWriteStream::executor_type executor_type;
586
587 explicit initiate_async_write_dynbuf_v1(AsyncWriteStream& stream)
588 : stream_(stream)
589 {
590 }
591
592 executor_type get_executor() const noexcept
593 {
594 return stream_.get_executor();
595 }
596
597 template <typename WriteHandler, typename DynamicBuffer_v1,
598 typename CompletionCondition>
599 void operator()(WriteHandler&& handler,
600 DynamicBuffer_v1&& buffers,
601 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 WriteHandler.
605 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
606
607 non_const_lvalue<WriteHandler> handler2(handler);
608 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
609 write_dynbuf_v1_op<AsyncWriteStream,
610 decay_t<DynamicBuffer_v1>,
611 CompletionCondition, decay_t<WriteHandler>>(
612 stream_, static_cast<DynamicBuffer_v1&&>(buffers),
613 completion_cond2.value, handler2.value)(
614 boost::system::error_code(), 0, 1);
615 }
616
617 private:
618 AsyncWriteStream& stream_;
619 };
620} // namespace detail
621
622#if !defined(GENERATING_DOCUMENTATION)
623
624template <template <typename, typename> class Associator,
625 typename AsyncWriteStream, typename DynamicBuffer_v1,
626 typename CompletionCondition, typename WriteHandler,
627 typename DefaultCandidate>
628struct associator<Associator,
629 detail::write_dynbuf_v1_op<AsyncWriteStream,
630 DynamicBuffer_v1, CompletionCondition, WriteHandler>,
631 DefaultCandidate>
632 : Associator<WriteHandler, DefaultCandidate>
633{
634 static typename Associator<WriteHandler, DefaultCandidate>::type get(
635 const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
636 CompletionCondition, WriteHandler>& h) noexcept
637 {
638 return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
639 }
640
641 static auto get(
642 const detail::write_dynbuf_v1_op<AsyncWriteStream,
643 DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
644 const DefaultCandidate& c) noexcept
645 -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
646 {
647 return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
648 }
649};
650
651#endif // !defined(GENERATING_DOCUMENTATION)
652
653template <typename AsyncWriteStream, typename DynamicBuffer_v1,
654 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
655 std::size_t)) WriteToken>
656inline auto async_write(AsyncWriteStream& s,
657 DynamicBuffer_v1&& buffers, WriteToken&& token,
658 constraint_t<
659 is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
660 >,
661 constraint_t<
662 !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
663 >)
664 -> decltype(
665 async_initiate<WriteToken,
666 void (boost::system::error_code, std::size_t)>(
667 declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
668 token, static_cast<DynamicBuffer_v1&&>(buffers),
669 transfer_all()))
670{
671 return async_initiate<WriteToken,
672 void (boost::system::error_code, std::size_t)>(
673 detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
674 token, static_cast<DynamicBuffer_v1&&>(buffers),
675 transfer_all());
676}
677
678template <typename AsyncWriteStream,
679 typename DynamicBuffer_v1, typename CompletionCondition,
680 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
681 std::size_t)) WriteToken>
682inline auto async_write(AsyncWriteStream& s, DynamicBuffer_v1&& buffers,
683 CompletionCondition completion_condition, WriteToken&& token,
684 constraint_t<
685 is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
686 >,
687 constraint_t<
688 !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
689 >)
690 -> decltype(
691 async_initiate<WriteToken,
692 void (boost::system::error_code, std::size_t)>(
693 declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
694 token, static_cast<DynamicBuffer_v1&&>(buffers),
695 static_cast<CompletionCondition&&>(completion_condition)))
696{
697 return async_initiate<WriteToken,
698 void (boost::system::error_code, std::size_t)>(
699 detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
700 token, static_cast<DynamicBuffer_v1&&>(buffers),
701 static_cast<CompletionCondition&&>(completion_condition));
702}
703
704#if !defined(BOOST_ASIO_NO_EXTENSIONS)
705#if !defined(BOOST_ASIO_NO_IOSTREAM)
706
707template <typename AsyncWriteStream, typename Allocator,
708 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
709 std::size_t)) WriteToken>
710inline auto async_write(AsyncWriteStream& s,
711 boost::asio::basic_streambuf<Allocator>& b,
712 WriteToken&& token)
713 -> decltype(
714 async_initiate<WriteToken,
715 void (boost::system::error_code, std::size_t)>(
716 declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
717 token, basic_streambuf_ref<Allocator>(b), transfer_all()))
718{
719 return async_initiate<WriteToken,
720 void (boost::system::error_code, std::size_t)>(
721 detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
722 token, basic_streambuf_ref<Allocator>(b), transfer_all());
723}
724
725template <typename AsyncWriteStream,
726 typename Allocator, typename CompletionCondition,
727 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
728 std::size_t)) WriteToken>
729inline auto async_write(AsyncWriteStream& s,
730 boost::asio::basic_streambuf<Allocator>& b,
731 CompletionCondition completion_condition, WriteToken&& token)
732 -> decltype(
733 async_initiate<WriteToken,
734 void (boost::system::error_code, std::size_t)>(
735 declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
736 token, basic_streambuf_ref<Allocator>(b),
737 static_cast<CompletionCondition&&>(completion_condition)))
738{
739 return async_initiate<WriteToken,
740 void (boost::system::error_code, std::size_t)>(
741 detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
742 token, basic_streambuf_ref<Allocator>(b),
743 static_cast<CompletionCondition&&>(completion_condition));
744}
745
746#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
747#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
748#endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
749
750namespace detail
751{
752 template <typename AsyncWriteStream, typename DynamicBuffer_v2,
753 typename CompletionCondition, typename WriteHandler>
754 class write_dynbuf_v2_op
755 {
756 public:
757 template <typename BufferSequence>
758 write_dynbuf_v2_op(AsyncWriteStream& stream,
759 BufferSequence&& buffers,
760 CompletionCondition& completion_condition, WriteHandler& handler)
761 : stream_(stream),
762 buffers_(static_cast<BufferSequence&&>(buffers)),
763 completion_condition_(
764 static_cast<CompletionCondition&&>(completion_condition)),
765 handler_(static_cast<WriteHandler&&>(handler))
766 {
767 }
768
769 write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
770 : stream_(other.stream_),
771 buffers_(other.buffers_),
772 completion_condition_(other.completion_condition_),
773 handler_(other.handler_)
774 {
775 }
776
777 write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
778 : stream_(other.stream_),
779 buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
780 completion_condition_(
781 static_cast<CompletionCondition&&>(
782 other.completion_condition_)),
783 handler_(static_cast<WriteHandler&&>(other.handler_))
784 {
785 }
786
787 void operator()(const boost::system::error_code& ec,
788 std::size_t bytes_transferred, int start = 0)
789 {
790 switch (start)
791 {
792 case 1:
793 async_write(stream_, buffers_.data(0, buffers_.size()),
794 static_cast<CompletionCondition&&>(completion_condition_),
795 static_cast<write_dynbuf_v2_op&&>(*this));
796 return; default:
797 buffers_.consume(bytes_transferred);
798 static_cast<WriteHandler&&>(handler_)(ec,
799 static_cast<const std::size_t&>(bytes_transferred));
800 }
801 }
802
803 //private:
804 AsyncWriteStream& stream_;
805 DynamicBuffer_v2 buffers_;
806 CompletionCondition completion_condition_;
807 WriteHandler handler_;
808 };
809
810 template <typename AsyncWriteStream, typename DynamicBuffer_v2,
811 typename CompletionCondition, typename WriteHandler>
812 inline bool asio_handler_is_continuation(
813 write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
814 CompletionCondition, WriteHandler>* this_handler)
815 {
816 return boost_asio_handler_cont_helpers::is_continuation(
817 this_handler->handler_);
818 }
819
820 template <typename AsyncWriteStream>
821 class initiate_async_write_dynbuf_v2
822 {
823 public:
824 typedef typename AsyncWriteStream::executor_type executor_type;
825
826 explicit initiate_async_write_dynbuf_v2(AsyncWriteStream& stream)
827 : stream_(stream)
828 {
829 }
830
831 executor_type get_executor() const noexcept
832 {
833 return stream_.get_executor();
834 }
835
836 template <typename WriteHandler, typename DynamicBuffer_v2,
837 typename CompletionCondition>
838 void operator()(WriteHandler&& handler,
839 DynamicBuffer_v2&& buffers,
840 CompletionCondition&& completion_cond) const
841 {
842 // If you get an error on the following line it means that your handler
843 // does not meet the documented type requirements for a WriteHandler.
844 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
845
846 non_const_lvalue<WriteHandler> handler2(handler);
847 non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
848 write_dynbuf_v2_op<AsyncWriteStream, decay_t<DynamicBuffer_v2>,
849 CompletionCondition, decay_t<WriteHandler>>(
850 stream_, static_cast<DynamicBuffer_v2&&>(buffers),
851 completion_cond2.value, handler2.value)(
852 boost::system::error_code(), 0, 1);
853 }
854
855 private:
856 AsyncWriteStream& stream_;
857 };
858} // namespace detail
859
860#if !defined(GENERATING_DOCUMENTATION)
861
862template <template <typename, typename> class Associator,
863 typename AsyncWriteStream, typename DynamicBuffer_v2,
864 typename CompletionCondition, typename WriteHandler,
865 typename DefaultCandidate>
866struct associator<Associator,
867 detail::write_dynbuf_v2_op<AsyncWriteStream,
868 DynamicBuffer_v2, CompletionCondition, WriteHandler>,
869 DefaultCandidate>
870 : Associator<WriteHandler, DefaultCandidate>
871{
872 static typename Associator<WriteHandler, DefaultCandidate>::type get(
873 const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
874 CompletionCondition, WriteHandler>& h) noexcept
875 {
876 return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
877 }
878
879 static auto get(
880 const detail::write_dynbuf_v2_op<AsyncWriteStream,
881 DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
882 const DefaultCandidate& c) noexcept
883 -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
884 {
885 return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
886 }
887};
888
889#endif // !defined(GENERATING_DOCUMENTATION)
890
891template <typename AsyncWriteStream, typename DynamicBuffer_v2,
892 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
893 std::size_t)) WriteToken>
894inline auto async_write(AsyncWriteStream& s,
895 DynamicBuffer_v2 buffers, WriteToken&& token,
896 constraint_t<
897 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
898 >)
899 -> decltype(
900 async_initiate<WriteToken,
901 void (boost::system::error_code, std::size_t)>(
902 declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(),
903 token, static_cast<DynamicBuffer_v2&&>(buffers),
904 transfer_all()))
905{
906 return async_initiate<WriteToken,
907 void (boost::system::error_code, std::size_t)>(
908 detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),
909 token, static_cast<DynamicBuffer_v2&&>(buffers),
910 transfer_all());
911}
912
913template <typename AsyncWriteStream,
914 typename DynamicBuffer_v2, typename CompletionCondition,
915 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
916 std::size_t)) WriteToken>
917inline auto async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
918 CompletionCondition completion_condition, WriteToken&& token,
919 constraint_t<
920 is_dynamic_buffer_v2<DynamicBuffer_v2>::value
921 >)
922 -> decltype(
923 async_initiate<WriteToken,
924 void (boost::system::error_code, std::size_t)>(
925 declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(),
926 token, static_cast<DynamicBuffer_v2&&>(buffers),
927 static_cast<CompletionCondition&&>(completion_condition)))
928{
929 return async_initiate<WriteToken,
930 void (boost::system::error_code, std::size_t)>(
931 detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),
932 token, static_cast<DynamicBuffer_v2&&>(buffers),
933 static_cast<CompletionCondition&&>(completion_condition));
934}
935
936} // namespace asio
937} // namespace boost
938
939#include <boost/asio/detail/pop_options.hpp>
940
941#endif // BOOST_ASIO_IMPL_WRITE_HPP
942

source code of boost/libs/asio/include/boost/asio/impl/write.hpp