$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r60741 - in branches/release: . boost boost/algorithm/string boost/archive boost/asio/detail boost/asio/ip boost/bimap boost/config boost/detail boost/filesystem boost/functional/hash boost/fusion boost/graph boost/integer boost/interprocess boost/intrusive boost/iostreams boost/math boost/numeric/ublas boost/program_options boost/property_tree boost/python boost/regex boost/serialization boost/signals boost/signals2 boost/spirit boost/spirit/home boost/spirit/home/karma boost/spirit/home/support boost/statechart boost/system boost/thread boost/tr1 boost/type_traits boost/unordered boost/utility boost/uuid boost/variant boost/wave doc libs libs/array/doc libs/asio/doc libs/asio/test libs/asio/test/ip libs/bimap libs/config libs/filesystem libs/functional/hash libs/fusion libs/graph_parallel libs/integer libs/interprocess libs/intrusive libs/iostreams libs/math libs/mpl/doc/refmanual libs/mpl/doc/src/refmanual libs/numeric/ublas libs/numeric/ublas/doc libs/program_options libs/property_tree libs/python libs/regex libs/regex/doc libs/serialization libs/signals libs/signals2 libs/spirit libs/spirit/classic/example libs/spirit/doc libs/spirit/example libs/spirit/phoenix libs/spirit/test libs/spirit/test/qi libs/statechart libs/static_assert libs/system libs/thread libs/thread/doc libs/timer libs/tr1 libs/type_traits libs/unordered libs/utility libs/uuid libs/wave more people status tools tools/bcp tools/boostbook tools/build/v2 tools/inspect tools/quickbook tools/regression tools/release tools/wave wiki
From: chris_at_[hidden]
Date: 2010-03-21 05:39:28
Author: chris_kohlhoff
Date: 2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
New Revision: 60741
URL: http://svn.boost.org/trac/boost/changeset/60741
Log:
Merge from trunk.
........
  r60681 | chris_kohlhoff | 2010-03-18 12:32:34 +1100 (Thu, 18 Mar 2010) | 3 lines
  
  Define NOMINMAX for all Windows compilers, not just Cygwin. Users can define
  BOOST_ASIO_NO_NOMINMAX to suppress this definition. Fixes #3901.
........
  r60687 | chris_kohlhoff | 2010-03-18 17:23:38 +1100 (Thu, 18 Mar 2010) | 4 lines
  
  Use a bitmask type for the resolver flags, as per the TR2 proposal. This will
  prevent implicit conversion from int to flags, allowing the compiler to catch
  cases where users incorrectly pass a numeric port number as the service name.
........
  r60689 | chris_kohlhoff | 2010-03-18 22:08:19 +1100 (Thu, 18 Mar 2010) | 2 lines
  
  Fix bug where 0-byte reads were incorrectly passing an eof error_code to the handler. Fixes #4023.
........
  r60705 | chris_kohlhoff | 2010-03-20 00:08:04 +1100 (Sat, 20 Mar 2010) | 3 lines
  
  Fix epoll_reactor bug where cancelled operations would complete with a
  "success" error_code.
........
  r60717 | chris_kohlhoff | 2010-03-20 10:23:28 +1100 (Sat, 20 Mar 2010) | 2 lines
  
  More extensive read and write tests.
........
  r60722 | chris_kohlhoff | 2010-03-20 10:57:50 +1100 (Sat, 20 Mar 2010) | 2 lines
  
  WinCE doesn't provide InitializeCriticalSectionAndSpinCount.
........
  r60723 | chris_kohlhoff | 2010-03-20 10:58:48 +1100 (Sat, 20 Mar 2010) | 2 lines
  
  Fix cancellation.
........
  r60725 | chris_kohlhoff | 2010-03-20 10:59:48 +1100 (Sat, 20 Mar 2010) | 3 lines
  
  Use cancel() to avoid Windows behaviour where a connection is reset if the
  socket is closed while there is a pending read operation.
