Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:06:45

0001 //
0002 // impl/write.hpp
0003 // ~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_IMPL_WRITE_HPP
0012 #define BOOST_ASIO_IMPL_WRITE_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/associator.hpp>
0019 #include <boost/asio/buffer.hpp>
0020 #include <boost/asio/detail/array_fwd.hpp>
0021 #include <boost/asio/detail/base_from_cancellation_state.hpp>
0022 #include <boost/asio/detail/base_from_completion_cond.hpp>
0023 #include <boost/asio/detail/bind_handler.hpp>
0024 #include <boost/asio/detail/consuming_buffers.hpp>
0025 #include <boost/asio/detail/dependent_type.hpp>
0026 #include <boost/asio/detail/handler_cont_helpers.hpp>
0027 #include <boost/asio/detail/handler_tracking.hpp>
0028 #include <boost/asio/detail/handler_type_requirements.hpp>
0029 #include <boost/asio/detail/non_const_lvalue.hpp>
0030 #include <boost/asio/detail/throw_error.hpp>
0031 
0032 #include <boost/asio/detail/push_options.hpp>
0033 
0034 namespace boost {
0035 namespace asio {
0036 
0037 namespace detail
0038 {
0039   template <typename SyncWriteStream, typename ConstBufferSequence,
0040       typename ConstBufferIterator, typename CompletionCondition>
0041   std::size_t write(SyncWriteStream& s,
0042       const ConstBufferSequence& buffers, const ConstBufferIterator&,
0043       CompletionCondition completion_condition, boost::system::error_code& ec)
0044   {
0045     ec = boost::system::error_code();
0046     boost::asio::detail::consuming_buffers<const_buffer,
0047         ConstBufferSequence, ConstBufferIterator> tmp(buffers);
0048     while (!tmp.empty())
0049     {
0050       if (std::size_t max_size = detail::adapt_completion_condition_result(
0051             completion_condition(ec, tmp.total_consumed())))
0052         tmp.consume(s.write_some(tmp.prepare(max_size), ec));
0053       else
0054         break;
0055     }
0056     return tmp.total_consumed();
0057   }
0058 } // namespace detail
0059 
0060 template <typename SyncWriteStream, typename ConstBufferSequence,
0061     typename CompletionCondition>
0062 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
0063     CompletionCondition completion_condition, boost::system::error_code& ec,
0064     constraint_t<
0065       is_const_buffer_sequence<ConstBufferSequence>::value
0066     >,
0067     constraint_t<
0068       is_completion_condition<CompletionCondition>::value
0069     >)
0070 {
0071   return detail::write(s, buffers,
0072       boost::asio::buffer_sequence_begin(buffers),
0073       static_cast<CompletionCondition&&>(completion_condition), ec);
0074 }
0075 
0076 template <typename SyncWriteStream, typename ConstBufferSequence>
0077 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
0078     constraint_t<
0079       is_const_buffer_sequence<ConstBufferSequence>::value
0080     >)
0081 {
0082   boost::system::error_code ec;
0083   std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
0084   boost::asio::detail::throw_error(ec, "write");
0085   return bytes_transferred;
0086 }
0087 
0088 template <typename SyncWriteStream, typename ConstBufferSequence>
0089 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
0090     boost::system::error_code& ec,
0091     constraint_t<
0092       is_const_buffer_sequence<ConstBufferSequence>::value
0093     >)
0094 {
0095   return write(s, buffers, transfer_all(), ec);
0096 }
0097 
0098 template <typename SyncWriteStream, typename ConstBufferSequence,
0099     typename CompletionCondition>
0100 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
0101     CompletionCondition completion_condition,
0102     constraint_t<
0103       is_const_buffer_sequence<ConstBufferSequence>::value
0104     >,
0105     constraint_t<
0106       is_completion_condition<CompletionCondition>::value
0107     >)
0108 {
0109   boost::system::error_code ec;
0110   std::size_t bytes_transferred = write(s, buffers,
0111       static_cast<CompletionCondition&&>(completion_condition), ec);
0112   boost::asio::detail::throw_error(ec, "write");
0113   return bytes_transferred;
0114 }
0115 
0116 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0117 
0118 template <typename SyncWriteStream, typename DynamicBuffer_v1,
0119     typename CompletionCondition>
0120 std::size_t write(SyncWriteStream& s,
0121     DynamicBuffer_v1&& buffers,
0122     CompletionCondition completion_condition, boost::system::error_code& ec,
0123     constraint_t<
0124       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0125     >,
0126     constraint_t<
0127       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0128     >,
0129     constraint_t<
0130       is_completion_condition<CompletionCondition>::value
0131     >)
0132 {
0133   decay_t<DynamicBuffer_v1> b(
0134       static_cast<DynamicBuffer_v1&&>(buffers));
0135 
0136   std::size_t bytes_transferred = write(s, b.data(),
0137       static_cast<CompletionCondition&&>(completion_condition), ec);
0138   b.consume(bytes_transferred);
0139   return bytes_transferred;
0140 }
0141 
0142 template <typename SyncWriteStream, typename DynamicBuffer_v1>
0143 inline std::size_t write(SyncWriteStream& s,
0144     DynamicBuffer_v1&& buffers,
0145     constraint_t<
0146       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0147     >,
0148     constraint_t<
0149       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0150     >)
0151 {
0152   boost::system::error_code ec;
0153   std::size_t bytes_transferred = write(s,
0154       static_cast<DynamicBuffer_v1&&>(buffers),
0155       transfer_all(), ec);
0156   boost::asio::detail::throw_error(ec, "write");
0157   return bytes_transferred;
0158 }
0159 
0160 template <typename SyncWriteStream, typename DynamicBuffer_v1>
0161 inline std::size_t write(SyncWriteStream& s,
0162     DynamicBuffer_v1&& buffers,
0163     boost::system::error_code& ec,
0164     constraint_t<
0165       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0166     >,
0167     constraint_t<
0168       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0169     >)
0170 {
0171   return write(s, static_cast<DynamicBuffer_v1&&>(buffers),
0172       transfer_all(), ec);
0173 }
0174 
0175 template <typename SyncWriteStream, typename DynamicBuffer_v1,
0176     typename CompletionCondition>
0177 inline std::size_t write(SyncWriteStream& s,
0178     DynamicBuffer_v1&& buffers,
0179     CompletionCondition completion_condition,
0180     constraint_t<
0181       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0182     >,
0183     constraint_t<
0184       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0185     >,
0186     constraint_t<
0187       is_completion_condition<CompletionCondition>::value
0188     >)
0189 {
0190   boost::system::error_code ec;
0191   std::size_t bytes_transferred = write(s,
0192       static_cast<DynamicBuffer_v1&&>(buffers),
0193       static_cast<CompletionCondition&&>(completion_condition), ec);
0194   boost::asio::detail::throw_error(ec, "write");
0195   return bytes_transferred;
0196 }
0197 
0198 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0199 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0200 
0201 template <typename SyncWriteStream, typename Allocator,
0202     typename CompletionCondition>
0203 inline std::size_t write(SyncWriteStream& s,
0204     boost::asio::basic_streambuf<Allocator>& b,
0205     CompletionCondition completion_condition, boost::system::error_code& ec,
0206     constraint_t<
0207       is_completion_condition<CompletionCondition>::value
0208     >)
0209 {
0210   return write(s, basic_streambuf_ref<Allocator>(b),
0211       static_cast<CompletionCondition&&>(completion_condition), ec);
0212 }
0213 
0214 template <typename SyncWriteStream, typename Allocator>
0215 inline std::size_t write(SyncWriteStream& s,
0216     boost::asio::basic_streambuf<Allocator>& b)
0217 {
0218   return write(s, basic_streambuf_ref<Allocator>(b));
0219 }
0220 
0221 template <typename SyncWriteStream, typename Allocator>
0222 inline std::size_t write(SyncWriteStream& s,
0223     boost::asio::basic_streambuf<Allocator>& b,
0224     boost::system::error_code& ec)
0225 {
0226   return write(s, basic_streambuf_ref<Allocator>(b), ec);
0227 }
0228 
0229 template <typename SyncWriteStream, typename Allocator,
0230     typename CompletionCondition>
0231 inline std::size_t write(SyncWriteStream& s,
0232     boost::asio::basic_streambuf<Allocator>& b,
0233     CompletionCondition completion_condition,
0234     constraint_t<
0235       is_completion_condition<CompletionCondition>::value
0236     >)
0237 {
0238   return write(s, basic_streambuf_ref<Allocator>(b),
0239       static_cast<CompletionCondition&&>(completion_condition));
0240 }
0241 
0242 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0243 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0244 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0245 
0246 template <typename SyncWriteStream, typename DynamicBuffer_v2,
0247     typename CompletionCondition>
0248 std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
0249     CompletionCondition completion_condition, boost::system::error_code& ec,
0250     constraint_t<
0251       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0252     >,
0253     constraint_t<
0254       is_completion_condition<CompletionCondition>::value
0255     >)
0256 {
0257   std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),
0258       static_cast<CompletionCondition&&>(completion_condition), ec);
0259   buffers.consume(bytes_transferred);
0260   return bytes_transferred;
0261 }
0262 
0263 template <typename SyncWriteStream, typename DynamicBuffer_v2>
0264 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
0265     constraint_t<
0266       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0267     >)
0268 {
0269   boost::system::error_code ec;
0270   std::size_t bytes_transferred = write(s,
0271       static_cast<DynamicBuffer_v2&&>(buffers),
0272       transfer_all(), ec);
0273   boost::asio::detail::throw_error(ec, "write");
0274   return bytes_transferred;
0275 }
0276 
0277 template <typename SyncWriteStream, typename DynamicBuffer_v2>
0278 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
0279     boost::system::error_code& ec,
0280     constraint_t<
0281       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0282     >)
0283 {
0284   return write(s, static_cast<DynamicBuffer_v2&&>(buffers),
0285       transfer_all(), ec);
0286 }
0287 
0288 template <typename SyncWriteStream, typename DynamicBuffer_v2,
0289     typename CompletionCondition>
0290 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
0291     CompletionCondition completion_condition,
0292     constraint_t<
0293       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0294     >,
0295     constraint_t<
0296       is_completion_condition<CompletionCondition>::value
0297     >)
0298 {
0299   boost::system::error_code ec;
0300   std::size_t bytes_transferred = write(s,
0301       static_cast<DynamicBuffer_v2&&>(buffers),
0302       static_cast<CompletionCondition&&>(completion_condition), ec);
0303   boost::asio::detail::throw_error(ec, "write");
0304   return bytes_transferred;
0305 }
0306 
0307 namespace detail
0308 {
0309   template <typename AsyncWriteStream, typename ConstBufferSequence,
0310       typename ConstBufferIterator, typename CompletionCondition,
0311       typename WriteHandler>
0312   class write_op
0313     : public base_from_cancellation_state<WriteHandler>,
0314       base_from_completion_cond<CompletionCondition>
0315   {
0316   public:
0317     write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
0318         CompletionCondition& completion_condition, WriteHandler& handler)
0319       : base_from_cancellation_state<WriteHandler>(
0320           handler, enable_partial_cancellation()),
0321         base_from_completion_cond<CompletionCondition>(completion_condition),
0322         stream_(stream),
0323         buffers_(buffers),
0324         start_(0),
0325         handler_(static_cast<WriteHandler&&>(handler))
0326     {
0327     }
0328 
0329     write_op(const write_op& other)
0330       : base_from_cancellation_state<WriteHandler>(other),
0331         base_from_completion_cond<CompletionCondition>(other),
0332         stream_(other.stream_),
0333         buffers_(other.buffers_),
0334         start_(other.start_),
0335         handler_(other.handler_)
0336     {
0337     }
0338 
0339     write_op(write_op&& other)
0340       : base_from_cancellation_state<WriteHandler>(
0341           static_cast<base_from_cancellation_state<WriteHandler>&&>(other)),
0342         base_from_completion_cond<CompletionCondition>(
0343           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0344         stream_(other.stream_),
0345         buffers_(static_cast<buffers_type&&>(other.buffers_)),
0346         start_(other.start_),
0347         handler_(static_cast<WriteHandler&&>(other.handler_))
0348     {
0349     }
0350 
0351     void operator()(boost::system::error_code ec,
0352         std::size_t bytes_transferred, int start = 0)
0353     {
0354       std::size_t max_size;
0355       switch (start_ = start)
0356       {
0357         case 1:
0358         max_size = this->check_for_completion(ec, buffers_.total_consumed());
0359         for (;;)
0360         {
0361           {
0362             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write"));
0363             stream_.async_write_some(buffers_.prepare(max_size),
0364                 static_cast<write_op&&>(*this));
0365           }
0366           return; default:
0367           buffers_.consume(bytes_transferred);
0368           if ((!ec && bytes_transferred == 0) || buffers_.empty())
0369             break;
0370           max_size = this->check_for_completion(ec, buffers_.total_consumed());
0371           if (max_size == 0)
0372             break;
0373           if (this->cancelled() != cancellation_type::none)
0374           {
0375             ec = error::operation_aborted;
0376             break;
0377           }
0378         }
0379 
0380         static_cast<WriteHandler&&>(handler_)(
0381             static_cast<const boost::system::error_code&>(ec),
0382             static_cast<const std::size_t&>(buffers_.total_consumed()));
0383       }
0384     }
0385 
0386   //private:
0387     typedef boost::asio::detail::consuming_buffers<const_buffer,
0388         ConstBufferSequence, ConstBufferIterator> buffers_type;
0389 
0390     AsyncWriteStream& stream_;
0391     buffers_type buffers_;
0392     int start_;
0393     WriteHandler handler_;
0394   };
0395 
0396   template <typename AsyncWriteStream, typename ConstBufferSequence,
0397       typename ConstBufferIterator, typename CompletionCondition,
0398       typename WriteHandler>
0399   inline bool asio_handler_is_continuation(
0400       write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
0401         CompletionCondition, WriteHandler>* this_handler)
0402   {
0403     return this_handler->start_ == 0 ? true
0404       : boost_asio_handler_cont_helpers::is_continuation(
0405           this_handler->handler_);
0406   }
0407 
0408   template <typename AsyncWriteStream, typename ConstBufferSequence,
0409       typename ConstBufferIterator, typename CompletionCondition,
0410       typename WriteHandler>
0411   inline void start_write_op(AsyncWriteStream& stream,
0412       const ConstBufferSequence& buffers, const ConstBufferIterator&,
0413       CompletionCondition& completion_condition, WriteHandler& handler)
0414   {
0415     detail::write_op<AsyncWriteStream, ConstBufferSequence,
0416       ConstBufferIterator, CompletionCondition, WriteHandler>(
0417         stream, buffers, completion_condition, handler)(
0418           boost::system::error_code(), 0, 1);
0419   }
0420 
0421   template <typename AsyncWriteStream>
0422   class initiate_async_write
0423   {
0424   public:
0425     typedef typename AsyncWriteStream::executor_type executor_type;
0426 
0427     explicit initiate_async_write(AsyncWriteStream& stream)
0428       : stream_(stream)
0429     {
0430     }
0431 
0432     executor_type get_executor() const noexcept
0433     {
0434       return stream_.get_executor();
0435     }
0436 
0437     template <typename WriteHandler, typename ConstBufferSequence,
0438         typename CompletionCondition>
0439     void operator()(WriteHandler&& handler,
0440         const ConstBufferSequence& buffers,
0441         CompletionCondition&& completion_cond) const
0442     {
0443       // If you get an error on the following line it means that your handler
0444       // does not meet the documented type requirements for a WriteHandler.
0445       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0446 
0447       non_const_lvalue<WriteHandler> handler2(handler);
0448       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0449       start_write_op(stream_, buffers,
0450           boost::asio::buffer_sequence_begin(buffers),
0451           completion_cond2.value, handler2.value);
0452     }
0453 
0454   private:
0455     AsyncWriteStream& stream_;
0456   };
0457 } // namespace detail
0458 
0459 #if !defined(GENERATING_DOCUMENTATION)
0460 
0461 template <template <typename, typename> class Associator,
0462     typename AsyncWriteStream, typename ConstBufferSequence,
0463     typename ConstBufferIterator, typename CompletionCondition,
0464     typename WriteHandler, typename DefaultCandidate>
0465 struct associator<Associator,
0466     detail::write_op<AsyncWriteStream, ConstBufferSequence,
0467       ConstBufferIterator, CompletionCondition, WriteHandler>,
0468     DefaultCandidate>
0469   : Associator<WriteHandler, DefaultCandidate>
0470 {
0471   static typename Associator<WriteHandler, DefaultCandidate>::type get(
0472       const detail::write_op<AsyncWriteStream, ConstBufferSequence,
0473         ConstBufferIterator, CompletionCondition, WriteHandler>& h) noexcept
0474   {
0475     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
0476   }
0477 
0478   static auto get(
0479       const detail::write_op<AsyncWriteStream, ConstBufferSequence,
0480         ConstBufferIterator, CompletionCondition, WriteHandler>& h,
0481       const DefaultCandidate& c) noexcept
0482     -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
0483   {
0484     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
0485   }
0486 };
0487 
0488 #endif // !defined(GENERATING_DOCUMENTATION)
0489 
0490 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0491 
0492 namespace detail
0493 {
0494   template <typename AsyncWriteStream, typename DynamicBuffer_v1,
0495       typename CompletionCondition, typename WriteHandler>
0496   class write_dynbuf_v1_op
0497   {
0498   public:
0499     template <typename BufferSequence>
0500     write_dynbuf_v1_op(AsyncWriteStream& stream,
0501         BufferSequence&& buffers,
0502         CompletionCondition& completion_condition, WriteHandler& handler)
0503       : stream_(stream),
0504         buffers_(static_cast<BufferSequence&&>(buffers)),
0505         completion_condition_(
0506           static_cast<CompletionCondition&&>(completion_condition)),
0507         handler_(static_cast<WriteHandler&&>(handler))
0508     {
0509     }
0510 
0511     write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
0512       : stream_(other.stream_),
0513         buffers_(other.buffers_),
0514         completion_condition_(other.completion_condition_),
0515         handler_(other.handler_)
0516     {
0517     }
0518 
0519     write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
0520       : stream_(other.stream_),
0521         buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
0522         completion_condition_(
0523           static_cast<CompletionCondition&&>(
0524             other.completion_condition_)),
0525         handler_(static_cast<WriteHandler&&>(other.handler_))
0526     {
0527     }
0528 
0529     void operator()(const boost::system::error_code& ec,
0530         std::size_t bytes_transferred, int start = 0)
0531     {
0532       switch (start)
0533       {
0534         case 1:
0535         async_write(stream_, buffers_.data(),
0536             static_cast<CompletionCondition&&>(completion_condition_),
0537             static_cast<write_dynbuf_v1_op&&>(*this));
0538         return; default:
0539         buffers_.consume(bytes_transferred);
0540         static_cast<WriteHandler&&>(handler_)(ec,
0541             static_cast<const std::size_t&>(bytes_transferred));
0542       }
0543     }
0544 
0545   //private:
0546     AsyncWriteStream& stream_;
0547     DynamicBuffer_v1 buffers_;
0548     CompletionCondition completion_condition_;
0549     WriteHandler handler_;
0550   };
0551 
0552   template <typename AsyncWriteStream, typename DynamicBuffer_v1,
0553       typename CompletionCondition, typename WriteHandler>
0554   inline bool asio_handler_is_continuation(
0555       write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
0556         CompletionCondition, WriteHandler>* this_handler)
0557   {
0558     return boost_asio_handler_cont_helpers::is_continuation(
0559         this_handler->handler_);
0560   }
0561 
0562   template <typename AsyncWriteStream>
0563   class initiate_async_write_dynbuf_v1
0564   {
0565   public:
0566     typedef typename AsyncWriteStream::executor_type executor_type;
0567 
0568     explicit initiate_async_write_dynbuf_v1(AsyncWriteStream& stream)
0569       : stream_(stream)
0570     {
0571     }
0572 
0573     executor_type get_executor() const noexcept
0574     {
0575       return stream_.get_executor();
0576     }
0577 
0578     template <typename WriteHandler, typename DynamicBuffer_v1,
0579         typename CompletionCondition>
0580     void operator()(WriteHandler&& handler,
0581         DynamicBuffer_v1&& buffers,
0582         CompletionCondition&& completion_cond) const
0583     {
0584       // If you get an error on the following line it means that your handler
0585       // does not meet the documented type requirements for a WriteHandler.
0586       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0587 
0588       non_const_lvalue<WriteHandler> handler2(handler);
0589       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0590       write_dynbuf_v1_op<AsyncWriteStream,
0591         decay_t<DynamicBuffer_v1>,
0592           CompletionCondition, decay_t<WriteHandler>>(
0593             stream_, static_cast<DynamicBuffer_v1&&>(buffers),
0594               completion_cond2.value, handler2.value)(
0595                 boost::system::error_code(), 0, 1);
0596     }
0597 
0598   private:
0599     AsyncWriteStream& stream_;
0600   };
0601 } // namespace detail
0602 
0603 #if !defined(GENERATING_DOCUMENTATION)
0604 
0605 template <template <typename, typename> class Associator,
0606     typename AsyncWriteStream, typename DynamicBuffer_v1,
0607     typename CompletionCondition, typename WriteHandler,
0608     typename DefaultCandidate>
0609 struct associator<Associator,
0610     detail::write_dynbuf_v1_op<AsyncWriteStream,
0611       DynamicBuffer_v1, CompletionCondition, WriteHandler>,
0612     DefaultCandidate>
0613   : Associator<WriteHandler, DefaultCandidate>
0614 {
0615   static typename Associator<WriteHandler, DefaultCandidate>::type get(
0616       const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
0617         CompletionCondition, WriteHandler>& h) noexcept
0618   {
0619     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
0620   }
0621 
0622   static auto get(
0623       const detail::write_dynbuf_v1_op<AsyncWriteStream,
0624         DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
0625       const DefaultCandidate& c) noexcept
0626     -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
0627   {
0628     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
0629   }
0630 };
0631 
0632 #endif // !defined(GENERATING_DOCUMENTATION)
0633 
0634 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0635 
0636 namespace detail
0637 {
0638   template <typename AsyncWriteStream, typename DynamicBuffer_v2,
0639       typename CompletionCondition, typename WriteHandler>
0640   class write_dynbuf_v2_op
0641   {
0642   public:
0643     template <typename BufferSequence>
0644     write_dynbuf_v2_op(AsyncWriteStream& stream,
0645         BufferSequence&& buffers,
0646         CompletionCondition& completion_condition, WriteHandler& handler)
0647       : stream_(stream),
0648         buffers_(static_cast<BufferSequence&&>(buffers)),
0649         completion_condition_(
0650           static_cast<CompletionCondition&&>(completion_condition)),
0651         handler_(static_cast<WriteHandler&&>(handler))
0652     {
0653     }
0654 
0655     write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
0656       : stream_(other.stream_),
0657         buffers_(other.buffers_),
0658         completion_condition_(other.completion_condition_),
0659         handler_(other.handler_)
0660     {
0661     }
0662 
0663     write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
0664       : stream_(other.stream_),
0665         buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
0666         completion_condition_(
0667           static_cast<CompletionCondition&&>(
0668             other.completion_condition_)),
0669         handler_(static_cast<WriteHandler&&>(other.handler_))
0670     {
0671     }
0672 
0673     void operator()(const boost::system::error_code& ec,
0674         std::size_t bytes_transferred, int start = 0)
0675     {
0676       switch (start)
0677       {
0678         case 1:
0679         async_write(stream_, buffers_.data(0, buffers_.size()),
0680             static_cast<CompletionCondition&&>(completion_condition_),
0681             static_cast<write_dynbuf_v2_op&&>(*this));
0682         return; default:
0683         buffers_.consume(bytes_transferred);
0684         static_cast<WriteHandler&&>(handler_)(ec,
0685             static_cast<const std::size_t&>(bytes_transferred));
0686       }
0687     }
0688 
0689   //private:
0690     AsyncWriteStream& stream_;
0691     DynamicBuffer_v2 buffers_;
0692     CompletionCondition completion_condition_;
0693     WriteHandler handler_;
0694   };
0695 
0696   template <typename AsyncWriteStream, typename DynamicBuffer_v2,
0697       typename CompletionCondition, typename WriteHandler>
0698   inline bool asio_handler_is_continuation(
0699       write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
0700         CompletionCondition, WriteHandler>* this_handler)
0701   {
0702     return boost_asio_handler_cont_helpers::is_continuation(
0703         this_handler->handler_);
0704   }
0705 
0706   template <typename AsyncWriteStream>
0707   class initiate_async_write_dynbuf_v2
0708   {
0709   public:
0710     typedef typename AsyncWriteStream::executor_type executor_type;
0711 
0712     explicit initiate_async_write_dynbuf_v2(AsyncWriteStream& stream)
0713       : stream_(stream)
0714     {
0715     }
0716 
0717     executor_type get_executor() const noexcept
0718     {
0719       return stream_.get_executor();
0720     }
0721 
0722     template <typename WriteHandler, typename DynamicBuffer_v2,
0723         typename CompletionCondition>
0724     void operator()(WriteHandler&& handler,
0725         DynamicBuffer_v2&& buffers,
0726         CompletionCondition&& completion_cond) const
0727     {
0728       // If you get an error on the following line it means that your handler
0729       // does not meet the documented type requirements for a WriteHandler.
0730       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0731 
0732       non_const_lvalue<WriteHandler> handler2(handler);
0733       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0734       write_dynbuf_v2_op<AsyncWriteStream, decay_t<DynamicBuffer_v2>,
0735         CompletionCondition, decay_t<WriteHandler>>(
0736           stream_, static_cast<DynamicBuffer_v2&&>(buffers),
0737             completion_cond2.value, handler2.value)(
0738               boost::system::error_code(), 0, 1);
0739     }
0740 
0741   private:
0742     AsyncWriteStream& stream_;
0743   };
0744 } // namespace detail
0745 
0746 #if !defined(GENERATING_DOCUMENTATION)
0747 
0748 template <template <typename, typename> class Associator,
0749     typename AsyncWriteStream, typename DynamicBuffer_v2,
0750     typename CompletionCondition, typename WriteHandler,
0751     typename DefaultCandidate>
0752 struct associator<Associator,
0753     detail::write_dynbuf_v2_op<AsyncWriteStream,
0754       DynamicBuffer_v2, CompletionCondition, WriteHandler>,
0755     DefaultCandidate>
0756   : Associator<WriteHandler, DefaultCandidate>
0757 {
0758   static typename Associator<WriteHandler, DefaultCandidate>::type get(
0759       const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
0760         CompletionCondition, WriteHandler>& h) noexcept
0761   {
0762     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
0763   }
0764 
0765   static auto get(
0766       const detail::write_dynbuf_v2_op<AsyncWriteStream,
0767         DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
0768       const DefaultCandidate& c) noexcept
0769     -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
0770   {
0771     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
0772   }
0773 };
0774 
0775 #endif // !defined(GENERATING_DOCUMENTATION)
0776 
0777 } // namespace asio
0778 } // namespace boost
0779 
0780 #include <boost/asio/detail/pop_options.hpp>
0781 
0782 #endif // BOOST_ASIO_IMPL_WRITE_HPP