Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:58

0001 //
0002 // impl/write.hpp
0003 // ~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 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 {
0068   return detail::write(s, buffers,
0069       boost::asio::buffer_sequence_begin(buffers),
0070       static_cast<CompletionCondition&&>(completion_condition), ec);
0071 }
0072 
0073 template <typename SyncWriteStream, typename ConstBufferSequence>
0074 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
0075     constraint_t<
0076       is_const_buffer_sequence<ConstBufferSequence>::value
0077     >)
0078 {
0079   boost::system::error_code ec;
0080   std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
0081   boost::asio::detail::throw_error(ec, "write");
0082   return bytes_transferred;
0083 }
0084 
0085 template <typename SyncWriteStream, typename ConstBufferSequence>
0086 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
0087     boost::system::error_code& ec,
0088     constraint_t<
0089       is_const_buffer_sequence<ConstBufferSequence>::value
0090     >)
0091 {
0092   return write(s, buffers, transfer_all(), ec);
0093 }
0094 
0095 template <typename SyncWriteStream, typename ConstBufferSequence,
0096     typename CompletionCondition>
0097 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
0098     CompletionCondition completion_condition,
0099     constraint_t<
0100       is_const_buffer_sequence<ConstBufferSequence>::value
0101     >)
0102 {
0103   boost::system::error_code ec;
0104   std::size_t bytes_transferred = write(s, buffers,
0105       static_cast<CompletionCondition&&>(completion_condition), ec);
0106   boost::asio::detail::throw_error(ec, "write");
0107   return bytes_transferred;
0108 }
0109 
0110 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0111 
0112 template <typename SyncWriteStream, typename DynamicBuffer_v1,
0113     typename CompletionCondition>
0114 std::size_t write(SyncWriteStream& s,
0115     DynamicBuffer_v1&& buffers,
0116     CompletionCondition completion_condition, boost::system::error_code& ec,
0117     constraint_t<
0118       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0119     >,
0120     constraint_t<
0121       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0122     >)
0123 {
0124   decay_t<DynamicBuffer_v1> b(
0125       static_cast<DynamicBuffer_v1&&>(buffers));
0126 
0127   std::size_t bytes_transferred = write(s, b.data(),
0128       static_cast<CompletionCondition&&>(completion_condition), ec);
0129   b.consume(bytes_transferred);
0130   return bytes_transferred;
0131 }
0132 
0133 template <typename SyncWriteStream, typename DynamicBuffer_v1>
0134 inline std::size_t write(SyncWriteStream& s,
0135     DynamicBuffer_v1&& buffers,
0136     constraint_t<
0137       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0138     >,
0139     constraint_t<
0140       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0141     >)
0142 {
0143   boost::system::error_code ec;
0144   std::size_t bytes_transferred = write(s,
0145       static_cast<DynamicBuffer_v1&&>(buffers),
0146       transfer_all(), ec);
0147   boost::asio::detail::throw_error(ec, "write");
0148   return bytes_transferred;
0149 }
0150 
0151 template <typename SyncWriteStream, typename DynamicBuffer_v1>
0152 inline std::size_t write(SyncWriteStream& s,
0153     DynamicBuffer_v1&& buffers,
0154     boost::system::error_code& ec,
0155     constraint_t<
0156       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0157     >,
0158     constraint_t<
0159       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0160     >)
0161 {
0162   return write(s, static_cast<DynamicBuffer_v1&&>(buffers),
0163       transfer_all(), ec);
0164 }
0165 
0166 template <typename SyncWriteStream, typename DynamicBuffer_v1,
0167     typename CompletionCondition>
0168 inline std::size_t write(SyncWriteStream& s,
0169     DynamicBuffer_v1&& buffers,
0170     CompletionCondition completion_condition,
0171     constraint_t<
0172       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0173     >,
0174     constraint_t<
0175       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0176     >)
0177 {
0178   boost::system::error_code ec;
0179   std::size_t bytes_transferred = write(s,
0180       static_cast<DynamicBuffer_v1&&>(buffers),
0181       static_cast<CompletionCondition&&>(completion_condition), ec);
0182   boost::asio::detail::throw_error(ec, "write");
0183   return bytes_transferred;
0184 }
0185 
0186 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0187 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0188 
0189 template <typename SyncWriteStream, typename Allocator,
0190     typename CompletionCondition>
0191 inline std::size_t write(SyncWriteStream& s,
0192     boost::asio::basic_streambuf<Allocator>& b,
0193     CompletionCondition completion_condition, boost::system::error_code& ec)
0194 {
0195   return write(s, basic_streambuf_ref<Allocator>(b),
0196       static_cast<CompletionCondition&&>(completion_condition), ec);
0197 }
0198 
0199 template <typename SyncWriteStream, typename Allocator>
0200 inline std::size_t write(SyncWriteStream& s,
0201     boost::asio::basic_streambuf<Allocator>& b)
0202 {
0203   return write(s, basic_streambuf_ref<Allocator>(b));
0204 }
0205 
0206 template <typename SyncWriteStream, typename Allocator>
0207 inline std::size_t write(SyncWriteStream& s,
0208     boost::asio::basic_streambuf<Allocator>& b,
0209     boost::system::error_code& ec)
0210 {
0211   return write(s, basic_streambuf_ref<Allocator>(b), ec);
0212 }
0213 
0214 template <typename SyncWriteStream, typename Allocator,
0215     typename CompletionCondition>
0216 inline std::size_t write(SyncWriteStream& s,
0217     boost::asio::basic_streambuf<Allocator>& b,
0218     CompletionCondition completion_condition)
0219 {
0220   return write(s, basic_streambuf_ref<Allocator>(b),
0221       static_cast<CompletionCondition&&>(completion_condition));
0222 }
0223 
0224 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0225 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0226 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0227 
0228 template <typename SyncWriteStream, typename DynamicBuffer_v2,
0229     typename CompletionCondition>
0230 std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
0231     CompletionCondition completion_condition, boost::system::error_code& ec,
0232     constraint_t<
0233       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0234     >)
0235 {
0236   std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),
0237       static_cast<CompletionCondition&&>(completion_condition), ec);
0238   buffers.consume(bytes_transferred);
0239   return bytes_transferred;
0240 }
0241 
0242 template <typename SyncWriteStream, typename DynamicBuffer_v2>
0243 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
0244     constraint_t<
0245       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0246     >)
0247 {
0248   boost::system::error_code ec;
0249   std::size_t bytes_transferred = write(s,
0250       static_cast<DynamicBuffer_v2&&>(buffers),
0251       transfer_all(), ec);
0252   boost::asio::detail::throw_error(ec, "write");
0253   return bytes_transferred;
0254 }
0255 
0256 template <typename SyncWriteStream, typename DynamicBuffer_v2>
0257 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
0258     boost::system::error_code& ec,
0259     constraint_t<
0260       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0261     >)
0262 {
0263   return write(s, static_cast<DynamicBuffer_v2&&>(buffers),
0264       transfer_all(), ec);
0265 }
0266 
0267 template <typename SyncWriteStream, typename DynamicBuffer_v2,
0268     typename CompletionCondition>
0269 inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,
0270     CompletionCondition completion_condition,
0271     constraint_t<
0272       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0273     >)
0274 {
0275   boost::system::error_code ec;
0276   std::size_t bytes_transferred = write(s,
0277       static_cast<DynamicBuffer_v2&&>(buffers),
0278       static_cast<CompletionCondition&&>(completion_condition), ec);
0279   boost::asio::detail::throw_error(ec, "write");
0280   return bytes_transferred;
0281 }
0282 
0283 namespace detail
0284 {
0285   template <typename AsyncWriteStream, typename ConstBufferSequence,
0286       typename ConstBufferIterator, typename CompletionCondition,
0287       typename WriteHandler>
0288   class write_op
0289     : public base_from_cancellation_state<WriteHandler>,
0290       base_from_completion_cond<CompletionCondition>
0291   {
0292   public:
0293     write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
0294         CompletionCondition& completion_condition, WriteHandler& handler)
0295       : base_from_cancellation_state<WriteHandler>(
0296           handler, enable_partial_cancellation()),
0297         base_from_completion_cond<CompletionCondition>(completion_condition),
0298         stream_(stream),
0299         buffers_(buffers),
0300         start_(0),
0301         handler_(static_cast<WriteHandler&&>(handler))
0302     {
0303     }
0304 
0305     write_op(const write_op& other)
0306       : base_from_cancellation_state<WriteHandler>(other),
0307         base_from_completion_cond<CompletionCondition>(other),
0308         stream_(other.stream_),
0309         buffers_(other.buffers_),
0310         start_(other.start_),
0311         handler_(other.handler_)
0312     {
0313     }
0314 
0315     write_op(write_op&& other)
0316       : base_from_cancellation_state<WriteHandler>(
0317           static_cast<base_from_cancellation_state<WriteHandler>&&>(other)),
0318         base_from_completion_cond<CompletionCondition>(
0319           static_cast<base_from_completion_cond<CompletionCondition>&&>(other)),
0320         stream_(other.stream_),
0321         buffers_(static_cast<buffers_type&&>(other.buffers_)),
0322         start_(other.start_),
0323         handler_(static_cast<WriteHandler&&>(other.handler_))
0324     {
0325     }
0326 
0327     void operator()(boost::system::error_code ec,
0328         std::size_t bytes_transferred, int start = 0)
0329     {
0330       std::size_t max_size;
0331       switch (start_ = start)
0332       {
0333         case 1:
0334         max_size = this->check_for_completion(ec, buffers_.total_consumed());
0335         for (;;)
0336         {
0337           {
0338             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write"));
0339             stream_.async_write_some(buffers_.prepare(max_size),
0340                 static_cast<write_op&&>(*this));
0341           }
0342           return; default:
0343           buffers_.consume(bytes_transferred);
0344           if ((!ec && bytes_transferred == 0) || buffers_.empty())
0345             break;
0346           max_size = this->check_for_completion(ec, buffers_.total_consumed());
0347           if (max_size == 0)
0348             break;
0349           if (this->cancelled() != cancellation_type::none)
0350           {
0351             ec = error::operation_aborted;
0352             break;
0353           }
0354         }
0355 
0356         static_cast<WriteHandler&&>(handler_)(
0357             static_cast<const boost::system::error_code&>(ec),
0358             static_cast<const std::size_t&>(buffers_.total_consumed()));
0359       }
0360     }
0361 
0362   //private:
0363     typedef boost::asio::detail::consuming_buffers<const_buffer,
0364         ConstBufferSequence, ConstBufferIterator> buffers_type;
0365 
0366     AsyncWriteStream& stream_;
0367     buffers_type buffers_;
0368     int start_;
0369     WriteHandler handler_;
0370   };
0371 
0372   template <typename AsyncWriteStream, typename ConstBufferSequence,
0373       typename ConstBufferIterator, typename CompletionCondition,
0374       typename WriteHandler>
0375   inline bool asio_handler_is_continuation(
0376       write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
0377         CompletionCondition, WriteHandler>* this_handler)
0378   {
0379     return this_handler->start_ == 0 ? true
0380       : boost_asio_handler_cont_helpers::is_continuation(
0381           this_handler->handler_);
0382   }
0383 
0384   template <typename AsyncWriteStream, typename ConstBufferSequence,
0385       typename ConstBufferIterator, typename CompletionCondition,
0386       typename WriteHandler>
0387   inline void start_write_op(AsyncWriteStream& stream,
0388       const ConstBufferSequence& buffers, const ConstBufferIterator&,
0389       CompletionCondition& completion_condition, WriteHandler& handler)
0390   {
0391     detail::write_op<AsyncWriteStream, ConstBufferSequence,
0392       ConstBufferIterator, CompletionCondition, WriteHandler>(
0393         stream, buffers, completion_condition, handler)(
0394           boost::system::error_code(), 0, 1);
0395   }
0396 
0397   template <typename AsyncWriteStream>
0398   class initiate_async_write
0399   {
0400   public:
0401     typedef typename AsyncWriteStream::executor_type executor_type;
0402 
0403     explicit initiate_async_write(AsyncWriteStream& stream)
0404       : stream_(stream)
0405     {
0406     }
0407 
0408     executor_type get_executor() const noexcept
0409     {
0410       return stream_.get_executor();
0411     }
0412 
0413     template <typename WriteHandler, typename ConstBufferSequence,
0414         typename CompletionCondition>
0415     void operator()(WriteHandler&& handler,
0416         const ConstBufferSequence& buffers,
0417         CompletionCondition&& completion_cond) const
0418     {
0419       // If you get an error on the following line it means that your handler
0420       // does not meet the documented type requirements for a WriteHandler.
0421       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0422 
0423       non_const_lvalue<WriteHandler> handler2(handler);
0424       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0425       start_write_op(stream_, buffers,
0426           boost::asio::buffer_sequence_begin(buffers),
0427           completion_cond2.value, handler2.value);
0428     }
0429 
0430   private:
0431     AsyncWriteStream& stream_;
0432   };
0433 } // namespace detail
0434 
0435 #if !defined(GENERATING_DOCUMENTATION)
0436 
0437 template <template <typename, typename> class Associator,
0438     typename AsyncWriteStream, typename ConstBufferSequence,
0439     typename ConstBufferIterator, typename CompletionCondition,
0440     typename WriteHandler, typename DefaultCandidate>
0441 struct associator<Associator,
0442     detail::write_op<AsyncWriteStream, ConstBufferSequence,
0443       ConstBufferIterator, CompletionCondition, WriteHandler>,
0444     DefaultCandidate>
0445   : Associator<WriteHandler, DefaultCandidate>
0446 {
0447   static typename Associator<WriteHandler, DefaultCandidate>::type get(
0448       const detail::write_op<AsyncWriteStream, ConstBufferSequence,
0449         ConstBufferIterator, CompletionCondition, WriteHandler>& h) noexcept
0450   {
0451     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
0452   }
0453 
0454   static auto get(
0455       const detail::write_op<AsyncWriteStream, ConstBufferSequence,
0456         ConstBufferIterator, CompletionCondition, WriteHandler>& h,
0457       const DefaultCandidate& c) noexcept
0458     -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
0459   {
0460     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
0461   }
0462 };
0463 
0464 #endif // !defined(GENERATING_DOCUMENTATION)
0465 
0466 template <typename AsyncWriteStream,
0467     typename ConstBufferSequence, typename CompletionCondition,
0468     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0469       std::size_t)) WriteToken>
0470 inline auto async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
0471     CompletionCondition completion_condition, WriteToken&& token,
0472     constraint_t<
0473       is_const_buffer_sequence<ConstBufferSequence>::value
0474     >)
0475   -> decltype(
0476     async_initiate<WriteToken,
0477       void (boost::system::error_code, std::size_t)>(
0478         declval<detail::initiate_async_write<AsyncWriteStream>>(),
0479         token, buffers,
0480         static_cast<CompletionCondition&&>(completion_condition)))
0481 {
0482   return async_initiate<WriteToken,
0483     void (boost::system::error_code, std::size_t)>(
0484       detail::initiate_async_write<AsyncWriteStream>(s),
0485       token, buffers,
0486       static_cast<CompletionCondition&&>(completion_condition));
0487 }
0488 
0489 template <typename AsyncWriteStream, typename ConstBufferSequence,
0490     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0491       std::size_t)) WriteToken>
0492 inline auto async_write(AsyncWriteStream& s,
0493     const ConstBufferSequence& buffers, WriteToken&& token,
0494     constraint_t<
0495       is_const_buffer_sequence<ConstBufferSequence>::value
0496     >)
0497   -> decltype(
0498     async_initiate<WriteToken,
0499       void (boost::system::error_code, std::size_t)>(
0500         declval<detail::initiate_async_write<AsyncWriteStream>>(),
0501         token, buffers, transfer_all()))
0502 {
0503   return async_initiate<WriteToken,
0504     void (boost::system::error_code, std::size_t)>(
0505       detail::initiate_async_write<AsyncWriteStream>(s),
0506       token, buffers, transfer_all());
0507 }
0508 
0509 #if !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0510 
0511 namespace detail
0512 {
0513   template <typename AsyncWriteStream, typename DynamicBuffer_v1,
0514       typename CompletionCondition, typename WriteHandler>
0515   class write_dynbuf_v1_op
0516   {
0517   public:
0518     template <typename BufferSequence>
0519     write_dynbuf_v1_op(AsyncWriteStream& stream,
0520         BufferSequence&& buffers,
0521         CompletionCondition& completion_condition, WriteHandler& handler)
0522       : stream_(stream),
0523         buffers_(static_cast<BufferSequence&&>(buffers)),
0524         completion_condition_(
0525           static_cast<CompletionCondition&&>(completion_condition)),
0526         handler_(static_cast<WriteHandler&&>(handler))
0527     {
0528     }
0529 
0530     write_dynbuf_v1_op(const write_dynbuf_v1_op& other)
0531       : stream_(other.stream_),
0532         buffers_(other.buffers_),
0533         completion_condition_(other.completion_condition_),
0534         handler_(other.handler_)
0535     {
0536     }
0537 
0538     write_dynbuf_v1_op(write_dynbuf_v1_op&& other)
0539       : stream_(other.stream_),
0540         buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)),
0541         completion_condition_(
0542           static_cast<CompletionCondition&&>(
0543             other.completion_condition_)),
0544         handler_(static_cast<WriteHandler&&>(other.handler_))
0545     {
0546     }
0547 
0548     void operator()(const boost::system::error_code& ec,
0549         std::size_t bytes_transferred, int start = 0)
0550     {
0551       switch (start)
0552       {
0553         case 1:
0554         async_write(stream_, buffers_.data(),
0555             static_cast<CompletionCondition&&>(completion_condition_),
0556             static_cast<write_dynbuf_v1_op&&>(*this));
0557         return; default:
0558         buffers_.consume(bytes_transferred);
0559         static_cast<WriteHandler&&>(handler_)(ec,
0560             static_cast<const std::size_t&>(bytes_transferred));
0561       }
0562     }
0563 
0564   //private:
0565     AsyncWriteStream& stream_;
0566     DynamicBuffer_v1 buffers_;
0567     CompletionCondition completion_condition_;
0568     WriteHandler handler_;
0569   };
0570 
0571   template <typename AsyncWriteStream, typename DynamicBuffer_v1,
0572       typename CompletionCondition, typename WriteHandler>
0573   inline bool asio_handler_is_continuation(
0574       write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
0575         CompletionCondition, WriteHandler>* this_handler)
0576   {
0577     return boost_asio_handler_cont_helpers::is_continuation(
0578         this_handler->handler_);
0579   }
0580 
0581   template <typename AsyncWriteStream>
0582   class initiate_async_write_dynbuf_v1
0583   {
0584   public:
0585     typedef typename AsyncWriteStream::executor_type executor_type;
0586 
0587     explicit initiate_async_write_dynbuf_v1(AsyncWriteStream& stream)
0588       : stream_(stream)
0589     {
0590     }
0591 
0592     executor_type get_executor() const noexcept
0593     {
0594       return stream_.get_executor();
0595     }
0596 
0597     template <typename WriteHandler, typename DynamicBuffer_v1,
0598         typename CompletionCondition>
0599     void operator()(WriteHandler&& handler,
0600         DynamicBuffer_v1&& buffers,
0601         CompletionCondition&& completion_cond) const
0602     {
0603       // If you get an error on the following line it means that your handler
0604       // does not meet the documented type requirements for a WriteHandler.
0605       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0606 
0607       non_const_lvalue<WriteHandler> handler2(handler);
0608       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0609       write_dynbuf_v1_op<AsyncWriteStream,
0610         decay_t<DynamicBuffer_v1>,
0611           CompletionCondition, decay_t<WriteHandler>>(
0612             stream_, static_cast<DynamicBuffer_v1&&>(buffers),
0613               completion_cond2.value, handler2.value)(
0614                 boost::system::error_code(), 0, 1);
0615     }
0616 
0617   private:
0618     AsyncWriteStream& stream_;
0619   };
0620 } // namespace detail
0621 
0622 #if !defined(GENERATING_DOCUMENTATION)
0623 
0624 template <template <typename, typename> class Associator,
0625     typename AsyncWriteStream, typename DynamicBuffer_v1,
0626     typename CompletionCondition, typename WriteHandler,
0627     typename DefaultCandidate>
0628 struct associator<Associator,
0629     detail::write_dynbuf_v1_op<AsyncWriteStream,
0630       DynamicBuffer_v1, CompletionCondition, WriteHandler>,
0631     DefaultCandidate>
0632   : Associator<WriteHandler, DefaultCandidate>
0633 {
0634   static typename Associator<WriteHandler, DefaultCandidate>::type get(
0635       const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,
0636         CompletionCondition, WriteHandler>& h) noexcept
0637   {
0638     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
0639   }
0640 
0641   static auto get(
0642       const detail::write_dynbuf_v1_op<AsyncWriteStream,
0643         DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,
0644       const DefaultCandidate& c) noexcept
0645     -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
0646   {
0647     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
0648   }
0649 };
0650 
0651 #endif // !defined(GENERATING_DOCUMENTATION)
0652 
0653 template <typename AsyncWriteStream, typename DynamicBuffer_v1,
0654     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0655       std::size_t)) WriteToken>
0656 inline auto async_write(AsyncWriteStream& s,
0657     DynamicBuffer_v1&& buffers, WriteToken&& token,
0658     constraint_t<
0659       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0660     >,
0661     constraint_t<
0662       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0663     >)
0664   -> decltype(
0665     async_initiate<WriteToken,
0666       void (boost::system::error_code, std::size_t)>(
0667         declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
0668         token, static_cast<DynamicBuffer_v1&&>(buffers),
0669         transfer_all()))
0670 {
0671   return async_initiate<WriteToken,
0672     void (boost::system::error_code, std::size_t)>(
0673       detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
0674       token, static_cast<DynamicBuffer_v1&&>(buffers),
0675       transfer_all());
0676 }
0677 
0678 template <typename AsyncWriteStream,
0679     typename DynamicBuffer_v1, typename CompletionCondition,
0680     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0681       std::size_t)) WriteToken>
0682 inline auto async_write(AsyncWriteStream& s, DynamicBuffer_v1&& buffers,
0683     CompletionCondition completion_condition, WriteToken&& token,
0684     constraint_t<
0685       is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value
0686     >,
0687     constraint_t<
0688       !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value
0689     >)
0690   -> decltype(
0691     async_initiate<WriteToken,
0692       void (boost::system::error_code, std::size_t)>(
0693         declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
0694         token, static_cast<DynamicBuffer_v1&&>(buffers),
0695         static_cast<CompletionCondition&&>(completion_condition)))
0696 {
0697   return async_initiate<WriteToken,
0698     void (boost::system::error_code, std::size_t)>(
0699       detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
0700       token, static_cast<DynamicBuffer_v1&&>(buffers),
0701       static_cast<CompletionCondition&&>(completion_condition));
0702 }
0703 
0704 #if !defined(BOOST_ASIO_NO_EXTENSIONS)
0705 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0706 
0707 template <typename AsyncWriteStream, typename Allocator,
0708     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0709       std::size_t)) WriteToken>
0710 inline auto async_write(AsyncWriteStream& s,
0711     boost::asio::basic_streambuf<Allocator>& b,
0712     WriteToken&& token)
0713   -> decltype(
0714     async_initiate<WriteToken,
0715       void (boost::system::error_code, std::size_t)>(
0716         declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
0717         token, basic_streambuf_ref<Allocator>(b), transfer_all()))
0718 {
0719   return async_initiate<WriteToken,
0720     void (boost::system::error_code, std::size_t)>(
0721       detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
0722       token, basic_streambuf_ref<Allocator>(b), transfer_all());
0723 }
0724 
0725 template <typename AsyncWriteStream,
0726     typename Allocator, typename CompletionCondition,
0727     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0728       std::size_t)) WriteToken>
0729 inline auto async_write(AsyncWriteStream& s,
0730     boost::asio::basic_streambuf<Allocator>& b,
0731     CompletionCondition completion_condition, WriteToken&& token)
0732   -> decltype(
0733     async_initiate<WriteToken,
0734       void (boost::system::error_code, std::size_t)>(
0735         declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(),
0736         token, basic_streambuf_ref<Allocator>(b),
0737         static_cast<CompletionCondition&&>(completion_condition)))
0738 {
0739   return async_initiate<WriteToken,
0740     void (boost::system::error_code, std::size_t)>(
0741       detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),
0742       token, basic_streambuf_ref<Allocator>(b),
0743       static_cast<CompletionCondition&&>(completion_condition));
0744 }
0745 
0746 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0747 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
0748 #endif // !defined(BOOST_ASIO_NO_DYNAMIC_BUFFER_V1)
0749 
0750 namespace detail
0751 {
0752   template <typename AsyncWriteStream, typename DynamicBuffer_v2,
0753       typename CompletionCondition, typename WriteHandler>
0754   class write_dynbuf_v2_op
0755   {
0756   public:
0757     template <typename BufferSequence>
0758     write_dynbuf_v2_op(AsyncWriteStream& stream,
0759         BufferSequence&& buffers,
0760         CompletionCondition& completion_condition, WriteHandler& handler)
0761       : stream_(stream),
0762         buffers_(static_cast<BufferSequence&&>(buffers)),
0763         completion_condition_(
0764           static_cast<CompletionCondition&&>(completion_condition)),
0765         handler_(static_cast<WriteHandler&&>(handler))
0766     {
0767     }
0768 
0769     write_dynbuf_v2_op(const write_dynbuf_v2_op& other)
0770       : stream_(other.stream_),
0771         buffers_(other.buffers_),
0772         completion_condition_(other.completion_condition_),
0773         handler_(other.handler_)
0774     {
0775     }
0776 
0777     write_dynbuf_v2_op(write_dynbuf_v2_op&& other)
0778       : stream_(other.stream_),
0779         buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)),
0780         completion_condition_(
0781           static_cast<CompletionCondition&&>(
0782             other.completion_condition_)),
0783         handler_(static_cast<WriteHandler&&>(other.handler_))
0784     {
0785     }
0786 
0787     void operator()(const boost::system::error_code& ec,
0788         std::size_t bytes_transferred, int start = 0)
0789     {
0790       switch (start)
0791       {
0792         case 1:
0793         async_write(stream_, buffers_.data(0, buffers_.size()),
0794             static_cast<CompletionCondition&&>(completion_condition_),
0795             static_cast<write_dynbuf_v2_op&&>(*this));
0796         return; default:
0797         buffers_.consume(bytes_transferred);
0798         static_cast<WriteHandler&&>(handler_)(ec,
0799             static_cast<const std::size_t&>(bytes_transferred));
0800       }
0801     }
0802 
0803   //private:
0804     AsyncWriteStream& stream_;
0805     DynamicBuffer_v2 buffers_;
0806     CompletionCondition completion_condition_;
0807     WriteHandler handler_;
0808   };
0809 
0810   template <typename AsyncWriteStream, typename DynamicBuffer_v2,
0811       typename CompletionCondition, typename WriteHandler>
0812   inline bool asio_handler_is_continuation(
0813       write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
0814         CompletionCondition, WriteHandler>* this_handler)
0815   {
0816     return boost_asio_handler_cont_helpers::is_continuation(
0817         this_handler->handler_);
0818   }
0819 
0820   template <typename AsyncWriteStream>
0821   class initiate_async_write_dynbuf_v2
0822   {
0823   public:
0824     typedef typename AsyncWriteStream::executor_type executor_type;
0825 
0826     explicit initiate_async_write_dynbuf_v2(AsyncWriteStream& stream)
0827       : stream_(stream)
0828     {
0829     }
0830 
0831     executor_type get_executor() const noexcept
0832     {
0833       return stream_.get_executor();
0834     }
0835 
0836     template <typename WriteHandler, typename DynamicBuffer_v2,
0837         typename CompletionCondition>
0838     void operator()(WriteHandler&& handler,
0839         DynamicBuffer_v2&& buffers,
0840         CompletionCondition&& completion_cond) const
0841     {
0842       // If you get an error on the following line it means that your handler
0843       // does not meet the documented type requirements for a WriteHandler.
0844       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
0845 
0846       non_const_lvalue<WriteHandler> handler2(handler);
0847       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);
0848       write_dynbuf_v2_op<AsyncWriteStream, decay_t<DynamicBuffer_v2>,
0849         CompletionCondition, decay_t<WriteHandler>>(
0850           stream_, static_cast<DynamicBuffer_v2&&>(buffers),
0851             completion_cond2.value, handler2.value)(
0852               boost::system::error_code(), 0, 1);
0853     }
0854 
0855   private:
0856     AsyncWriteStream& stream_;
0857   };
0858 } // namespace detail
0859 
0860 #if !defined(GENERATING_DOCUMENTATION)
0861 
0862 template <template <typename, typename> class Associator,
0863     typename AsyncWriteStream, typename DynamicBuffer_v2,
0864     typename CompletionCondition, typename WriteHandler,
0865     typename DefaultCandidate>
0866 struct associator<Associator,
0867     detail::write_dynbuf_v2_op<AsyncWriteStream,
0868       DynamicBuffer_v2, CompletionCondition, WriteHandler>,
0869     DefaultCandidate>
0870   : Associator<WriteHandler, DefaultCandidate>
0871 {
0872   static typename Associator<WriteHandler, DefaultCandidate>::type get(
0873       const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,
0874         CompletionCondition, WriteHandler>& h) noexcept
0875   {
0876     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);
0877   }
0878 
0879   static auto get(
0880       const detail::write_dynbuf_v2_op<AsyncWriteStream,
0881         DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,
0882       const DefaultCandidate& c) noexcept
0883     -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))
0884   {
0885     return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);
0886   }
0887 };
0888 
0889 #endif // !defined(GENERATING_DOCUMENTATION)
0890 
0891 template <typename AsyncWriteStream, typename DynamicBuffer_v2,
0892     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0893       std::size_t)) WriteToken>
0894 inline auto async_write(AsyncWriteStream& s,
0895     DynamicBuffer_v2 buffers, WriteToken&& token,
0896     constraint_t<
0897       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0898     >)
0899   -> decltype(
0900     async_initiate<WriteToken,
0901       void (boost::system::error_code, std::size_t)>(
0902         declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(),
0903         token, static_cast<DynamicBuffer_v2&&>(buffers),
0904         transfer_all()))
0905 {
0906   return async_initiate<WriteToken,
0907     void (boost::system::error_code, std::size_t)>(
0908       detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),
0909       token, static_cast<DynamicBuffer_v2&&>(buffers),
0910       transfer_all());
0911 }
0912 
0913 template <typename AsyncWriteStream,
0914     typename DynamicBuffer_v2, typename CompletionCondition,
0915     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0916       std::size_t)) WriteToken>
0917 inline auto async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,
0918     CompletionCondition completion_condition, WriteToken&& token,
0919     constraint_t<
0920       is_dynamic_buffer_v2<DynamicBuffer_v2>::value
0921     >)
0922   -> decltype(
0923     async_initiate<WriteToken,
0924       void (boost::system::error_code, std::size_t)>(
0925         declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(),
0926         token, static_cast<DynamicBuffer_v2&&>(buffers),
0927         static_cast<CompletionCondition&&>(completion_condition)))
0928 {
0929   return async_initiate<WriteToken,
0930     void (boost::system::error_code, std::size_t)>(
0931       detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),
0932       token, static_cast<DynamicBuffer_v2&&>(buffers),
0933       static_cast<CompletionCondition&&>(completion_condition));
0934 }
0935 
0936 } // namespace asio
0937 } // namespace boost
0938 
0939 #include <boost/asio/detail/pop_options.hpp>
0940 
0941 #endif // BOOST_ASIO_IMPL_WRITE_HPP