........
Properties modified: 
   branches/release/   (props changed)
   branches/release/CMakeLists.txt   (props changed)
   branches/release/INSTALL   (props changed)
   branches/release/Jamroot   (props changed)
   branches/release/LICENSE_1_0.txt   (props changed)
   branches/release/boost/   (props changed)
   branches/release/boost-build.jam   (props changed)
   branches/release/boost.css   (props changed)
   branches/release/boost.png   (props changed)
   branches/release/boost/algorithm/string/   (props changed)
   branches/release/boost/archive/   (props changed)
   branches/release/boost/array.hpp   (props changed)
   branches/release/boost/bimap/   (props changed)
   branches/release/boost/config/   (props changed)
   branches/release/boost/detail/   (props changed)
   branches/release/boost/filesystem/   (props changed)
   branches/release/boost/functional/hash/   (props changed)
   branches/release/boost/fusion/   (props changed)
   branches/release/boost/graph/   (props changed)
   branches/release/boost/integer/   (props changed)
   branches/release/boost/interprocess/   (props changed)
   branches/release/boost/intrusive/   (props changed)
   branches/release/boost/iostreams/   (props changed)
   branches/release/boost/math/   (props changed)
   branches/release/boost/numeric/ublas/   (props changed)
   branches/release/boost/program_options/   (props changed)
   branches/release/boost/property_tree/   (props changed)
   branches/release/boost/python/   (props changed)
   branches/release/boost/regex/   (props changed)
   branches/release/boost/serialization/   (props changed)
   branches/release/boost/signals/   (props changed)
   branches/release/boost/signals2/   (props changed)
   branches/release/boost/spirit/   (props changed)
   branches/release/boost/spirit/home/   (props changed)
   branches/release/boost/spirit/home/karma/   (props changed)
   branches/release/boost/spirit/home/support/attributes.hpp   (props changed)
   branches/release/boost/statechart/   (props changed)
   branches/release/boost/system/   (props changed)
   branches/release/boost/thread/   (props changed)
   branches/release/boost/thread.hpp   (props changed)
   branches/release/boost/tr1/   (props changed)
   branches/release/boost/type_traits/   (props changed)
   branches/release/boost/unordered/   (props changed)
   branches/release/boost/utility/   (props changed)
   branches/release/boost/utility/value_init.hpp   (props changed)
   branches/release/boost/uuid/   (props changed)
   branches/release/boost/variant/   (props changed)
   branches/release/boost/version.hpp   (props changed)
   branches/release/boost/wave/   (props changed)
   branches/release/bootstrap.bat   (props changed)
   branches/release/bootstrap.sh   (props changed)
   branches/release/doc/   (props changed)
   branches/release/index.htm   (props changed)
   branches/release/index.html   (props changed)
   branches/release/libs/   (props changed)
   branches/release/libs/array/doc/array.xml   (props changed)
   branches/release/libs/bimap/   (props changed)
   branches/release/libs/config/   (props changed)
   branches/release/libs/filesystem/   (props changed)
   branches/release/libs/functional/hash/   (props changed)
   branches/release/libs/fusion/   (props changed)
   branches/release/libs/graph_parallel/   (props changed)
   branches/release/libs/integer/   (props changed)
   branches/release/libs/interprocess/   (props changed)
   branches/release/libs/intrusive/   (props changed)
   branches/release/libs/iostreams/   (props changed)
   branches/release/libs/libraries.htm   (props changed)
   branches/release/libs/maintainers.txt   (props changed)
   branches/release/libs/math/   (props changed)
   branches/release/libs/mpl/doc/refmanual/broken-compiler-workarounds.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/categorized-index-concepts.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/cfg-no-preprocessed-headers.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/composition-and-argument-binding.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/data-types-concepts.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/data-types-miscellaneous.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/extensible-associative-sequence.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/inserter-class.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/tag-dispatched-metafunction.html   (props changed)
   branches/release/libs/mpl/doc/refmanual/trivial-metafunctions-summary.html   (props changed)
   branches/release/libs/mpl/doc/src/refmanual/Iterators-Iterator.rst   (props changed)
   branches/release/libs/numeric/ublas/   (props changed)
   branches/release/libs/numeric/ublas/doc/   (props changed)
   branches/release/libs/program_options/   (props changed)
   branches/release/libs/property_tree/   (props changed)
   branches/release/libs/python/   (props changed)
   branches/release/libs/regex/   (props changed)
   branches/release/libs/regex/doc/   (props changed)
   branches/release/libs/serialization/   (props changed)
   branches/release/libs/signals/   (props changed)
   branches/release/libs/signals2/   (props changed)
   branches/release/libs/spirit/   (props changed)
   branches/release/libs/spirit/classic/example/   (props changed)
   branches/release/libs/spirit/doc/   (props changed)
   branches/release/libs/spirit/example/   (props changed)
   branches/release/libs/spirit/phoenix/   (props changed)
   branches/release/libs/spirit/test/   (props changed)
   branches/release/libs/spirit/test/qi/optional.cpp   (props changed)
   branches/release/libs/statechart/   (props changed)
   branches/release/libs/static_assert/   (props changed)
   branches/release/libs/system/   (props changed)
   branches/release/libs/thread/   (props changed)
   branches/release/libs/thread/doc/   (props changed)
   branches/release/libs/timer/   (props changed)
   branches/release/libs/tr1/   (props changed)
   branches/release/libs/type_traits/   (props changed)
   branches/release/libs/unordered/   (props changed)
   branches/release/libs/utility/   (props changed)
   branches/release/libs/utility/swap.html   (props changed)
   branches/release/libs/utility/value_init.htm   (props changed)
   branches/release/libs/utility/value_init_test.cpp   (props changed)
   branches/release/libs/uuid/   (props changed)
   branches/release/libs/wave/   (props changed)
   branches/release/more/   (props changed)
   branches/release/people/   (props changed)
   branches/release/rst.css   (props changed)
   branches/release/status/   (props changed)
   branches/release/status/Jamfile.v2   (props changed)
   branches/release/tools/   (props changed)
   branches/release/tools/bcp/   (props changed)
   branches/release/tools/boostbook/   (props changed)
   branches/release/tools/build/v2/   (props changed)
   branches/release/tools/inspect/   (props changed)
   branches/release/tools/quickbook/   (props changed)
   branches/release/tools/regression/   (props changed)
   branches/release/tools/release/   (props changed)
   branches/release/tools/wave/   (props changed)
   branches/release/wiki/   (props changed)
Text files modified: 
   branches/release/boost/asio/detail/epoll_reactor.hpp           |    18                                         
   branches/release/boost/asio/detail/socket_types.hpp            |     8                                         
   branches/release/boost/asio/detail/win_iocp_socket_service.hpp |    18                                         
   branches/release/boost/asio/detail/win_mutex.hpp               |     8                                         
   branches/release/boost/asio/ip/basic_resolver_query.hpp        |    17                                         
   branches/release/boost/asio/ip/resolver_query_base.hpp         |    89 +                                       
   branches/release/libs/asio/doc/using.qbk                       |     9                                         
   branches/release/libs/asio/test/ip/tcp.cpp                     |   175 ++++                                    
   branches/release/libs/asio/test/read.cpp                       |  1748 +++++++++++++++++++++++++++++++++++---- 
   branches/release/libs/asio/test/write.cpp                      |  1242 +++++++++++++++++++++++++++             
   10 files changed, 3079 insertions(+), 253 deletions(-)
Modified: branches/release/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- branches/release/boost/asio/detail/epoll_reactor.hpp	(original)
+++ branches/release/boost/asio/detail/epoll_reactor.hpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -212,7 +212,14 @@
 
     op_queue<operation> ops;
     for (int i = 0; i < max_ops; ++i)
-      ops.push(descriptor_data->op_queue_[i]);
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = boost::asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
 
     descriptor_lock.unlock();
 
@@ -233,7 +240,14 @@
 
     op_queue<operation> ops;
     for (int i = 0; i < max_ops; ++i)
-      ops.push(descriptor_data->op_queue_[i]);
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = boost::asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
 
     descriptor_lock.unlock();
 
Modified: branches/release/boost/asio/detail/socket_types.hpp
==============================================================================
--- branches/release/boost/asio/detail/socket_types.hpp	(original)
+++ branches/release/boost/asio/detail/socket_types.hpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -68,13 +68,15 @@
 #   define WIN32_LEAN_AND_MEAN
 #  endif // !defined(WIN32_LEAN_AND_MEAN)
 # endif // !defined(BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN)
+# if !defined(BOOST_ASIO_NO_NOMINMAX)
+#  if !defined(NOMINMAX)
+#   define NOMINMAX 1
+#  endif // !defined(NOMINMAX)
+# endif // !defined(BOOST_ASIO_NO_NOMINMAX)
 # if defined(__CYGWIN__)
 #  if !defined(__USE_W32_SOCKETS)
 #   error You must add -D__USE_W32_SOCKETS to your compiler options.
 #  endif // !defined(__USE_W32_SOCKETS)
-#  if !defined(NOMINMAX)
-#   define NOMINMAX 1
-#  endif // !defined(NOMINMAX)
 # endif // defined(__CYGWIN__)
 # include <winsock2.h>
 # include <ws2tcpip.h>
