10ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
20ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// impl/write.hpp
30ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// ~~~~~~~~~~~~~~
40ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
50ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
60ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
70ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Distributed under the Boost Software License, Version 1.0. (See accompanying
80ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
90ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#ifndef ASIO_IMPL_WRITE_HPP
120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#define ASIO_IMPL_WRITE_HPP
130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/buffer.hpp"
160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/completion_condition.hpp"
170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/array_fwd.hpp"
180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/base_from_completion_cond.hpp"
190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/bind_handler.hpp"
200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/consuming_buffers.hpp"
210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/dependent_type.hpp"
220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_alloc_helpers.hpp"
230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_cont_helpers.hpp"
240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_invoke_helpers.hpp"
250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_type_requirements.hpp"
260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/throw_error.hpp"
270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/push_options.hpp"
290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace asio {
310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename SyncWriteStream, typename ConstBufferSequence,
330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typename CompletionCondition>
340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiestd::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    CompletionCondition completion_condition, asio::error_code& ec)
360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ec = asio::error_code();
380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::detail::consuming_buffers<
390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    const_buffer, ConstBufferSequence> tmp(buffers);
400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  std::size_t total_transferred = 0;
410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  tmp.prepare(detail::adapt_completion_condition_result(
420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        completion_condition(ec, total_transferred)));
430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  while (tmp.begin() != tmp.end())
440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t bytes_transferred = s.write_some(tmp, ec);
460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    tmp.consume(bytes_transferred);
470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    total_transferred += bytes_transferred;
480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    tmp.prepare(detail::adapt_completion_condition_result(
490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          completion_condition(ec, total_transferred)));
500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return total_transferred;
520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename SyncWriteStream, typename ConstBufferSequence>
550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code ec;
580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::detail::throw_error(ec, "write");
600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return bytes_transferred;
610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename SyncWriteStream, typename ConstBufferSequence>
640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::error_code& ec)
660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return write(s, buffers, transfer_all(), ec);
680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename SyncWriteStream, typename ConstBufferSequence,
710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typename CompletionCondition>
720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    CompletionCondition completion_condition)
740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::error_code ec;
760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  asio::detail::throw_error(ec, "write");
780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return bytes_transferred;
790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace detail
830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncWriteStream, typename ConstBufferSequence,
850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename WriteHandler>
860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class write_op
870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition, WriteHandler& handler)
920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(buffers),
960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(const write_op& other)
1030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
1040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
1050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
1060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
1070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
1080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
1090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(write_op&& other)
1130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
1140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
1150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
1160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
1170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
1180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
1190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
1230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
1240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
1260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
1270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
1280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_.prepare(this->check_for_completion(ec, total_transferred_));
1290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
1300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
1310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_write_some(buffers_,
1320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              ASIO_MOVE_CAST(write_op)(*this));
1330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
1340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
1350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          buffers_.consume(bytes_transferred);
1360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          buffers_.prepare(this->check_for_completion(ec, total_transferred_));
1370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
1380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || buffers_.begin() == buffers_.end())
1390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
1400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
1410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
1430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
1440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
1470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncWriteStream& stream_;
1480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::detail::consuming_buffers<
1490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const_buffer, ConstBufferSequence> buffers_;
1500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
1510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
1520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    WriteHandler handler_;
1530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
1540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncWriteStream,
1560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename WriteHandler>
1570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class write_op<AsyncWriteStream, asio::mutable_buffers_1,
1580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      CompletionCondition, WriteHandler>
1590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
1600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
1620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(AsyncWriteStream& stream,
1630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        const asio::mutable_buffers_1& buffers,
1640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition,
1650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        WriteHandler& handler)
1660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
1670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
1680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
1690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(buffers),
1700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
1710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
1720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
1730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(const write_op& other)
1770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
1780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
1790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(other.buffer_),
1800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
1810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
1820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
1830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(write_op&& other)
1870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
1880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
1890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(other.buffer_),
1900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
1910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
1920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
1930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
1970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
1980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t n = 0;
2000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
2010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
2020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
2030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        n = this->check_for_completion(ec, total_transferred_);
2040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
2050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
2060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_write_some(
2070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              asio::buffer(buffer_ + total_transferred_, n),
2080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              ASIO_MOVE_CAST(write_op)(*this));
2090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
2100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
2110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
2120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || (n = this->check_for_completion(ec, total_transferred_)) == 0
2130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || total_transferred_ == asio::buffer_size(buffer_))
2140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
2150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
2160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
2180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
2190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
2220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncWriteStream& stream_;
2230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::mutable_buffer buffer_;
2240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
2250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
2260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    WriteHandler handler_;
2270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
2280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncWriteStream,
2300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename WriteHandler>
2310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class write_op<AsyncWriteStream, asio::const_buffers_1,
2320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      CompletionCondition, WriteHandler>
2330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
2340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
2350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
2360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(AsyncWriteStream& stream,
2370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        const asio::const_buffers_1& buffers,
2380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition,
2390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        WriteHandler& handler)
2400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
2410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
2420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
2430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(buffers),
2440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
2450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
2460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
2470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(const write_op& other)
2510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
2520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
2530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(other.buffer_),
2540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
2550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
2560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
2570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(write_op&& other)
2610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
2620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
2630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffer_(other.buffer_),
2640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
2650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
2660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
2670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
2710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
2720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
2730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t n = 0;
2740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
2750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
2760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
2770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        n = this->check_for_completion(ec, total_transferred_);
2780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
2790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
2800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_write_some(
2810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              asio::buffer(buffer_ + total_transferred_, n),
2820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              ASIO_MOVE_CAST(write_op)(*this));
2830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
2840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
2850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
2860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || (n = this->check_for_completion(ec, total_transferred_)) == 0
2870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || total_transferred_ == asio::buffer_size(buffer_))
2880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
2890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
2900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
2920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
2930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
2940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
2960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncWriteStream& stream_;
2970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio::const_buffer buffer_;
2980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
2990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
3000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    WriteHandler handler_;
3010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
3020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncWriteStream, typename Elem,
3040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename WriteHandler>
3050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class write_op<AsyncWriteStream, boost::array<Elem, 2>,
3060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      CompletionCondition, WriteHandler>
3070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
3080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
3100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(AsyncWriteStream& stream, const boost::array<Elem, 2>& buffers,
3110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition, WriteHandler& handler)
3120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
3130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
3140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
3150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(buffers),
3160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
3170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
3180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
3190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
3200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(const write_op& other)
3230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
3240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
3250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
3260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
3270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
3280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
3290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
3300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(write_op&& other)
3330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
3340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
3350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
3360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
3370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
3380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
3390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
3400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
3430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
3440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
3450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename asio::detail::dependent_type<Elem,
3460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          boost::array<asio::const_buffer, 2> >::type bufs = {{
3470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::const_buffer(buffers_[0]),
3480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::const_buffer(buffers_[1]) }};
3490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t buffer_size0 = asio::buffer_size(bufs[0]);
3500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t buffer_size1 = asio::buffer_size(bufs[1]);
3510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t n = 0;
3520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
3530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
3540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
3550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        n = this->check_for_completion(ec, total_transferred_);
3560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
3570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
3580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          bufs[0] = asio::buffer(bufs[0] + total_transferred_, n);
3590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          bufs[1] = asio::buffer(
3600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              bufs[1] + (total_transferred_ < buffer_size0
3610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie                ? 0 : total_transferred_ - buffer_size0),
3620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              n - asio::buffer_size(bufs[0]));
3630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_write_some(bufs, ASIO_MOVE_CAST(write_op)(*this));
3640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
3650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
3660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
3670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || (n = this->check_for_completion(ec, total_transferred_)) == 0
3680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || total_transferred_ == buffer_size0 + buffer_size1)
3690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
3700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
3710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
3730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
3740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
3750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
3770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncWriteStream& stream_;
3780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    boost::array<Elem, 2> buffers_;
3790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
3800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
3810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    WriteHandler handler_;
3820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
3830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
3850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncWriteStream, typename Elem,
3860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename WriteHandler>
3870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  class write_op<AsyncWriteStream, std::array<Elem, 2>,
3880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      CompletionCondition, WriteHandler>
3890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : detail::base_from_completion_cond<CompletionCondition>
3900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
3910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public:
3920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(AsyncWriteStream& stream, const std::array<Elem, 2>& buffers,
3930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition completion_condition, WriteHandler& handler)
3940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<
3950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          CompletionCondition>(completion_condition),
3960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(stream),
3970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(buffers),
3980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(0),
3990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(0),
4000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
4010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
4020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
4030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(const write_op& other)
4050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
4060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
4070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
4080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
4090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
4100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(other.handler_)
4110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
4120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
4130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_op(write_op&& other)
4150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : detail::base_from_completion_cond<CompletionCondition>(other),
4160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        stream_(other.stream_),
4170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        buffers_(other.buffers_),
4180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        start_(other.start_),
4190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        total_transferred_(other.total_transferred_),
4200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
4210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
4220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
4230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void operator()(const asio::error_code& ec,
4250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::size_t bytes_transferred, int start = 0)
4260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
4270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename asio::detail::dependent_type<Elem,
4280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          std::array<asio::const_buffer, 2> >::type bufs = {{
4290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::const_buffer(buffers_[0]),
4300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::const_buffer(buffers_[1]) }};
4310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t buffer_size0 = asio::buffer_size(bufs[0]);
4320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t buffer_size1 = asio::buffer_size(bufs[1]);
4330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t n = 0;
4340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      switch (start_ = start)
4350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      {
4360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        case 1:
4370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        n = this->check_for_completion(ec, total_transferred_);
4380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        for (;;)
4390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        {
4400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          bufs[0] = asio::buffer(bufs[0] + total_transferred_, n);
4410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          bufs[1] = asio::buffer(
4420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              bufs[1] + (total_transferred_ < buffer_size0
4430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie                ? 0 : total_transferred_ - buffer_size0),
4440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              n - asio::buffer_size(bufs[0]));
4450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          stream_.async_write_some(bufs, ASIO_MOVE_CAST(write_op)(*this));
4460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          return; default:
4470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          total_transferred_ += bytes_transferred;
4480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          if ((!ec && bytes_transferred == 0)
4490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || (n = this->check_for_completion(ec, total_transferred_)) == 0
4500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie              || total_transferred_ == buffer_size0 + buffer_size1)
4510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie            break;
4520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        }
4530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
4550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      }
4560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
4570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  //private:
4590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    AsyncWriteStream& stream_;
4600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::array<Elem, 2> buffers_;
4610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    int start_;
4620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t total_transferred_;
4630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    WriteHandler handler_;
4640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  };
4650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncWriteStream, typename ConstBufferSequence,
4680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename WriteHandler>
4690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline void* asio_handler_allocate(std::size_t size,
4700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      write_op<AsyncWriteStream, ConstBufferSequence,
4710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, WriteHandler>* this_handler)
4720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return asio_handler_alloc_helpers::allocate(
4740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        size, this_handler->handler_);
4750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncWriteStream, typename ConstBufferSequence,
4780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename WriteHandler>
4790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline void asio_handler_deallocate(void* pointer, std::size_t size,
4800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      write_op<AsyncWriteStream, ConstBufferSequence,
4810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, WriteHandler>* this_handler)
4820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio_handler_alloc_helpers::deallocate(
4840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        pointer, size, this_handler->handler_);
4850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename AsyncWriteStream, typename ConstBufferSequence,
4880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename CompletionCondition, typename WriteHandler>
4890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline bool asio_handler_is_continuation(
4900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      write_op<AsyncWriteStream, ConstBufferSequence,
4910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, WriteHandler>* this_handler)
4920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
4930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return this_handler->start_ == 0 ? true
4940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      : asio_handler_cont_helpers::is_continuation(
4950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          this_handler->handler_);
4960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
4970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
4980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename Function, typename AsyncWriteStream,
4990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename ConstBufferSequence, typename CompletionCondition,
5000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename WriteHandler>
5010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline void asio_handler_invoke(Function& function,
5020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      write_op<AsyncWriteStream, ConstBufferSequence,
5030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, WriteHandler>* this_handler)
5040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
5050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio_handler_invoke_helpers::invoke(
5060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        function, this_handler->handler_);
5070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
5080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  template <typename Function, typename AsyncWriteStream,
5100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename ConstBufferSequence, typename CompletionCondition,
5110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename WriteHandler>
5120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  inline void asio_handler_invoke(const Function& function,
5130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      write_op<AsyncWriteStream, ConstBufferSequence,
5140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        CompletionCondition, WriteHandler>* this_handler)
5150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
5160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    asio_handler_invoke_helpers::invoke(
5170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        function, this_handler->handler_);
5180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
5190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace detail
5200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename AsyncWriteStream, typename ConstBufferSequence,
5220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typename CompletionCondition, typename WriteHandler>
5230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline ASIO_INITFN_RESULT_TYPE(WriteHandler,
5240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void (asio::error_code, std::size_t))
5250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieasync_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
5260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    CompletionCondition completion_condition,
5270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ASIO_MOVE_ARG(WriteHandler) handler)
5280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
5290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // If you get an error on the following line it means that your handler does
5300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // not meet the documented type requirements for a WriteHandler.
5310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
5320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  detail::async_result_init<
5340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    WriteHandler, void (asio::error_code, std::size_t)> init(
5350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_MOVE_CAST(WriteHandler)(handler));
5360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  detail::write_op<AsyncWriteStream, ConstBufferSequence,
5380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    CompletionCondition, ASIO_HANDLER_TYPE(
5390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      WriteHandler, void (asio::error_code, std::size_t))>(
5400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        s, buffers, completion_condition, init.handler)(
5410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          asio::error_code(), 0, 1);
5420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return init.result.get();
5440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
5450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename AsyncWriteStream, typename ConstBufferSequence,
5470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typename WriteHandler>
5480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieinline ASIO_INITFN_RESULT_TYPE(WriteHandler,
5490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void (asio::error_code, std::size_t))
5500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieasync_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
5510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ASIO_MOVE_ARG(WriteHandler) handler)
5520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
5530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // If you get an error on the following line it means that your handler does
5540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  // not meet the documented type requirements for a WriteHandler.
5550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
5560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  detail::async_result_init<
5580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    WriteHandler, void (asio::error_code, std::size_t)> init(
5590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_MOVE_CAST(WriteHandler)(handler));
5600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  detail::write_op<AsyncWriteStream, ConstBufferSequence,
5620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    detail::transfer_all_t, ASIO_HANDLER_TYPE(
5630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      WriteHandler, void (asio::error_code, std::size_t))>(
5640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        s, buffers, transfer_all(), init.handler)(
5650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          asio::error_code(), 0, 1);
5660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return init.result.get();
5680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
5690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace asio
5720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/pop_options.hpp"
5740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
5750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // ASIO_IMPL_WRITE_HPP
576