Modified: branches/release/boost/asio/detail/win_iocp_socket_service.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_iocp_socket_service.hpp	(original)
+++ branches/release/boost/asio/detail/win_iocp_socket_service.hpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -1059,6 +1059,8 @@
         // Check for connection closed.
         else if (!ec && bytes_transferred == 0
             && o->protocol_type_ == SOCK_STREAM
+            && !buffer_sequence_adapter<boost::asio::mutable_buffer,
+                MutableBufferSequence>::all_empty(o->buffers_)
             && !boost::is_same<MutableBufferSequence, null_buffers>::value)
         {
           ec = boost::asio::error::eof;
@@ -1691,7 +1693,7 @@
       std::size_t buffer_count, socket_base::message_flags flags,
       bool noop, operation* op)
   {
-    update_cancellation_thread_id();
+    update_cancellation_thread_id(impl);
     iocp_service_.work_started();
 
     if (noop)
@@ -1718,7 +1720,7 @@
       std::size_t buffer_count, const endpoint_type& destination,
       socket_base::message_flags flags, operation* op)
   {
-    update_cancellation_thread_id();
+    update_cancellation_thread_id(impl);
     iocp_service_.work_started();
 
     if (!is_open(impl))
@@ -1744,7 +1746,7 @@
       std::size_t buffer_count, socket_base::message_flags flags,
       bool noop, operation* op)
   {
-    update_cancellation_thread_id();
+    update_cancellation_thread_id(impl);
     iocp_service_.work_started();
 
     if (noop)
@@ -1774,7 +1776,7 @@
       std::size_t buffer_count, endpoint_type& sender_endpoint,
       socket_base::message_flags flags, int* endpoint_size, operation* op)
   {
-    update_cancellation_thread_id();
+    update_cancellation_thread_id(impl);
     iocp_service_.work_started();
 
     if (!is_open(impl))
@@ -1801,7 +1803,7 @@
       bool peer_is_open, socket_holder& new_socket,
       void* output_buffer, DWORD address_length, operation* op)
   {
-    update_cancellation_thread_id();
+    update_cancellation_thread_id(impl);
     iocp_service_.work_started();
 
     if (!is_open(impl))
@@ -1833,7 +1835,7 @@
   void start_reactor_op(implementation_type& impl, int op_type, reactor_op* op)
   {
     reactor& r = get_reactor();
-    update_cancellation_thread_id();
+    update_cancellation_thread_id(impl);
 
     if (is_open(impl))
     {
@@ -1851,7 +1853,7 @@
       reactor_op* op, const endpoint_type& peer_endpoint)
   {
     reactor& r = get_reactor();
-    update_cancellation_thread_id();
+    update_cancellation_thread_id(impl);
 
     if (is_open(impl))
     {
@@ -1925,7 +1927,7 @@
   }
 
   // Update the ID of the thread from which cancellation is safe.
-  void update_cancellation_thread_id()
+  void update_cancellation_thread_id(implementation_type& impl)
   {
 #if defined(BOOST_ASIO_ENABLE_CANCELIO)
     if (impl.safe_cancellation_thread_id_ == 0)
Modified: branches/release/boost/asio/detail/win_mutex.hpp
==============================================================================
--- branches/release/boost/asio/detail/win_mutex.hpp	(original)
+++ branches/release/boost/asio/detail/win_mutex.hpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -84,12 +84,20 @@
 #if defined(__MINGW32__)
     // Not sure if MinGW supports structured exception handling, so for now
     // we'll just call the Windows API and hope.
+# if defined(UNDER_CE)
+    ::InitializeCriticalSection(&crit_section_);
+# else
     ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000);
+# endif
     return 0;
 #else
     __try
     {
+# if defined(UNDER_CE)
+      ::InitializeCriticalSection(&crit_section_);
+# else
       ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000);
+# endif
     }
     __except(GetExceptionCode() == STATUS_NO_MEMORY
         ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
Modified: branches/release/boost/asio/ip/basic_resolver_query.hpp
==============================================================================
--- branches/release/boost/asio/ip/basic_resolver_query.hpp	(original)
+++ branches/release/boost/asio/ip/basic_resolver_query.hpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -48,13 +48,13 @@
 
   /// Construct with specified service name for any protocol.
   basic_resolver_query(const std::string& service_name,
-      int flags = passive | address_configured)
+      resolver_query_base::flags resolve_flags = passive | address_configured)
     : hints_(),
       host_name_(),
       service_name_(service_name)
   {
     typename InternetProtocol::endpoint endpoint;
-    hints_.ai_flags = flags;
+    hints_.ai_flags = static_cast<int>(resolve_flags);
     hints_.ai_family = PF_UNSPEC;
     hints_.ai_socktype = endpoint.protocol().type();
     hints_.ai_protocol = endpoint.protocol().protocol();
@@ -67,12 +67,12 @@
   /// Construct with specified service name for a given protocol.
   basic_resolver_query(const protocol_type& protocol,
       const std::string& service_name,
-      int flags = passive | address_configured)
+      resolver_query_base::flags resolve_flags = passive | address_configured)
     : hints_(),
       host_name_(),
       service_name_(service_name)
   {
-    hints_.ai_flags = flags;
+    hints_.ai_flags = static_cast<int>(resolve_flags);
     hints_.ai_family = protocol.family();
     hints_.ai_socktype = protocol.type();
     hints_.ai_protocol = protocol.protocol();
@@ -84,13 +84,14 @@
 
   /// Construct with specified host name and service name for any protocol.
   basic_resolver_query(const std::string& host_name,
-      const std::string& service_name, int flags = address_configured)
+      const std::string& service_name,
+      resolver_query_base::flags resolve_flags = address_configured)
     : hints_(),
       host_name_(host_name),
       service_name_(service_name)
   {
     typename InternetProtocol::endpoint endpoint;
-    hints_.ai_flags = flags;
+    hints_.ai_flags = static_cast<int>(resolve_flags);
     hints_.ai_family = PF_UNSPEC;
     hints_.ai_socktype = endpoint.protocol().type();
     hints_.ai_protocol = endpoint.protocol().protocol();
@@ -103,12 +104,12 @@
   /// Construct with specified host name and service name for a given protocol.
   basic_resolver_query(const protocol_type& protocol,
       const std::string& host_name, const std::string& service_name,
-      int flags = address_configured)
+      resolver_query_base::flags resolve_flags = address_configured)
     : hints_(),
       host_name_(host_name),
       service_name_(service_name)
   {
-    hints_.ai_flags = flags;
+    hints_.ai_flags = static_cast<int>(resolve_flags);
     hints_.ai_family = protocol.family();
     hints_.ai_socktype = protocol.type();
     hints_.ai_protocol = protocol.protocol();
Modified: branches/release/boost/asio/ip/resolver_query_base.hpp
==============================================================================
--- branches/release/boost/asio/ip/resolver_query_base.hpp	(original)
+++ branches/release/boost/asio/ip/resolver_query_base.hpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -35,58 +35,107 @@
 {
 public:
 #if defined(GENERATING_DOCUMENTATION)
+  /// A bitmask type (C++ Std [lib.bitmask.types]).
+  typedef unspecified flags;
+
   /// Determine the canonical name of the host specified in the query.
-  static const int canonical_name = implementation_defined;
+  static const flags canonical_name = implementation_defined;
 
   /// Indicate that returned endpoint is intended for use as a locally bound
   /// socket endpoint.
-  static const int passive = implementation_defined;
+  static const flags passive = implementation_defined;
 
   /// Host name should be treated as a numeric string defining an IPv4 or IPv6
   /// address and no name resolution should be attempted.
-  static const int numeric_host = implementation_defined;
+  static const flags numeric_host = implementation_defined;
 
   /// Service name should be treated as a numeric string defining a port number
   /// and no name resolution should be attempted.
-  static const int numeric_service = implementation_defined;
+  static const flags numeric_service = implementation_defined;
 
   /// If the query protocol family is specified as IPv6, return IPv4-mapped
   /// IPv6 addresses on finding no IPv6 addresses.
-  static const int v4_mapped = implementation_defined;
+  static const flags v4_mapped = implementation_defined;
 
   /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses.
-  static const int all_matching = implementation_defined;
+  static const flags xll_matching = implementation_defined;
 
   /// Only return IPv4 addresses if a non-loopback IPv4 address is configured
   /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address
   /// is configured for the system.
-  static const int address_configured = implementation_defined;
+  static const flags xddress_configured = implementation_defined;
 #else
-  BOOST_STATIC_CONSTANT(int, canonical_name = AI_CANONNAME);
-  BOOST_STATIC_CONSTANT(int, passive = AI_PASSIVE);
-  BOOST_STATIC_CONSTANT(int, numeric_host = AI_NUMERICHOST);
+  enum flags
+  {
+    canonical_name = AI_CANONNAME,
+    passive = AI_PASSIVE,
+    numeric_host = AI_NUMERICHOST,
 # if defined(AI_NUMERICSERV)
-  BOOST_STATIC_CONSTANT(int, numeric_service = AI_NUMERICSERV);
+    numeric_service = AI_NUMERICSERV,
 # else
-  BOOST_STATIC_CONSTANT(int, numeric_service = 0);
+    numeric_service = 0,
 # endif
-  // Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but
-  // does not implement them. Therefore they are specifically excluded here.
+    // Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but
+    // does not implement them. Therefore they are specifically excluded here.
 # if defined(AI_V4MAPPED) && !defined(__QNXNTO__)
-  BOOST_STATIC_CONSTANT(int, v4_mapped = AI_V4MAPPED);
+    v4_mapped = AI_V4MAPPED,
 # else
-  BOOST_STATIC_CONSTANT(int, v4_mapped = 0);
+    v4_mapped = 0,
 # endif
 # if defined(AI_ALL) && !defined(__QNXNTO__)
-  BOOST_STATIC_CONSTANT(int, all_matching = AI_ALL);
+    all_matching = AI_ALL,
 # else
-  BOOST_STATIC_CONSTANT(int, all_matching = 0);
+    all_matching = 0,
 # endif
 # if defined(AI_ADDRCONFIG) && !defined(__QNXNTO__)
-  BOOST_STATIC_CONSTANT(int, address_configured = AI_ADDRCONFIG);
+    address_configured = AI_ADDRCONFIG
 # else
-  BOOST_STATIC_CONSTANT(int, address_configured = 0);
+    address_configured = 0
 # endif
+  };
+
+  // Implement bitmask operations as shown in C++ Std [lib.bitmask.types].
+
+  friend flags operator&(flags x, flags y)
+  {
+    return static_cast<flags>(
+        static_cast<unsigned int>(x) & static_cast<unsigned int>(y));
+  }
+
+  friend flags operator|(flags x, flags y)
+  {
+    return static_cast<flags>(
+        static_cast<unsigned int>(x) | static_cast<unsigned int>(y));
+  }
+
+  friend flags operator^(flags x, flags y)
+  {
+    return static_cast<flags>(
+        static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y));
+  }
+
+  friend flags operator~(flags x)
+  {
+    return static_cast<flags>(static_cast<unsigned int>(~x));
+  }
+
+  friend flags& operator&=(flags& x, flags y)
+  {
+    x = x & y;
+    return x;
+  }
+
+  friend flags& operator|=(flags& x, flags y)
+  {
+    x = x | y;
+    return x;
+  }
+
+  friend flags& operator^=(flags& x, flags y)
+  {
+    x = x ^ y;
+    return x;
+  }
 #endif
 
 protected:
Modified: branches/release/libs/asio/doc/using.qbk
==============================================================================
--- branches/release/libs/asio/doc/using.qbk	(original)
+++ branches/release/libs/asio/doc/using.qbk	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -206,6 +206,15 @@
     ]
   ]
   [
+    [`BOOST_ASIO_NO_NOMINMAX`]
+    [
+      By default, Boost.Asio will automatically define `NOMINMAX` when
+      compiling for Windows, to suppress the definition of the `min()` and
+      `max()` macros. The presence of `BOOST_ASIO_NO_NOMINMAX` prevents
+      `NOMINMAX` from being defined.
+    ]
+  ]
+  [
     [`BOOST_ASIO_NO_DEFAULT_LINKED_LIBS`]
     [
       When compiling for Windows using Microsoft Visual C++ or Borland C++, Boost.Asio
Modified: branches/release/libs/asio/test/ip/tcp.cpp
==============================================================================
--- branches/release/libs/asio/test/ip/tcp.cpp	(original)
+++ branches/release/libs/asio/test/ip/tcp.cpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -13,12 +13,18 @@
 #define BOOST_ALL_NO_LIB 1
 #endif // !defined(BOOST_ALL_NO_LIB)
 
+// Enable cancel() support on Windows.
+#define BOOST_ASIO_ENABLE_CANCELIO 1
+
 // Test that header file is self-contained.
 #include <boost/asio/ip/tcp.hpp>
 
 #include <boost/bind.hpp>
 #include <cstring>
 #include <boost/asio/io_service.hpp>
+#include <boost/asio/placeholders.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/write.hpp>
 #include "../unit_test.hpp"
 #include "../archetypes/io_control_command.hpp"
 
@@ -300,6 +306,174 @@
 
 //------------------------------------------------------------------------------
 
+// ip_tcp_socket_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the ip::tcp::socket class.
+
+namespace ip_tcp_socket_runtime {
+
+static const char write_data[]
+  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void handle_read_noop(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!err);
+  BOOST_CHECK(bytes_transferred == 0);
+}
+
+void handle_write_noop(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!err);
+  BOOST_CHECK(bytes_transferred == 0);
+}
+
+void handle_read(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!err);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+}
+
+void handle_write(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!err);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+}
+
+void handle_read_cancel(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(err == boost::asio::error::operation_aborted);
+  BOOST_CHECK(bytes_transferred == 0);
+}
+
+void handle_read_eof(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(err == boost::asio::error::eof);
+  BOOST_CHECK(bytes_transferred == 0);
+}
+
+void test()
+{
+  using namespace std; // For memcmp.
+  using namespace boost::asio;
+  namespace ip = boost::asio::ip;
+
+  io_service ios;
+
+  ip::tcp::acceptor acceptor(ios, ip::tcp::endpoint(ip::tcp::v4(), 0));
+  ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+  server_endpoint.address(ip::address_v4::loopback());
+
+  ip::tcp::socket client_side_socket(ios);
+  ip::tcp::socket server_side_socket(ios);
+
+  client_side_socket.connect(server_endpoint);
+  acceptor.accept(server_side_socket);
+
+  // No-op read.
+
+  bool read_noop_completed = false;
+  client_side_socket.async_read_some(
+      boost::asio::mutable_buffers_1(0, 0),
+      boost::bind(handle_read_noop,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &read_noop_completed));
+
+  ios.run();
+  BOOST_CHECK(read_noop_completed);
+
+  // No-op write.
+
+  bool write_noop_completed = false;
+  client_side_socket.async_write_some(
+      boost::asio::const_buffers_1(0, 0),
+      boost::bind(handle_write_noop,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &write_noop_completed));
+
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(write_noop_completed);
+
+  // Read and write to transfer data.
+
+  char read_buffer[sizeof(write_data)];
+  bool read_completed = false;
+  boost::asio::async_read(client_side_socket,
+      boost::asio::buffer(read_buffer),
+      boost::bind(handle_read,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &read_completed));
+
+  bool write_completed = false;
+  boost::asio::async_write(server_side_socket,
+      boost::asio::buffer(write_data),
+      boost::bind(handle_write,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &write_completed));
+
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(read_completed);
+  BOOST_CHECK(write_completed);
+  BOOST_CHECK(memcmp(read_buffer, write_data, sizeof(write_data)) == 0);
+
+  // Cancelled read.
+
+  bool read_cancel_completed = false;
+  boost::asio::async_read(server_side_socket,
+      boost::asio::buffer(read_buffer),
+      boost::bind(handle_read_cancel,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &read_cancel_completed));
+
+  ios.reset();
+  ios.poll();
+  BOOST_CHECK(!read_cancel_completed);
+
+  server_side_socket.cancel();
+
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(read_cancel_completed);
+
+  // A read when the peer closes socket should fail with eof.
+
+  bool read_eof_completed = false;
+  boost::asio::async_read(client_side_socket,
+      boost::asio::buffer(read_buffer),
+      boost::bind(handle_read_eof,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &read_eof_completed));
+
+  server_side_socket.close();
+
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(read_eof_completed);
+}
+
+} // namespace ip_tcp_socket_runtime
+
+//------------------------------------------------------------------------------
+
 // ip_tcp_acceptor_runtime test
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // The following test checks the runtime operation of the ip::tcp::acceptor
@@ -383,6 +557,7 @@
   test->add(BOOST_TEST_CASE(&ip_tcp_compile::test));
   test->add(BOOST_TEST_CASE(&ip_tcp_runtime::test));
   test->add(BOOST_TEST_CASE(&ip_tcp_socket_compile::test));
+  test->add(BOOST_TEST_CASE(&ip_tcp_socket_runtime::test));
   test->add(BOOST_TEST_CASE(&ip_tcp_acceptor_runtime::test));
   return test;
 }
Modified: branches/release/libs/asio/test/read.cpp
==============================================================================
--- branches/release/libs/asio/test/read.cpp	(original)
+++ branches/release/libs/asio/test/read.cpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -21,6 +21,7 @@
 #include <cstring>
 #include <boost/asio/io_service.hpp>
 #include <boost/asio/placeholders.hpp>
+#include <boost/asio/streambuf.hpp>
 #include "unit_test.hpp"
 
 using namespace std; // For memcmp, memcpy and memset.
@@ -134,7 +135,7 @@
 static const char read_data[]
   = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
-void test_2_arg_read()
+void test_2_arg_mutable_buffers_1_read()
 {
   boost::asio::io_service ios;
   test_stream s(ios);
@@ -163,6 +164,66 @@
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
 }
 
+void test_2_arg_multi_buffers_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  char read_buf[sizeof(read_data)];
+  boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+    boost::asio::buffer(read_buf, 32),
+    boost::asio::buffer(read_buf) + 32 } };
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  size_t bytes_transferred = boost::asio::read(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  bytes_transferred = boost::asio::read(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  bytes_transferred = boost::asio::read(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+}
+
+void test_2_arg_streambuf_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::streambuf sb(sizeof(read_data));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  size_t bytes_transferred = boost::asio::read(s, sb);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+}
+
 bool old_style_transfer_all(const boost::system::error_code& ec,
     size_t /*bytes_transferred*/)
 {
@@ -175,7 +236,7 @@
   return !!ec ? 0 : 3;
 }
 
-void test_3_arg_read()
+void test_3_arg_mutable_buffers_1_read()
 {
   boost::asio::io_service ios;
   test_stream s(ios);
@@ -316,336 +377,1366 @@
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
 }
 
-void test_4_arg_read()
+void test_3_arg_multi_buffers_read()
 {
   boost::asio::io_service ios;
   test_stream s(ios);
   char read_buf[sizeof(read_data)];
-  boost::asio::mutable_buffers_1 buffers
-    = boost::asio::buffer(read_buf, sizeof(read_buf));
+  boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+    boost::asio::buffer(read_buf, 32),
+    boost::asio::buffer(read_buf) + 32 } };
 
   s.reset(read_data, sizeof(read_data));
   memset(read_buf, 0, sizeof(read_buf));
-  boost::system::error_code error;
   size_t bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_all(), error);
+      boost::asio::transfer_all());
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_all(), error);
+      boost::asio::transfer_all());
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_all(), error);
+      boost::asio::transfer_all());
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(1), error);
+      boost::asio::transfer_at_least(1));
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(1), error);
+      boost::asio::transfer_at_least(1));
   BOOST_CHECK(bytes_transferred == 1);
   BOOST_CHECK(s.check(buffers, 1));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(1), error);
+      boost::asio::transfer_at_least(1));
   BOOST_CHECK(bytes_transferred == 10);
   BOOST_CHECK(s.check(buffers, 10));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(10), error);
+      boost::asio::transfer_at_least(10));
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(10), error);
+      boost::asio::transfer_at_least(10));
   BOOST_CHECK(bytes_transferred == 10);
   BOOST_CHECK(s.check(buffers, 10));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(10), error);
+      boost::asio::transfer_at_least(10));
   BOOST_CHECK(bytes_transferred == 10);
   BOOST_CHECK(s.check(buffers, 10));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(42), error);
+      boost::asio::transfer_at_least(42));
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(42), error);
+      boost::asio::transfer_at_least(42));
   BOOST_CHECK(bytes_transferred == 42);
   BOOST_CHECK(s.check(buffers, 42));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
   bytes_transferred = boost::asio::read(s, buffers,
-      boost::asio::transfer_at_least(42), error);
+      boost::asio::transfer_at_least(42));
   BOOST_CHECK(bytes_transferred == 50);
   BOOST_CHECK(s.check(buffers, 50));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   memset(read_buf, 0, sizeof(read_buf));
-  bytes_transferred = boost::asio::read(s, buffers,
-      old_style_transfer_all, error);
+  bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
-  bytes_transferred = boost::asio::read(s, buffers,
-      old_style_transfer_all, error);
+  bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
-  bytes_transferred = boost::asio::read(s, buffers,
-      old_style_transfer_all, error);
+  bytes_transferred = boost::asio::read(s, buffers, old_style_transfer_all);
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   memset(read_buf, 0, sizeof(read_buf));
-  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer);
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
-  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer);
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
   memset(read_buf, 0, sizeof(read_buf));
-  error = boost::system::error_code();
-  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer);
   BOOST_CHECK(bytes_transferred == sizeof(read_data));
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-  BOOST_CHECK(!error);
-}
-
-void async_read_handler(const boost::system::error_code& e,
-    size_t bytes_transferred, size_t expected_bytes_transferred, bool* called)
-{
-  *called = true;
-  BOOST_CHECK(!e);
-  BOOST_CHECK(bytes_transferred == expected_bytes_transferred);
 }
 
-void test_3_arg_async_read()
+void test_3_arg_streambuf_read()
 {
   boost::asio::io_service ios;
   test_stream s(ios);
-  char read_buf[sizeof(read_data)];
-  boost::asio::mutable_buffers_1 buffers
-    = boost::asio::buffer(read_buf, sizeof(read_buf));
+  boost::asio::streambuf sb(sizeof(read_data));
 
   s.reset(read_data, sizeof(read_data));
-  memset(read_buf, 0, sizeof(read_buf));
-  bool called = false;
-  boost::asio::async_read(s, buffers,
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        sizeof(read_data), &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  sb.consume(sb.size());
+  size_t bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
-  memset(read_buf, 0, sizeof(read_buf));
-  called = false;
-  boost::asio::async_read(s, buffers,
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        sizeof(read_data), &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
-  memset(read_buf, 0, sizeof(read_buf));
-  called = false;
-  boost::asio::async_read(s, buffers,
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        sizeof(read_data), &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
-}
-
-void test_4_arg_async_read()
-{
-  boost::asio::io_service ios;
-  test_stream s(ios);
-  char read_buf[sizeof(read_data)];
-  boost::asio::mutable_buffers_1 buffers
-    = boost::asio::buffer(read_buf, sizeof(read_buf));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
 
   s.reset(read_data, sizeof(read_data));
-  memset(read_buf, 0, sizeof(read_buf));
-  bool called = false;
-  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        sizeof(read_data), &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
-  memset(read_buf, 0, sizeof(read_buf));
-  called = false;
-  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        sizeof(read_data), &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == 1);
+  BOOST_CHECK(sb.size() == 1);
+  BOOST_CHECK(s.check(sb.data(), 1));
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
-  memset(read_buf, 0, sizeof(read_buf));
-  called = false;
-  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        sizeof(read_data), &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
 
   s.reset(read_data, sizeof(read_data));
-  memset(read_buf, 0, sizeof(read_buf));
-  called = false;
-  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        sizeof(read_data), &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(1);
-  memset(read_buf, 0, sizeof(read_buf));
-  called = false;
-  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        1, &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, 1));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
 
   s.reset(read_data, sizeof(read_data));
   s.next_read_length(10);
-  memset(read_buf, 0, sizeof(read_buf));
-  called = false;
-  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
-      boost::bind(async_read_handler,
-        boost::asio::placeholders::error,
-        boost::asio::placeholders::bytes_transferred,
-        10, &called));
-  ios.reset();
-  ios.run();
-  BOOST_CHECK(called);
-  BOOST_CHECK(s.check(buffers, 10));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
 
   s.reset(read_data, sizeof(read_data));
-  memset(read_buf, 0, sizeof(read_buf));
-  called = false;
-  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == 42);
+  BOOST_CHECK(sb.size() == 42);
+  BOOST_CHECK(s.check(sb.data(), 42));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == 50);
+  BOOST_CHECK(sb.size() == 50);
+  BOOST_CHECK(s.check(sb.data(), 50));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+}
+
+void test_4_arg_mutable_buffers_1_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  char read_buf[sizeof(read_data)];
+  boost::asio::mutable_buffers_1 buffers
+    = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  boost::system::error_code error;
+  size_t bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 1);
+  BOOST_CHECK(s.check(buffers, 1));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 42);
+  BOOST_CHECK(s.check(buffers, 42));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 50);
+  BOOST_CHECK(s.check(buffers, 50));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  bytes_transferred = boost::asio::read(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+}
+
+void test_4_arg_multi_buffers_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  char read_buf[sizeof(read_data)];
+  boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+    boost::asio::buffer(read_buf, 32),
+    boost::asio::buffer(read_buf) + 32 } };
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  boost::system::error_code error;
+  size_t bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 1);
+  BOOST_CHECK(s.check(buffers, 1));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 42);
+  BOOST_CHECK(s.check(buffers, 42));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 50);
+  BOOST_CHECK(s.check(buffers, 50));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  bytes_transferred = boost::asio::read(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+  BOOST_CHECK(!error);
+}
+
+void test_4_arg_streambuf_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::streambuf sb(sizeof(read_data));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  boost::system::error_code error;
+  size_t bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 1);
+  BOOST_CHECK(sb.size() == 1);
+  BOOST_CHECK(s.check(sb.data(), 1));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 42);
+  BOOST_CHECK(sb.size() == 42);
+  BOOST_CHECK(s.check(sb.data(), 42));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 50);
+  BOOST_CHECK(sb.size() == 50);
+  BOOST_CHECK(s.check(sb.data(), 50));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  bytes_transferred = boost::asio::read(s, sb, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::read(s, sb, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(read_data));
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+  BOOST_CHECK(!error);
+}
+
+void async_read_handler(const boost::system::error_code& e,
+    size_t bytes_transferred, size_t expected_bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!e);
+  BOOST_CHECK(bytes_transferred == expected_bytes_transferred);
+}
+
+void test_3_arg_mutable_buffers_1_async_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  char read_buf[sizeof(read_data)];
+  boost::asio::mutable_buffers_1 buffers
+    = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  bool called = false;
+  boost::asio::async_read(s, buffers,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+}
+
+void test_3_arg_multi_buffers_async_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  char read_buf[sizeof(read_data)];
+  boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+    boost::asio::buffer(read_buf, 32),
+    boost::asio::buffer(read_buf) + 32 } };
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  bool called = false;
+  boost::asio::async_read(s, buffers,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+}
+
+void test_3_arg_streambuf_async_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::streambuf sb(sizeof(read_data));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  bool called = false;
+  boost::asio::async_read(s, sb,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+}
+
+void test_4_arg_mutable_buffers_1_async_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  char read_buf[sizeof(read_data)];
+  boost::asio::mutable_buffers_1 buffers
+    = boost::asio::buffer(read_buf, sizeof(read_buf));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  bool called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        1, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 1));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        42, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 42));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        50, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 50));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, old_style_transfer_all,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, old_style_transfer_all,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, old_style_transfer_all,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, short_transfer,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, short_transfer,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, short_transfer,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+}
+
+void test_4_arg_multi_buffers_async_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  char read_buf[sizeof(read_data)];
+  boost::array<boost::asio::mutable_buffer, 2> buffers = { {
+    boost::asio::buffer(read_buf, 32),
+    boost::asio::buffer(read_buf) + 32 } };
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  bool called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        1, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 1));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset(read_data, sizeof(read_data));
+  memset(read_buf, 0, sizeof(read_buf));
+  called = false;
+  boost::asio::async_read(s, buffers, boost::asio::transfer_at_least(10),
       boost::bind(async_read_handler,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred,
@@ -807,13 +1898,294 @@
   BOOST_CHECK(s.check(buffers, sizeof(read_data)));
 }
 
+void test_4_arg_streambuf_async_read()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::streambuf sb(sizeof(read_data));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  bool called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_all(),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        1, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == 1);
+  BOOST_CHECK(s.check(sb.data(), 1));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(1),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(10),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == 10);
+  BOOST_CHECK(s.check(sb.data(), 10));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        42, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == 42);
+  BOOST_CHECK(s.check(sb.data(), 42));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, boost::asio::transfer_at_least(42),
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        50, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == 50);
+  BOOST_CHECK(s.check(sb.data(), 50));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, old_style_transfer_all,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, old_style_transfer_all,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, old_style_transfer_all,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, short_transfer,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(1);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, short_transfer,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+
+  s.reset(read_data, sizeof(read_data));
+  s.next_read_length(10);
+  sb.consume(sb.size());
+  called = false;
+  boost::asio::async_read(s, sb, short_transfer,
+      boost::bind(async_read_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(read_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(sb.size() == sizeof(read_data));
+  BOOST_CHECK(s.check(sb.data(), sizeof(read_data)));
+}
+
 test_suite* init_unit_test_suite(int, char*[])
 {
   test_suite* test = BOOST_TEST_SUITE("read");
-  test->add(BOOST_TEST_CASE(&test_2_arg_read));
-  test->add(BOOST_TEST_CASE(&test_3_arg_read));
-  test->add(BOOST_TEST_CASE(&test_4_arg_read));
-  test->add(BOOST_TEST_CASE(&test_3_arg_async_read));
-  test->add(BOOST_TEST_CASE(&test_4_arg_async_read));
+  test->add(BOOST_TEST_CASE(&test_2_arg_mutable_buffers_1_read));
+  test->add(BOOST_TEST_CASE(&test_2_arg_multi_buffers_read));
+  test->add(BOOST_TEST_CASE(&test_2_arg_streambuf_read));
+  test->add(BOOST_TEST_CASE(&test_3_arg_mutable_buffers_1_read));
+  test->add(BOOST_TEST_CASE(&test_3_arg_multi_buffers_read));
+  test->add(BOOST_TEST_CASE(&test_3_arg_streambuf_read));
+  test->add(BOOST_TEST_CASE(&test_4_arg_mutable_buffers_1_read));
+  test->add(BOOST_TEST_CASE(&test_4_arg_multi_buffers_read));
+  test->add(BOOST_TEST_CASE(&test_4_arg_streambuf_read));
+  test->add(BOOST_TEST_CASE(&test_3_arg_mutable_buffers_1_async_read));
+  test->add(BOOST_TEST_CASE(&test_3_arg_multi_buffers_async_read));
+  test->add(BOOST_TEST_CASE(&test_3_arg_streambuf_async_read));
+  test->add(BOOST_TEST_CASE(&test_4_arg_mutable_buffers_1_async_read));
+  test->add(BOOST_TEST_CASE(&test_4_arg_multi_buffers_async_read));
+  test->add(BOOST_TEST_CASE(&test_4_arg_streambuf_async_read));
   return test;
 }
Modified: branches/release/libs/asio/test/write.cpp
==============================================================================
--- branches/release/libs/asio/test/write.cpp	(original)
+++ branches/release/libs/asio/test/write.cpp	2010-03-21 05:39:26 EDT (Sun, 21 Mar 2010)
@@ -16,6 +16,7 @@
 // Test that header file is self-contained.
 #include <boost/asio/write.hpp>
 
+#include <boost/array.hpp>
 #include <boost/bind.hpp>
 #include <boost/noncopyable.hpp>
 #include <cstring>
@@ -134,8 +135,10 @@
 
 static const char write_data[]
   = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static char mutable_write_data[]
+  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
-void test_2_arg_write()
+void test_2_arg_const_buffers_1_write()
 {
   boost::asio::io_service ios;
   test_stream s(ios);
@@ -160,6 +163,57 @@
   BOOST_CHECK(s.check(buffers, sizeof(write_data)));
 }
 
+void test_2_arg_mutable_buffers_1_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::mutable_buffers_1 buffers
+    = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+  s.reset();
+  size_t bytes_transferred = boost::asio::write(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+}
+
+void test_2_arg_multi_buffers_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::array<boost::asio::const_buffer, 2> buffers = { {
+    boost::asio::buffer(write_data, 32),
+    boost::asio::buffer(write_data) + 32 } };
+
+  s.reset();
+  size_t bytes_transferred = boost::asio::write(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+}
+
 bool old_style_transfer_all(const boost::system::error_code& ec,
     size_t /*bytes_transferred*/)
 {
@@ -172,7 +226,7 @@
   return !!ec ? 0 : 3;
 }
 
-void test_3_arg_write()
+void test_3_arg_const_buffers_1_write()
 {
   boost::asio::io_service ios;
   test_stream s(ios);
@@ -294,7 +348,252 @@
   BOOST_CHECK(s.check(buffers, sizeof(write_data)));
 }
 
-void test_4_arg_write()
+void test_3_arg_mutable_buffers_1_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::mutable_buffers_1 buffers
+    = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+  s.reset();
+  size_t bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == 1);
+  BOOST_CHECK(s.check(buffers, 1));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == 42);
+  BOOST_CHECK(s.check(buffers, 42));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == 50);
+  BOOST_CHECK(s.check(buffers, 50));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+}
+
+void test_3_arg_multi_buffers_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::array<boost::asio::const_buffer, 2> buffers = { {
+    boost::asio::buffer(write_data, 32),
+    boost::asio::buffer(write_data) + 32 } };
+
+  s.reset();
+  size_t bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all());
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == 1);
+  BOOST_CHECK(s.check(buffers, 1));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10));
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == 42);
+  BOOST_CHECK(s.check(buffers, 42));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42));
+  BOOST_CHECK(bytes_transferred == 50);
+  BOOST_CHECK(s.check(buffers, 50));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers, old_style_transfer_all);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+}
+
+void test_4_arg_const_buffers_1_write()
 {
   boost::asio::io_service ios;
   test_stream s(ios);
@@ -453,24 +752,672 @@
   BOOST_CHECK(!error);
 }
 
-void async_write_handler(const boost::system::error_code& e,
-    size_t bytes_transferred, size_t expected_bytes_transferred, bool* called)
+void test_4_arg_mutable_buffers_1_write()
 {
-  *called = true;
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::mutable_buffers_1 buffers
+    = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+  s.reset();
+  boost::system::error_code error;
+  size_t bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 1);
+  BOOST_CHECK(s.check(buffers, 1));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 42);
+  BOOST_CHECK(s.check(buffers, 42));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 50);
+  BOOST_CHECK(s.check(buffers, 50));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(mutable_write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+  BOOST_CHECK(!error);
+}
+
+void test_4_arg_multi_buffers_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::array<boost::asio::const_buffer, 2> buffers = { {
+    boost::asio::buffer(write_data, 32),
+    boost::asio::buffer(write_data) + 32 } };
+
+  s.reset();
+  boost::system::error_code error;
+  size_t bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_all(), error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 1);
+  BOOST_CHECK(s.check(buffers, 1));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(1), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(10), error);
+  BOOST_CHECK(bytes_transferred == 10);
+  BOOST_CHECK(s.check(buffers, 10));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 42);
+  BOOST_CHECK(s.check(buffers, 42));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      boost::asio::transfer_at_least(42), error);
+  BOOST_CHECK(bytes_transferred == 50);
+  BOOST_CHECK(s.check(buffers, 50));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers,
+      old_style_transfer_all, error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(1);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+
+  s.reset();
+  s.next_write_length(10);
+  error = boost::system::error_code();
+  bytes_transferred = boost::asio::write(s, buffers, short_transfer, error);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+  BOOST_CHECK(!error);
+}
+
+void async_write_handler(const boost::system::error_code& e,
+    size_t bytes_transferred, size_t expected_bytes_transferred, bool* called)
+{
+  *called = true;
   BOOST_CHECK(!e);
   BOOST_CHECK(bytes_transferred == expected_bytes_transferred);
 }
 
-void test_3_arg_async_write()
-{
-  boost::asio::io_service ios;
-  test_stream s(ios);
-  boost::asio::const_buffers_1 buffers
-    = boost::asio::buffer(write_data, sizeof(write_data));
+void test_3_arg_const_buffers_1_async_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::const_buffers_1 buffers
+    = boost::asio::buffer(write_data, sizeof(write_data));
+
+  s.reset();
+  bool called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+}
+
+void test_3_arg_mutable_buffers_1_async_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::mutable_buffers_1 buffers
+    = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+  s.reset();
+  bool called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+}
+
+void test_3_arg_multi_buffers_async_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::array<boost::asio::const_buffer, 2> buffers = { {
+    boost::asio::buffer(write_data, 32),
+    boost::asio::buffer(write_data) + 32 } };
+
+  s.reset();
+  bool called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+}
+
+void test_4_arg_const_buffers_1_async_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::asio::const_buffers_1 buffers
+    = boost::asio::buffer(write_data, sizeof(write_data));
+
+  s.reset();
+  bool called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        1, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 1));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        42, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 42));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        50, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 50));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, old_style_transfer_all,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, old_style_transfer_all,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
 
   s.reset();
-  bool called = false;
-  boost::asio::async_write(s, buffers,
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, old_style_transfer_all,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(write_data)));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, short_transfer,
       boost::bind(async_write_handler,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred,
@@ -483,7 +1430,7 @@
   s.reset();
   s.next_write_length(1);
   called = false;
-  boost::asio::async_write(s, buffers,
+  boost::asio::async_write(s, buffers, short_transfer,
       boost::bind(async_write_handler,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred,
@@ -496,7 +1443,7 @@
   s.reset();
   s.next_write_length(10);
   called = false;
-  boost::asio::async_write(s, buffers,
+  boost::asio::async_write(s, buffers, short_transfer,
       boost::bind(async_write_handler,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred,
@@ -507,12 +1454,249 @@
   BOOST_CHECK(s.check(buffers, sizeof(write_data)));
 }
 
-void test_4_arg_async_write()
+void test_4_arg_mutable_buffers_1_async_write()
 {
   boost::asio::io_service ios;
   test_stream s(ios);
-  boost::asio::const_buffers_1 buffers
-    = boost::asio::buffer(write_data, sizeof(write_data));
+  boost::asio::mutable_buffers_1 buffers
+    = boost::asio::buffer(mutable_write_data, sizeof(mutable_write_data));
+
+  s.reset();
+  bool called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_all(),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        1, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 1));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(1),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(10),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        10, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 10));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        42, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 42));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, boost::asio::transfer_at_least(42),
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        50, &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, 50));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, old_style_transfer_all,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, old_style_transfer_all,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, old_style_transfer_all,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  called = false;
+  boost::asio::async_write(s, buffers, short_transfer,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(1);
+  called = false;
+  boost::asio::async_write(s, buffers, short_transfer,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+
+  s.reset();
+  s.next_write_length(10);
+  called = false;
+  boost::asio::async_write(s, buffers, short_transfer,
+      boost::bind(async_write_handler,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        sizeof(mutable_write_data), &called));
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(called);
+  BOOST_CHECK(s.check(buffers, sizeof(mutable_write_data)));
+}
+
+void test_4_arg_multi_buffers_async_write()
+{
+  boost::asio::io_service ios;
+  test_stream s(ios);
+  boost::array<boost::asio::const_buffer, 2> buffers = { {
+    boost::asio::buffer(write_data, 32),
+    boost::asio::buffer(write_data) + 32 } };
 
   s.reset();
   bool called = false;
@@ -746,10 +1930,20 @@
 test_suite* init_unit_test_suite(int, char*[])
 {
   test_suite* test = BOOST_TEST_SUITE("write");
-  test->add(BOOST_TEST_CASE(&test_2_arg_write));
-  test->add(BOOST_TEST_CASE(&test_3_arg_write));
-  test->add(BOOST_TEST_CASE(&test_4_arg_write));
-  test->add(BOOST_TEST_CASE(&test_3_arg_async_write));
-  test->add(BOOST_TEST_CASE(&test_4_arg_async_write));
+  test->add(BOOST_TEST_CASE(&test_2_arg_const_buffers_1_write));
+  test->add(BOOST_TEST_CASE(&test_2_arg_mutable_buffers_1_write));
+  test->add(BOOST_TEST_CASE(&test_2_arg_multi_buffers_write));
+  test->add(BOOST_TEST_CASE(&test_3_arg_const_buffers_1_write));
+  test->add(BOOST_TEST_CASE(&test_3_arg_mutable_buffers_1_write));
+  test->add(BOOST_TEST_CASE(&test_3_arg_multi_buffers_write));
+  test->add(BOOST_TEST_CASE(&test_4_arg_const_buffers_1_write));
+  test->add(BOOST_TEST_CASE(&test_4_arg_mutable_buffers_1_write));
+  test->add(BOOST_TEST_CASE(&test_4_arg_multi_buffers_write));
+  test->add(BOOST_TEST_CASE(&test_3_arg_const_buffers_1_async_write));
+  test->add(BOOST_TEST_CASE(&test_3_arg_mutable_buffers_1_async_write));
+  test->add(BOOST_TEST_CASE(&test_3_arg_multi_buffers_async_write));
+  test->add(BOOST_TEST_CASE(&test_4_arg_const_buffers_1_async_write));
+  test->add(BOOST_TEST_CASE(&test_4_arg_mutable_buffers_1_async_write));
+  test->add(BOOST_TEST_CASE(&test_4_arg_multi_buffers_async_write));
   return test;
 }