Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84314 - in trunk: boost boost/asio boost/asio/detail boost/asio/detail/impl boost/asio/impl boost/asio/ssl/detail libs/asio/test
From: chris_at_[hidden]
Date: 2013-05-16 23:07:55


Author: chris_kohlhoff
Date: 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
New Revision: 84314
URL: http://svn.boost.org/trac/boost/changeset/84314

Log:
Add a new handler hook called asio_handler_is_continuation.

Asynchronous operations may represent a continuation of the asynchronous
control flow associated with the current handler. Asio's implementation
can use this knowledge to optimise scheduling of the handler.

The asio_handler_is_continuation hook returns true to indicate whether a
completion handler represents a continuation of the current call
context. The default implementation of the hook returns false, and
applications may customise the hook when necessary. The hook has already
been customised within Asio to return true for the following cases:

- Handlers returned by strand.wrap(), when the corresponding
  asynchronous operation is being initiated from within the strand.

- The internal handlers used to implement the asio::spawn() function's
  stackful coroutines.

- When an intermediate handler of a composed operation (e.g.
  asio::async_read(), asio::async_write(), asio::async_connect(),
  ssl::stream<>, etc.) starts a new asynchronous operation due to the
  composed operation not being complete.

To support this optimisation, a new running_in_this_thread() member
function has been added to the io_service::strand class. This function
returns true when called from within a strand.

Added:
   trunk/boost/asio/detail/handler_cont_helpers.hpp (contents, props changed)
   trunk/boost/asio/handler_continuation_hook.hpp (contents, props changed)
Text files modified:
   trunk/boost/asio.hpp | 1
   trunk/boost/asio/detail/bind_handler.hpp | 43 +++++++++++++++++++++++++
   trunk/boost/asio/detail/dev_poll_reactor.hpp | 7 ++-
   trunk/boost/asio/detail/epoll_reactor.hpp | 6 +-
   trunk/boost/asio/detail/impl/dev_poll_reactor.hpp | 2
   trunk/boost/asio/detail/impl/dev_poll_reactor.ipp | 8 ++--
   trunk/boost/asio/detail/impl/epoll_reactor.hpp | 2
   trunk/boost/asio/detail/impl/epoll_reactor.ipp | 12 +++---
   trunk/boost/asio/detail/impl/kqueue_reactor.hpp | 2
   trunk/boost/asio/detail/impl/kqueue_reactor.ipp | 10 ++--
   trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp | 7 ++-
   trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp | 22 +++++++-----
   trunk/boost/asio/detail/impl/resolver_service_base.ipp | 2
   trunk/boost/asio/detail/impl/select_reactor.hpp | 2
   trunk/boost/asio/detail/impl/select_reactor.ipp | 5 +-
   trunk/boost/asio/detail/impl/strand_service.hpp | 7 ++-
   trunk/boost/asio/detail/impl/strand_service.ipp | 15 ++++++--
   trunk/boost/asio/detail/impl/task_io_service.hpp | 8 +++-
   trunk/boost/asio/detail/impl/task_io_service.ipp | 36 ++-------------------
   trunk/boost/asio/detail/impl/win_iocp_io_service.hpp | 6 +-
   trunk/boost/asio/detail/impl/win_iocp_socket_service_base.ipp | 8 ++--
   trunk/boost/asio/detail/kqueue_reactor.hpp | 8 ++--
   trunk/boost/asio/detail/reactive_descriptor_service.hpp | 22 ++++++++++--
   trunk/boost/asio/detail/reactive_socket_service.hpp | 31 ++++++++++++++---
   trunk/boost/asio/detail/reactive_socket_service_base.hpp | 39 +++++++++++++++++-----
   trunk/boost/asio/detail/select_reactor.hpp | 6 +-
   trunk/boost/asio/detail/strand_service.hpp | 7 +++
   trunk/boost/asio/detail/task_io_service.hpp | 25 ++-----------
   trunk/boost/asio/detail/win_iocp_io_service.hpp | 4 +-
   trunk/boost/asio/detail/wrapped_handler.hpp | 55 +++++++++++++++++++++++++++-----
   trunk/boost/asio/impl/connect.hpp | 17 +++++++++
   trunk/boost/asio/impl/read.hpp | 53 ++++++++++++++++++++++++++++--
   trunk/boost/asio/impl/read_at.hpp | 54 +++++++++++++++++++++++++++++--
   trunk/boost/asio/impl/read_until.hpp | 67 +++++++++++++++++++++++++++++++++++++--
   trunk/boost/asio/impl/spawn.hpp | 7 ++++
   trunk/boost/asio/impl/write.hpp | 50 ++++++++++++++++++++++++++--
   trunk/boost/asio/impl/write_at.hpp | 50 ++++++++++++++++++++++++++--
   trunk/boost/asio/spawn.hpp | 3 +
   trunk/boost/asio/ssl/detail/io.hpp | 14 +++++++
   trunk/boost/asio/strand.hpp | 16 ++++++++-
   trunk/libs/asio/test/strand.cpp | 4 ++
   41 files changed, 567 insertions(+), 176 deletions(-)

Modified: trunk/boost/asio.hpp
==============================================================================
--- trunk/boost/asio.hpp (original)
+++ trunk/boost/asio.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -46,6 +46,7 @@
 #include <boost/asio/deadline_timer.hpp>
 #include <boost/asio/error.hpp>
 #include <boost/asio/handler_alloc_hook.hpp>
+#include <boost/asio/handler_continuation_hook.hpp>
 #include <boost/asio/handler_invoke_hook.hpp>
 #include <boost/asio/handler_type.hpp>
 #include <boost/asio/io_service.hpp>

Modified: trunk/boost/asio/detail/bind_handler.hpp
==============================================================================
--- trunk/boost/asio/detail/bind_handler.hpp (original)
+++ trunk/boost/asio/detail/bind_handler.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -17,6 +17,7 @@
 
 #include <boost/asio/detail/config.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
@@ -72,6 +73,14 @@
       pointer, size, this_handler->handler_);
 }
 
+template <typename Handler, typename Arg1>
+inline bool asio_handler_is_continuation(
+ binder1<Handler, Arg1>* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+}
+
 template <typename Function, typename Handler, typename Arg1>
 inline void asio_handler_invoke(Function& function,
     binder1<Handler, Arg1>* this_handler)
@@ -146,6 +155,14 @@
       pointer, size, this_handler->handler_);
 }
 
+template <typename Handler, typename Arg1, typename Arg2>
+inline bool asio_handler_is_continuation(
+ binder2<Handler, Arg1, Arg2>* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+}
+
 template <typename Function, typename Handler, typename Arg1, typename Arg2>
 inline void asio_handler_invoke(Function& function,
     binder2<Handler, Arg1, Arg2>* this_handler)
@@ -226,6 +243,14 @@
       pointer, size, this_handler->handler_);
 }
 
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+inline bool asio_handler_is_continuation(
+ binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+}
+
 template <typename Function, typename Handler, typename Arg1, typename Arg2,
     typename Arg3>
 inline void asio_handler_invoke(Function& function,
@@ -315,6 +340,15 @@
       pointer, size, this_handler->handler_);
 }
 
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+inline bool asio_handler_is_continuation(
+ binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+}
+
 template <typename Function, typename Handler, typename Arg1, typename Arg2,
     typename Arg3, typename Arg4>
 inline void asio_handler_invoke(Function& function,
@@ -411,6 +445,15 @@
       pointer, size, this_handler->handler_);
 }
 
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+inline bool asio_handler_is_continuation(
+ binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+}
+
 template <typename Function, typename Handler, typename Arg1, typename Arg2,
     typename Arg3, typename Arg4, typename Arg5>
 inline void asio_handler_invoke(Function& function,

Modified: trunk/boost/asio/detail/dev_poll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/dev_poll_reactor.hpp (original)
+++ trunk/boost/asio/detail/dev_poll_reactor.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -87,15 +87,16 @@
       per_descriptor_data& source_descriptor_data);
 
   // Post a reactor operation for immediate completion.
- void post_immediate_completion(reactor_op* op)
+ void post_immediate_completion(reactor_op* op, bool is_continuation)
   {
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, is_continuation);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
   BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
- per_descriptor_data&, reactor_op* op, bool allow_speculative);
+ per_descriptor_data&, reactor_op* op,
+ bool is_continuation, bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the

Modified: trunk/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/epoll_reactor.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -108,16 +108,16 @@
       per_descriptor_data& source_descriptor_data);
 
   // Post a reactor operation for immediate completion.
- void post_immediate_completion(reactor_op* op)
+ void post_immediate_completion(reactor_op* op, bool is_continuation)
   {
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, is_continuation);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
   BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
       per_descriptor_data& descriptor_data, reactor_op* op,
- bool allow_speculative);
+ bool is_continuation, bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the

Added: trunk/boost/asio/detail/handler_cont_helpers.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/detail/handler_cont_helpers.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -0,0 +1,45 @@
+//
+// detail/handler_cont_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/asio/handler_continuation_hook.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+// Calls to asio_handler_is_continuation must be made from a namespace that
+// does not contain overloads of this function. This namespace is defined here
+// for that purpose.
+namespace boost_asio_handler_cont_helpers {
+
+template <typename Context>
+inline bool is_continuation(Context& context)
+{
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
+ || BOOST_WORKAROUND(__GNUC__, < 3)
+ return false;
+#else
+ using boost::asio::asio_handler_is_continuation;
+ return asio_handler_is_continuation(boost::addressof(context));
+#endif
+}
+
+} // namespace boost_asio_handler_cont_helpers
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP

Modified: trunk/boost/asio/detail/impl/dev_poll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/dev_poll_reactor.hpp (original)
+++ trunk/boost/asio/detail/impl/dev_poll_reactor.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -46,7 +46,7 @@
 
   if (shutdown_)
   {
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, false);
     return;
   }
 

Modified: trunk/boost/asio/detail/impl/dev_poll_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/dev_poll_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/dev_poll_reactor.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -163,14 +163,14 @@
 }
 
 void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
- dev_poll_reactor::per_descriptor_data&,
- reactor_op* op, bool allow_speculative)
+ dev_poll_reactor::per_descriptor_data&, reactor_op* op,
+ bool is_continuation, bool allow_speculative)
 {
   boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
   if (shutdown_)
   {
- post_immediate_completion(op);
+ post_immediate_completion(op, is_continuation);
     return;
   }
 
@@ -183,7 +183,7 @@
         if (op->perform())
         {
           lock.unlock();
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, is_continuation);
           return;
         }
       }

Modified: trunk/boost/asio/detail/impl/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/impl/epoll_reactor.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -44,7 +44,7 @@
 
   if (shutdown_)
   {
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, false);
     return;
   }
 

Modified: trunk/boost/asio/detail/impl/epoll_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/epoll_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/epoll_reactor.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -204,13 +204,13 @@
 }
 
 void epoll_reactor::start_op(int op_type, socket_type descriptor,
- epoll_reactor::per_descriptor_data& descriptor_data,
- reactor_op* op, bool allow_speculative)
+ epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op,
+ bool is_continuation, bool allow_speculative)
 {
   if (!descriptor_data)
   {
     op->ec_ = boost::asio::error::bad_descriptor;
- post_immediate_completion(op);
+ post_immediate_completion(op, is_continuation);
     return;
   }
 
@@ -218,7 +218,7 @@
 
   if (descriptor_data->shutdown_)
   {
- post_immediate_completion(op);
+ post_immediate_completion(op, is_continuation);
     return;
   }
 
@@ -231,7 +231,7 @@
       if (op->perform())
       {
         descriptor_lock.unlock();
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, is_continuation);
         return;
       }
 
@@ -250,7 +250,7 @@
           {
             op->ec_ = boost::system::error_code(errno,
                 boost::asio::error::get_system_category());
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, is_continuation);
             return;
           }
         }

Modified: trunk/boost/asio/detail/impl/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/kqueue_reactor.hpp (original)
+++ trunk/boost/asio/detail/impl/kqueue_reactor.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -48,7 +48,7 @@
 
   if (shutdown_)
   {
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, false);
     return;
   }
 

Modified: trunk/boost/asio/detail/impl/kqueue_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/kqueue_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/kqueue_reactor.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -178,13 +178,13 @@
 }
 
 void kqueue_reactor::start_op(int op_type, socket_type descriptor,
- kqueue_reactor::per_descriptor_data& descriptor_data,
- reactor_op* op, bool allow_speculative)
+ kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op,
+ bool is_continuation, bool allow_speculative)
 {
   if (!descriptor_data)
   {
     op->ec_ = boost::asio::error::bad_descriptor;
- post_immediate_completion(op);
+ post_immediate_completion(op, is_continuation);
     return;
   }
 
@@ -192,7 +192,7 @@
 
   if (descriptor_data->shutdown_)
   {
- post_immediate_completion(op);
+ post_immediate_completion(op, is_continuation);
     return;
   }
 
@@ -206,7 +206,7 @@
         if (op->perform())
         {
           descriptor_lock.unlock();
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, is_continuation);
           return;
         }
       }

Modified: trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp (original)
+++ trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -177,7 +177,8 @@
 
 void reactive_descriptor_service::start_op(
     reactive_descriptor_service::implementation_type& impl,
- int op_type, reactor_op* op, bool is_non_blocking, bool noop)
+ int op_type, reactor_op* op, bool is_continuation,
+ bool is_non_blocking, bool noop)
 {
   if (!noop)
   {
@@ -186,12 +187,12 @@
           impl.descriptor_, impl.state_, true, op->ec_))
     {
       reactor_.start_op(op_type, impl.descriptor_,
- impl.reactor_data_, op, is_non_blocking);
+ impl.reactor_data_, op, is_continuation, is_non_blocking);
       return;
     }
   }
 
- reactor_.post_immediate_completion(op);
+ reactor_.post_immediate_completion(op, is_continuation);
 }
 
 } // namespace detail

Modified: trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp (original)
+++ trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -200,7 +200,8 @@
 
 void reactive_socket_service_base::start_op(
     reactive_socket_service_base::base_implementation_type& impl,
- int op_type, reactor_op* op, bool is_non_blocking, bool noop)
+ int op_type, reactor_op* op, bool is_continuation,
+ bool is_non_blocking, bool noop)
 {
   if (!noop)
   {
@@ -209,30 +210,31 @@
           impl.socket_, impl.state_, true, op->ec_))
     {
       reactor_.start_op(op_type, impl.socket_,
- impl.reactor_data_, op, is_non_blocking);
+ impl.reactor_data_, op, is_continuation, is_non_blocking);
       return;
     }
   }
 
- reactor_.post_immediate_completion(op);
+ reactor_.post_immediate_completion(op, is_continuation);
 }
 
 void reactive_socket_service_base::start_accept_op(
     reactive_socket_service_base::base_implementation_type& impl,
- reactor_op* op, bool peer_is_open)
+ reactor_op* op, bool is_continuation, bool peer_is_open)
 {
   if (!peer_is_open)
- start_op(impl, reactor::read_op, op, true, false);
+ start_op(impl, reactor::read_op, op, true, is_continuation, false);
   else
   {
     op->ec_ = boost::asio::error::already_open;
- reactor_.post_immediate_completion(op);
+ reactor_.post_immediate_completion(op, is_continuation);
   }
 }
 
 void reactive_socket_service_base::start_connect_op(
     reactive_socket_service_base::base_implementation_type& impl,
- reactor_op* op, const socket_addr_type* addr, size_t addrlen)
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen)
 {
   if ((impl.state_ & socket_ops::non_blocking)
       || socket_ops::set_internal_non_blocking(
@@ -244,14 +246,14 @@
           || op->ec_ == boost::asio::error::would_block)
       {
         op->ec_ = boost::system::error_code();
- reactor_.start_op(reactor::connect_op,
- impl.socket_, impl.reactor_data_, op, false);
+ reactor_.start_op(reactor::connect_op, impl.socket_,
+ impl.reactor_data_, op, is_continuation, false);
         return;
       }
     }
   }
 
- reactor_.post_immediate_completion(op);
+ reactor_.post_immediate_completion(op, is_continuation);
 }
 
 } // namespace detail

Modified: trunk/boost/asio/detail/impl/resolver_service_base.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/resolver_service_base.ipp (original)
+++ trunk/boost/asio/detail/impl/resolver_service_base.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -110,7 +110,7 @@
 {
   start_work_thread();
   io_service_impl_.work_started();
- work_io_service_impl_.post_immediate_completion(op);
+ work_io_service_impl_.post_immediate_completion(op, false);
 }
 
 void resolver_service_base::start_work_thread()

Modified: trunk/boost/asio/detail/impl/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/impl/select_reactor.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -50,7 +50,7 @@
 
   if (shutdown_)
   {
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, false);
     return;
   }
 

Modified: trunk/boost/asio/detail/impl/select_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/select_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/select_reactor.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -122,13 +122,14 @@
 }
 
 void select_reactor::start_op(int op_type, socket_type descriptor,
- select_reactor::per_descriptor_data&, reactor_op* op, bool)
+ select_reactor::per_descriptor_data&, reactor_op* op,
+ bool is_continuation, bool)
 {
   boost::asio::detail::mutex::scoped_lock lock(mutex_);
 
   if (shutdown_)
   {
- post_immediate_completion(op);
+ post_immediate_completion(op, is_continuation);
     return;
   }
 

Modified: trunk/boost/asio/detail/impl/strand_service.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/strand_service.hpp (original)
+++ trunk/boost/asio/detail/impl/strand_service.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -46,7 +46,7 @@
     impl_->mutex_.unlock();
 
     if (more_handlers)
- io_service_->post_immediate_completion(impl_);
+ io_service_->post_immediate_completion(impl_, false);
   }
 };
 
@@ -94,6 +94,9 @@
 void strand_service::post(strand_service::implementation_type& impl,
     Handler& handler)
 {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
   // Allocate and construct an operation to wrap the handler.
   typedef completion_handler<Handler> op;
   typename op::ptr p = { boost::addressof(handler),
@@ -103,7 +106,7 @@
 
   BOOST_ASIO_HANDLER_CREATION((p.p, "strand", impl, "post"));
 
- do_post(impl, p.p);
+ do_post(impl, p.p, is_continuation);
   p.v = p.p = 0;
 }
 

Modified: trunk/boost/asio/detail/impl/strand_service.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/strand_service.ipp (original)
+++ trunk/boost/asio/detail/impl/strand_service.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -38,7 +38,7 @@
     impl_->mutex_.unlock();
 
     if (more_handlers)
- owner_->post_private_immediate_completion(impl_);
+ owner_->post_immediate_completion(impl_, true);
   }
 };
 
@@ -85,6 +85,12 @@
   impl = implementations_[index].get();
 }
 
+bool strand_service::running_in_this_thread(
+ const implementation_type& impl) const
+{
+ return call_stack<strand_impl>::contains(impl) != 0;
+}
+
 bool strand_service::do_dispatch(implementation_type& impl, operation* op)
 {
   // If we are running inside the io_service, and no other handler already
@@ -112,13 +118,14 @@
     impl->locked_ = true;
     impl->mutex_.unlock();
     impl->ready_queue_.push(op);
- io_service_.post_immediate_completion(impl);
+ io_service_.post_immediate_completion(impl, false);
   }
 
   return false;
 }
 
-void strand_service::do_post(implementation_type& impl, operation* op)
+void strand_service::do_post(implementation_type& impl,
+ operation* op, bool is_continuation)
 {
   impl->mutex_.lock();
   if (impl->locked_)
@@ -134,7 +141,7 @@
     impl->locked_ = true;
     impl->mutex_.unlock();
     impl->ready_queue_.push(op);
- io_service_.post_immediate_completion(impl);
+ io_service_.post_immediate_completion(impl, is_continuation);
   }
 }
 

Modified: trunk/boost/asio/detail/impl/task_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/task_io_service.hpp (original)
+++ trunk/boost/asio/detail/impl/task_io_service.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -18,6 +18,7 @@
 #include <boost/asio/detail/completion_handler.hpp>
 #include <boost/asio/detail/fenced_block.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
@@ -45,7 +46,7 @@
 
     BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
 
- post_non_private_immediate_completion(p.p);
+ do_dispatch(p.p);
     p.v = p.p = 0;
   }
 }
@@ -53,6 +54,9 @@
 template <typename Handler>
 void task_io_service::post(Handler& handler)
 {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
   // Allocate and construct an operation to wrap the handler.
   typedef completion_handler<Handler> op;
   typename op::ptr p = { boost::addressof(handler),
@@ -62,7 +66,7 @@
 
   BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "post"));
 
- post_immediate_completion(p.p);
+ post_immediate_completion(p.p, is_continuation);
   p.v = p.p = 0;
 }
 

Modified: trunk/boost/asio/detail/impl/task_io_service.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/task_io_service.ipp (original)
+++ trunk/boost/asio/detail/impl/task_io_service.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -257,10 +257,11 @@
   stopped_ = false;
 }
 
-void task_io_service::post_immediate_completion(task_io_service::operation* op)
+void task_io_service::post_immediate_completion(
+ task_io_service::operation* op, bool is_continuation)
 {
 #if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
- if (one_thread_)
+ if (one_thread_ || is_continuation)
   {
     if (thread_info* this_thread = thread_call_stack::contains(this))
     {
@@ -317,39 +318,10 @@
   }
 }
 
-void task_io_service::post_private_immediate_completion(
- task_io_service::operation* op)
-{
- work_started();
- post_private_deferred_completion(op);
-}
-
-void task_io_service::post_private_deferred_completion(
- task_io_service::operation* op)
-{
-#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
- if (thread_info* this_thread = thread_call_stack::contains(this))
- {
- this_thread->private_op_queue.push(op);
- return;
- }
-#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
-
- mutex::scoped_lock lock(mutex_);
- op_queue_.push(op);
- wake_one_thread_and_unlock(lock);
-}
-
-void task_io_service::post_non_private_immediate_completion(
+void task_io_service::do_dispatch(
     task_io_service::operation* op)
 {
   work_started();
- post_non_private_deferred_completion(op);
-}
-
-void task_io_service::post_non_private_deferred_completion(
- task_io_service::operation* op)
-{
   mutex::scoped_lock lock(mutex_);
   op_queue_.push(op);
   wake_one_thread_and_unlock(lock);

Modified: trunk/boost/asio/detail/impl/win_iocp_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/impl/win_iocp_io_service.hpp (original)
+++ trunk/boost/asio/detail/impl/win_iocp_io_service.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -49,7 +49,7 @@
 
     BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
 
- post_immediate_completion(p.p);
+ post_immediate_completion(p.p, false);
     p.v = p.p = 0;
   }
 }
@@ -66,7 +66,7 @@
 
   BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "post"));
 
- post_immediate_completion(p.p);
+ post_immediate_completion(p.p, false);
   p.v = p.p = 0;
 }
 
@@ -92,7 +92,7 @@
   // If the service has been shut down we silently discard the timer.
   if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
   {
- post_immediate_completion(op);
+ post_immediate_completion(op, false);
     return;
   }
 

Modified: trunk/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/win_iocp_socket_service_base.ipp (original)
+++ trunk/boost/asio/detail/impl/win_iocp_socket_service_base.ipp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -534,13 +534,13 @@
 
   if (is_open(impl))
   {
- r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false);
+ r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false, false);
     return;
   }
   else
     op->ec_ = boost::asio::error::bad_descriptor;
 
- iocp_service_.post_immediate_completion(op);
+ iocp_service_.post_immediate_completion(op, false);
 }
 
 void win_iocp_socket_service_base::start_connect_op(
@@ -561,13 +561,13 @@
       {
         op->ec_ = boost::system::error_code();
         r.start_op(reactor::connect_op, impl.socket_,
- impl.reactor_data_, op, false);
+ impl.reactor_data_, op, false, false);
         return;
       }
     }
   }
 
- r.post_immediate_completion(op);
+ r.post_immediate_completion(op, false);
 }
 
 void win_iocp_socket_service_base::close_for_destruction(

Modified: trunk/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/kqueue_reactor.hpp (original)
+++ trunk/boost/asio/detail/kqueue_reactor.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -108,16 +108,16 @@
       per_descriptor_data& source_descriptor_data);
 
   // Post a reactor operation for immediate completion.
- void post_immediate_completion(reactor_op* op)
+ void post_immediate_completion(reactor_op* op, bool is_continuation)
   {
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, is_continuation);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
   BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
- per_descriptor_data& descriptor_data,
- reactor_op* op, bool allow_speculative);
+ per_descriptor_data& descriptor_data, reactor_op* op,
+ bool is_continuation, bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the

Modified: trunk/boost/asio/detail/reactive_descriptor_service.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_descriptor_service.hpp (original)
+++ trunk/boost/asio/detail/reactive_descriptor_service.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -188,6 +188,9 @@
   void async_write_some(implementation_type& impl,
       const ConstBufferSequence& buffers, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef descriptor_write_op<ConstBufferSequence, Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -197,7 +200,7 @@
 
     BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", &impl, "async_write_some"));
 
- start_op(impl, reactor::write_op, p.p, true,
+ start_op(impl, reactor::write_op, p.p, is_continuation, true,
         buffer_sequence_adapter<boost::asio::const_buffer,
           ConstBufferSequence>::all_empty(buffers));
     p.v = p.p = 0;
@@ -208,6 +211,9 @@
   void async_write_some(implementation_type& impl,
       const null_buffers&, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_null_buffers_op<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -218,7 +224,7 @@
     BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor",
           &impl, "async_write_some(null_buffers)"));
 
- start_op(impl, reactor::write_op, p.p, false, false);
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
     p.v = p.p = 0;
   }
 
@@ -250,6 +256,9 @@
   void async_read_some(implementation_type& impl,
       const MutableBufferSequence& buffers, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef descriptor_read_op<MutableBufferSequence, Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -259,7 +268,7 @@
 
     BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", &impl, "async_read_some"));
 
- start_op(impl, reactor::read_op, p.p, true,
+ start_op(impl, reactor::read_op, p.p, is_continuation, true,
         buffer_sequence_adapter<boost::asio::mutable_buffer,
           MutableBufferSequence>::all_empty(buffers));
     p.v = p.p = 0;
@@ -270,6 +279,9 @@
   void async_read_some(implementation_type& impl,
       const null_buffers&, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_null_buffers_op<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -280,14 +292,14 @@
     BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor",
           &impl, "async_read_some(null_buffers)"));
 
- start_op(impl, reactor::read_op, p.p, false, false);
+ start_op(impl, reactor::read_op, p.p, is_continuation, false, false);
     p.v = p.p = 0;
   }
 
 private:
   // Start the asynchronous operation.
   BOOST_ASIO_DECL void start_op(implementation_type& impl, int op_type,
- reactor_op* op, bool is_non_blocking, bool noop);
+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
 
   // The selector that performs event demultiplexing for the service.
   reactor& reactor_;

Modified: trunk/boost/asio/detail/reactive_socket_service.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_service.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_service.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -217,6 +217,9 @@
       const endpoint_type& destination, socket_base::message_flags flags,
       Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_socket_sendto_op<ConstBufferSequence,
         endpoint_type, Handler> op;
@@ -227,7 +230,7 @@
 
     BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
 
- start_op(impl, reactor::write_op, p.p, true, false);
+ start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
     p.v = p.p = 0;
   }
 
@@ -236,6 +239,9 @@
   void async_send_to(implementation_type& impl, const null_buffers&,
       const endpoint_type&, socket_base::message_flags, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_null_buffers_op<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -246,7 +252,7 @@
     BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
           &impl, "async_send_to(null_buffers)"));
 
- start_op(impl, reactor::write_op, p.p, false, false);
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
     p.v = p.p = 0;
   }
 
@@ -294,6 +300,9 @@
       const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
       socket_base::message_flags flags, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_socket_recvfrom_op<MutableBufferSequence,
         endpoint_type, Handler> op;
@@ -310,7 +319,7 @@
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
- p.p, true, false);
+ p.p, is_continuation, true, false);
     p.v = p.p = 0;
   }
 
@@ -320,6 +329,9 @@
       const null_buffers&, endpoint_type& sender_endpoint,
       socket_base::message_flags flags, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_null_buffers_op<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -336,7 +348,7 @@
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
- p.p, false, false);
+ p.p, is_continuation, false, false);
     p.v = p.p = 0;
   }
 
@@ -375,6 +387,9 @@
   void async_accept(implementation_type& impl, Socket& peer,
       endpoint_type* peer_endpoint, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -385,7 +400,7 @@
 
     BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
 
- start_accept_op(impl, p.p, peer.is_open());
+ start_accept_op(impl, p.p, is_continuation, peer.is_open());
     p.v = p.p = 0;
   }
 
@@ -403,6 +418,9 @@
   void async_connect(implementation_type& impl,
       const endpoint_type& peer_endpoint, Handler& handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_socket_connect_op<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -412,7 +430,8 @@
 
     BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
 
- start_connect_op(impl, p.p, peer_endpoint.data(), peer_endpoint.size());
+ start_connect_op(impl, p.p, is_continuation,
+ peer_endpoint.data(), peer_endpoint.size());
     p.v = p.p = 0;
   }
 };

Modified: trunk/boost/asio/detail/reactive_socket_service_base.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_service_base.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_service_base.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -200,6 +200,9 @@
       const ConstBufferSequence& buffers,
       socket_base::message_flags flags, Handler handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -209,7 +212,7 @@
 
     BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
 
- start_op(impl, reactor::write_op, p.p, true,
+ start_op(impl, reactor::write_op, p.p, is_continuation, true,
         ((impl.state_ & socket_ops::stream_oriented)
           && buffer_sequence_adapter<boost::asio::const_buffer,
             ConstBufferSequence>::all_empty(buffers)));
@@ -221,6 +224,9 @@
   void async_send(base_implementation_type& impl, const null_buffers&,
       socket_base::message_flags, Handler handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_null_buffers_op<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -231,7 +237,7 @@
     BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
           &impl, "async_send(null_buffers)"));
 
- start_op(impl, reactor::write_op, p.p, false, false);
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
     p.v = p.p = 0;
   }
 
@@ -265,6 +271,9 @@
       const MutableBufferSequence& buffers,
       socket_base::message_flags flags, Handler handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_socket_recv_op<MutableBufferSequence, Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -277,7 +286,8 @@
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
- p.p, (flags & socket_base::message_out_of_band) == 0,
+ p.p, is_continuation,
+ (flags & socket_base::message_out_of_band) == 0,
         ((impl.state_ & socket_ops::stream_oriented)
           && buffer_sequence_adapter<boost::asio::mutable_buffer,
             MutableBufferSequence>::all_empty(buffers)));
@@ -289,6 +299,9 @@
   void async_receive(base_implementation_type& impl, const null_buffers&,
       socket_base::message_flags flags, Handler handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_null_buffers_op<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -302,7 +315,7 @@
     start_op(impl,
         (flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
- p.p, false, false);
+ p.p, is_continuation, false, false);
     p.v = p.p = 0;
   }
 
@@ -343,6 +356,9 @@
       const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
       socket_base::message_flags& out_flags, Handler handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_socket_recvmsg_op<MutableBufferSequence, Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -356,7 +372,8 @@
     start_op(impl,
         (in_flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
- p.p, (in_flags & socket_base::message_out_of_band) == 0, false);
+ p.p, is_continuation,
+ (in_flags & socket_base::message_out_of_band) == 0, false);
     p.v = p.p = 0;
   }
 
@@ -366,6 +383,9 @@
       const null_buffers&, socket_base::message_flags in_flags,
       socket_base::message_flags& out_flags, Handler handler)
   {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
     // Allocate and construct an operation to wrap the handler.
     typedef reactive_null_buffers_op<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
@@ -383,7 +403,7 @@
     start_op(impl,
         (in_flags & socket_base::message_out_of_band)
           ? reactor::except_op : reactor::read_op,
- p.p, false, false);
+ p.p, is_continuation, false, false);
     p.v = p.p = 0;
   }
 
@@ -400,15 +420,16 @@
 
   // Start the asynchronous read or write operation.
   BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
- reactor_op* op, bool is_non_blocking, bool noop);
+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
 
   // Start the asynchronous accept operation.
   BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
- reactor_op* op, bool peer_is_open);
+ reactor_op* op, bool is_continuation, bool peer_is_open);
 
   // Start the asynchronous connect operation.
   BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl,
- reactor_op* op, const socket_addr_type* addr, size_t addrlen);
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen);
 
   // The selector that performs event demultiplexing for the service.
   reactor& reactor_;

Modified: trunk/boost/asio/detail/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/select_reactor.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -92,15 +92,15 @@
       per_descriptor_data& descriptor_data, reactor_op* op);
 
   // Post a reactor operation for immediate completion.
- void post_immediate_completion(reactor_op* op)
+ void post_immediate_completion(reactor_op* op, bool is_continuation)
   {
- io_service_.post_immediate_completion(op);
+ io_service_.post_immediate_completion(op, is_continuation);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
   BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor,
- per_descriptor_data&, reactor_op* op, bool);
+ per_descriptor_data&, reactor_op* op, bool is_continuation, bool);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the

Modified: trunk/boost/asio/detail/strand_service.hpp
==============================================================================
--- trunk/boost/asio/detail/strand_service.hpp (original)
+++ trunk/boost/asio/detail/strand_service.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -92,13 +92,18 @@
   template <typename Handler>
   void post(implementation_type& impl, Handler& handler);
 
+ // Determine whether the strand is running in the current thread.
+ BOOST_ASIO_DECL bool running_in_this_thread(
+ const implementation_type& impl) const;
+
 private:
   // Helper function to dispatch a handler. Returns true if the handler should
   // be dispatched immediately.
   BOOST_ASIO_DECL bool do_dispatch(implementation_type& impl, operation* op);
 
   // Helper fiunction to post a handler.
- BOOST_ASIO_DECL void do_post(implementation_type& impl, operation* op);
+ BOOST_ASIO_DECL void do_post(implementation_type& impl,
+ operation* op, bool is_continuation);
 
   BOOST_ASIO_DECL static void do_complete(io_service_impl* owner,
       operation* base, const boost::system::error_code& ec,

Modified: trunk/boost/asio/detail/task_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/task_io_service.hpp (original)
+++ trunk/boost/asio/detail/task_io_service.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -102,7 +102,8 @@
 
   // Request invocation of the given operation and return immediately. Assumes
   // that work_started() has not yet been called for the operation.
- BOOST_ASIO_DECL void post_immediate_completion(operation* op);
+ BOOST_ASIO_DECL void post_immediate_completion(
+ operation* op, bool is_continuation);
 
   // Request invocation of the given operation and return immediately. Assumes
   // that work_started() was previously called for the operation.
@@ -112,16 +113,6 @@
   // that work_started() was previously called for each operation.
   BOOST_ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);
 
- // Request invocation of the given operation, preferring the thread-private
- // queue if available, and return immediately. Assumes that work_started()
- // has not yet been called for the operation.
- BOOST_ASIO_DECL void post_private_immediate_completion(operation* op);
-
- // Request invocation of the given operation, preferring the thread-private
- // queue if available, and return immediately. Assumes that work_started()
- // was previously called for the operation.
- BOOST_ASIO_DECL void post_private_deferred_completion(operation* op);
-
   // Process unfinished operations as part of a shutdown_service operation.
   // Assumes that work_started() was previously called for the operations.
   BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops);
@@ -130,15 +121,9 @@
   // Structure containing information about an idle thread.
   typedef task_io_service_thread_info thread_info;
 
- // Request invocation of the given operation, avoiding the thread-private
- // queue, and return immediately. Assumes that work_started() has not yet
- // been called for the operation.
- BOOST_ASIO_DECL void post_non_private_immediate_completion(operation* op);
-
- // Request invocation of the given operation, avoiding the thread-private
- // queue, and return immediately. Assumes that work_started() was previously
- // called for the operation.
- BOOST_ASIO_DECL void post_non_private_deferred_completion(operation* op);
+ // Enqueue the given operation following a failed attempt to dispatch the
+ // operation for immediate invocation.
+ BOOST_ASIO_DECL void do_dispatch(operation* op);
 
   // Run at most one operation. May block.
   BOOST_ASIO_DECL std::size_t do_run_one(mutex::scoped_lock& lock,

Modified: trunk/boost/asio/detail/win_iocp_io_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_io_service.hpp (original)
+++ trunk/boost/asio/detail/win_iocp_io_service.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -121,7 +121,7 @@
 
   // Request invocation of the given operation and return immediately. Assumes
   // that work_started() has not yet been called for the operation.
- void post_immediate_completion(win_iocp_operation* op)
+ void post_immediate_completion(win_iocp_operation* op, bool)
   {
     work_started();
     post_deferred_completion(op);
@@ -141,7 +141,7 @@
   // called for the operation.
   void post_private_immediate_completion(win_iocp_operation* op)
   {
- post_immediate_completion(op);
+ post_immediate_completion(op, false);
   }
 
   // Request invocation of the given operation using the thread-private queue

Modified: trunk/boost/asio/detail/wrapped_handler.hpp
==============================================================================
--- trunk/boost/asio/detail/wrapped_handler.hpp (original)
+++ trunk/boost/asio/detail/wrapped_handler.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -17,6 +17,7 @@
 
 #include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 
 #include <boost/asio/detail/push_options.hpp>
@@ -25,7 +26,26 @@
 namespace asio {
 namespace detail {
 
-template <typename Dispatcher, typename Handler>
+struct is_continuation_delegated
+{
+ template <typename Dispatcher, typename Handler>
+ bool operator()(Dispatcher&, Handler& handler) const
+ {
+ return boost_asio_handler_cont_helpers::is_continuation(handler);
+ }
+};
+
+struct is_continuation_if_running
+{
+ template <typename Dispatcher, typename Handler>
+ bool operator()(Dispatcher& dispatcher, Handler&) const
+ {
+ return dispatcher.running_in_this_thread();
+ }
+};
+
+template <typename Dispatcher, typename Handler,
+ typename IsContinuation = is_continuation_delegated>
 class wrapped_handler
 {
 public:
@@ -181,34 +201,43 @@
   Handler handler_;
 };
 
-template <typename Dispatcher, typename Handler>
+template <typename Dispatcher, typename Handler, typename IsContinuation>
 inline void* asio_handler_allocate(std::size_t size,
- wrapped_handler<Dispatcher, Handler>* this_handler)
+ wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
 {
   return boost_asio_handler_alloc_helpers::allocate(
       size, this_handler->handler_);
 }
 
-template <typename Dispatcher, typename Handler>
+template <typename Dispatcher, typename Handler, typename IsContinuation>
 inline void asio_handler_deallocate(void* pointer, std::size_t size,
- wrapped_handler<Dispatcher, Handler>* this_handler)
+ wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
 {
   boost_asio_handler_alloc_helpers::deallocate(
       pointer, size, this_handler->handler_);
 }
 
-template <typename Function, typename Dispatcher, typename Handler>
+template <typename Dispatcher, typename Handler, typename IsContinuation>
+inline bool asio_handler_is_continuation(
+ wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
+{
+ return IsContinuation()(this_handler->dispatcher_, this_handler->handler_);
+}
+
+template <typename Function, typename Dispatcher,
+ typename Handler, typename IsContinuation>
 inline void asio_handler_invoke(Function& function,
- wrapped_handler<Dispatcher, Handler>* this_handler)
+ wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
 {
   this_handler->dispatcher_.dispatch(
       rewrapped_handler<Function, Handler>(
         function, this_handler->handler_));
 }
 
-template <typename Function, typename Dispatcher, typename Handler>
+template <typename Function, typename Dispatcher,
+ typename Handler, typename IsContinuation>
 inline void asio_handler_invoke(const Function& function,
- wrapped_handler<Dispatcher, Handler>* this_handler)
+ wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)
 {
   this_handler->dispatcher_.dispatch(
       rewrapped_handler<Function, Handler>(
@@ -231,6 +260,14 @@
       pointer, size, this_handler->context_);
 }
 
+template <typename Dispatcher, typename Context>
+inline bool asio_handler_is_continuation(
+ rewrapped_handler<Dispatcher, Context>* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+}
+
 template <typename Function, typename Handler, typename Context>
 inline void asio_handler_invoke(Function& function,
     rewrapped_handler<Handler, Context>* this_handler)

Added: trunk/boost/asio/handler_continuation_hook.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/asio/handler_continuation_hook.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -0,0 +1,56 @@
+//
+// handler_continuation_hook.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_HANDLER_CONTINUATION_HOOK_HPP
+#define BOOST_ASIO_HANDLER_CONTINUATION_HOOK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default continuation function for handlers.
+/**
+ * Asynchronous operations may represent a continuation of the asynchronous
+ * control flow associated with the current handler. The implementation can use
+ * this knowledge to optimise scheduling of the handler.
+ *
+ * Implement asio_handler_is_continuation for your own handlers to indicate
+ * when a handler represents a continuation.
+ *
+ * The default implementation of the continuation hook returns <tt>false</tt>.
+ *
+ * @par Example
+ * @code
+ * class my_handler;
+ *
+ * bool asio_handler_is_continuation(my_handler* context)
+ * {
+ * return true;
+ * }
+ * @endcode
+ */
+inline bool asio_handler_is_continuation(...)
+{
+ return false;
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_HANDLER_CONTINUATION_HOOK_HPP

Modified: trunk/boost/asio/impl/connect.hpp
==============================================================================
--- trunk/boost/asio/impl/connect.hpp (original)
+++ trunk/boost/asio/impl/connect.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -18,6 +18,7 @@
 #include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/consuming_buffers.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/handler_type_requirements.hpp>
 #include <boost/asio/detail/throw_error.hpp>
@@ -184,6 +185,7 @@
         socket_(sock),
         iter_(begin),
         end_(end),
+ start_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler))
     {
     }
@@ -194,6 +196,7 @@
         socket_(other.socket_),
         iter_(other.iter_),
         end_(other.end_),
+ start_(other.start_),
         handler_(other.handler_)
     {
     }
@@ -203,6 +206,7 @@
         socket_(other.socket_),
         iter_(other.iter_),
         end_(other.end_),
+ start_(other.start_),
         handler_(BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(other.handler_))
     {
     }
@@ -210,7 +214,7 @@
 
     void operator()(boost::system::error_code ec, int start = 0)
     {
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         for (;;)
@@ -258,6 +262,7 @@
     basic_socket<Protocol, SocketService>& socket_;
     Iterator iter_;
     Iterator end_;
+ int start_;
     ComposedConnectHandler handler_;
   };
 
@@ -281,6 +286,16 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename Protocol, typename SocketService, typename Iterator,
+ typename ConnectCondition, typename ComposedConnectHandler>
+ inline bool asio_handler_is_continuation(
+ connect_op<Protocol, SocketService, Iterator,
+ ConnectCondition, ComposedConnectHandler>* this_handler)
+ {
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename Protocol,
       typename SocketService, typename Iterator,
       typename ConnectCondition, typename ComposedConnectHandler>

Modified: trunk/boost/asio/impl/read.hpp
==============================================================================
--- trunk/boost/asio/impl/read.hpp (original)
+++ trunk/boost/asio/impl/read.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -24,6 +24,7 @@
 #include <boost/asio/detail/consuming_buffers.hpp>
 #include <boost/asio/detail/dependent_type.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/handler_type_requirements.hpp>
 #include <boost/asio/detail/throw_error.hpp>
@@ -154,6 +155,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -164,6 +166,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -173,6 +176,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -182,7 +186,7 @@
     void operator()(const boost::system::error_code& ec,
         std::size_t bytes_transferred, int start = 0)
     {
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         buffers_.prepare(this->check_for_completion(ec, total_transferred_));
@@ -207,6 +211,7 @@
     AsyncReadStream& stream_;
     boost::asio::detail::consuming_buffers<
       mutable_buffer, MutableBufferSequence> buffers_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -225,6 +230,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffer_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -235,6 +241,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -244,6 +251,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -254,7 +262,7 @@
         std::size_t bytes_transferred, int start = 0)
     {
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -278,6 +286,7 @@
   //private:
     AsyncReadStream& stream_;
     boost::asio::mutable_buffer buffer_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -295,6 +304,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -305,6 +315,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -314,6 +325,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -330,7 +342,7 @@
       std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
       std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -357,6 +369,7 @@
   //private:
     AsyncReadStream& stream_;
     boost::array<Elem, 2> buffers_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -376,6 +389,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -386,6 +400,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -395,6 +410,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -411,7 +427,7 @@
       std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
       std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -438,6 +454,7 @@
   //private:
     AsyncReadStream& stream_;
     std::array<Elem, 2> buffers_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -464,6 +481,17 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_op<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncReadStream,
       typename MutableBufferSequence, typename CompletionCondition,
       typename ReadHandler>
@@ -553,6 +581,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         streambuf_(streambuf),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -563,6 +592,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         streambuf_(other.streambuf_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -572,6 +602,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         streambuf_(other.streambuf_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -582,7 +613,7 @@
         std::size_t bytes_transferred, int start = 0)
     {
       std::size_t max_size, bytes_available;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         max_size = this->check_for_completion(ec, total_transferred_);
@@ -607,6 +638,7 @@
   //private:
     AsyncReadStream& stream_;
     boost::asio::basic_streambuf<Allocator>& streambuf_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -631,6 +663,17 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_streambuf_op<AsyncReadStream, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncReadStream,
       typename Allocator, typename CompletionCondition, typename ReadHandler>
   inline void asio_handler_invoke(Function& function,

Modified: trunk/boost/asio/impl/read_at.hpp
==============================================================================
--- trunk/boost/asio/impl/read_at.hpp (original)
+++ trunk/boost/asio/impl/read_at.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -24,6 +24,7 @@
 #include <boost/asio/detail/consuming_buffers.hpp>
 #include <boost/asio/detail/dependent_type.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/handler_type_requirements.hpp>
 #include <boost/asio/detail/throw_error.hpp>
@@ -167,6 +168,7 @@
         device_(device),
         offset_(offset),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -178,6 +180,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -188,6 +191,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -197,7 +201,7 @@
     void operator()(const boost::system::error_code& ec,
         std::size_t bytes_transferred, int start = 0)
     {
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         buffers_.prepare(this->check_for_completion(ec, total_transferred_));
@@ -223,6 +227,7 @@
     boost::uint64_t offset_;
     boost::asio::detail::consuming_buffers<
       mutable_buffer, MutableBufferSequence> buffers_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -242,6 +247,7 @@
         device_(device),
         offset_(offset),
         buffer_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -253,6 +259,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -263,6 +270,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -273,7 +281,7 @@
         std::size_t bytes_transferred, int start = 0)
     {
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -298,6 +306,7 @@
     AsyncRandomAccessReadDevice& device_;
     boost::uint64_t offset_;
     boost::asio::mutable_buffer buffer_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -317,6 +326,7 @@
         device_(device),
         offset_(offset),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -328,6 +338,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -338,6 +349,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -354,7 +366,7 @@
       std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
       std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -383,6 +395,7 @@
     AsyncRandomAccessReadDevice& device_;
     boost::uint64_t offset_;
     boost::array<Elem, 2> buffers_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -404,6 +417,7 @@
         device_(device),
         offset_(offset),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -415,6 +429,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -425,6 +440,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -441,7 +457,7 @@
       std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
       std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -470,6 +486,7 @@
     AsyncRandomAccessReadDevice& device_;
     boost::uint64_t offset_;
     std::array<Elem, 2> buffers_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -498,6 +515,18 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncRandomAccessReadDevice,
       typename MutableBufferSequence, typename CompletionCondition,
       typename ReadHandler>
@@ -604,6 +633,7 @@
         device_(device),
         offset_(offset),
         streambuf_(streambuf),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -615,6 +645,7 @@
         device_(other.device_),
         offset_(other.offset_),
         streambuf_(other.streambuf_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -625,6 +656,7 @@
         device_(other.device_),
         offset_(other.offset_),
         streambuf_(other.streambuf_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -635,7 +667,7 @@
         std::size_t bytes_transferred, int start = 0)
     {
       std::size_t max_size, bytes_available;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         max_size = this->check_for_completion(ec, total_transferred_);
@@ -662,6 +694,7 @@
     AsyncRandomAccessReadDevice& device_;
     boost::uint64_t offset_;
     boost::asio::basic_streambuf<Allocator>& streambuf_;
+ int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
@@ -686,6 +719,17 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncRandomAccessReadDevice,
       typename Allocator, typename CompletionCondition, typename ReadHandler>
   inline void asio_handler_invoke(Function& function,

Modified: trunk/boost/asio/impl/read_until.hpp
==============================================================================
--- trunk/boost/asio/impl/read_until.hpp (original)
+++ trunk/boost/asio/impl/read_until.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -24,6 +24,7 @@
 #include <boost/asio/buffers_iterator.hpp>
 #include <boost/asio/detail/bind_handler.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/handler_type_requirements.hpp>
 #include <boost/asio/detail/throw_error.hpp>
@@ -331,6 +332,7 @@
       : stream_(stream),
         streambuf_(streambuf),
         delim_(delim),
+ start_(0),
         search_position_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -341,6 +343,7 @@
       : stream_(other.stream_),
         streambuf_(other.streambuf_),
         delim_(other.delim_),
+ start_(other.start_),
         search_position_(other.search_position_),
         handler_(other.handler_)
     {
@@ -350,6 +353,7 @@
       : stream_(other.stream_),
         streambuf_(other.streambuf_),
         delim_(other.delim_),
+ start_(other.start_),
         search_position_(other.search_position_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -361,7 +365,7 @@
     {
       const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
       std::size_t bytes_to_read;
- switch (start)
+ switch (start_ = start)
       {
       case 1:
         for (;;)
@@ -430,6 +434,7 @@
     AsyncReadStream& stream_;
     boost::asio::basic_streambuf<Allocator>& streambuf_;
     char delim_;
+ int start_;
     std::size_t search_position_;
     ReadHandler handler_;
   };
@@ -452,6 +457,16 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_until_delim_op<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncReadStream, typename Allocator,
       typename ReadHandler>
   inline void asio_handler_invoke(Function& function,
@@ -509,6 +524,7 @@
       : stream_(stream),
         streambuf_(streambuf),
         delim_(delim),
+ start_(0),
         search_position_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -519,6 +535,7 @@
       : stream_(other.stream_),
         streambuf_(other.streambuf_),
         delim_(other.delim_),
+ start_(other.start_),
         search_position_(other.search_position_),
         handler_(other.handler_)
     {
@@ -528,6 +545,7 @@
       : stream_(other.stream_),
         streambuf_(other.streambuf_),
         delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
+ start_(other.start_),
         search_position_(other.search_position_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -539,7 +557,7 @@
     {
       const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
       std::size_t bytes_to_read;
- switch (start)
+ switch (start_ = start)
       {
       case 1:
         for (;;)
@@ -619,6 +637,7 @@
     AsyncReadStream& stream_;
     boost::asio::basic_streambuf<Allocator>& streambuf_;
     std::string delim_;
+ int start_;
     std::size_t search_position_;
     ReadHandler handler_;
   };
@@ -641,6 +660,16 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_until_delim_string_op<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncReadStream,
       typename Allocator, typename ReadHandler>
   inline void asio_handler_invoke(Function& function,
@@ -699,6 +728,7 @@
       : stream_(stream),
         streambuf_(streambuf),
         expr_(expr),
+ start_(0),
         search_position_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -709,6 +739,7 @@
       : stream_(other.stream_),
         streambuf_(other.streambuf_),
         expr_(other.expr_),
+ start_(other.start_),
         search_position_(other.search_position_),
         handler_(other.handler_)
     {
@@ -718,6 +749,7 @@
       : stream_(other.stream_),
         streambuf_(other.streambuf_),
         expr_(other.expr_),
+ start_(other.start_),
         search_position_(other.search_position_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -729,7 +761,7 @@
     {
       const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
       std::size_t bytes_to_read;
- switch (start)
+ switch (start_ = start)
       {
       case 1:
         for (;;)
@@ -812,6 +844,7 @@
     AsyncReadStream& stream_;
     boost::asio::basic_streambuf<Allocator>& streambuf_;
     RegEx expr_;
+ int start_;
     std::size_t search_position_;
     ReadHandler handler_;
   };
@@ -836,6 +869,17 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncReadStream, typename Allocator,
+ typename RegEx, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_until_expr_op<AsyncReadStream,
+ Allocator, RegEx, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncReadStream, typename Allocator,
       typename RegEx, typename ReadHandler>
   inline void asio_handler_invoke(Function& function,
@@ -894,6 +938,7 @@
       : stream_(stream),
         streambuf_(streambuf),
         match_condition_(match_condition),
+ start_(0),
         search_position_(0),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
     {
@@ -904,6 +949,7 @@
       : stream_(other.stream_),
         streambuf_(other.streambuf_),
         match_condition_(other.match_condition_),
+ start_(other.start_),
         search_position_(other.search_position_),
         handler_(other.handler_)
     {
@@ -913,6 +959,7 @@
       : stream_(other.stream_),
         streambuf_(other.streambuf_),
         match_condition_(other.match_condition_),
+ start_(other.start_),
         search_position_(other.search_position_),
         handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
     {
@@ -924,7 +971,7 @@
     {
       const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
       std::size_t bytes_to_read;
- switch (start)
+ switch (start_ = start)
       {
       case 1:
         for (;;)
@@ -1003,6 +1050,7 @@
     AsyncReadStream& stream_;
     boost::asio::basic_streambuf<Allocator>& streambuf_;
     MatchCondition match_condition_;
+ int start_;
     std::size_t search_position_;
     ReadHandler handler_;
   };
@@ -1027,6 +1075,17 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ inline bool asio_handler_is_continuation(
+ read_until_match_op<AsyncReadStream,
+ Allocator, MatchCondition, ReadHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncReadStream, typename Allocator,
       typename MatchCondition, typename ReadHandler>
   inline void asio_handler_invoke(Function& function,

Modified: trunk/boost/asio/impl/spawn.hpp
==============================================================================
--- trunk/boost/asio/impl/spawn.hpp (original)
+++ trunk/boost/asio/impl/spawn.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -18,6 +18,7 @@
 #include <boost/asio/detail/config.hpp>
 #include <boost/asio/async_result.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/noncopyable.hpp>
 #include <boost/asio/detail/shared_ptr.hpp>
@@ -111,6 +112,12 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename Handler, typename T>
+ inline bool asio_handler_is_continuation(coro_handler<Handler, T>*)
+ {
+ return true;
+ }
+
   template <typename Function, typename Handler, typename T>
   inline void asio_handler_invoke(Function& function,
       coro_handler<Handler, T>* this_handler)

Modified: trunk/boost/asio/impl/write.hpp
==============================================================================
--- trunk/boost/asio/impl/write.hpp (original)
+++ trunk/boost/asio/impl/write.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -23,6 +23,7 @@
 #include <boost/asio/detail/consuming_buffers.hpp>
 #include <boost/asio/detail/dependent_type.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/handler_type_requirements.hpp>
 #include <boost/asio/detail/throw_error.hpp>
@@ -140,6 +141,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -150,6 +152,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -159,6 +162,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -168,7 +172,7 @@
     void operator()(const boost::system::error_code& ec,
         std::size_t bytes_transferred, int start = 0)
     {
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         buffers_.prepare(this->check_for_completion(ec, total_transferred_));
@@ -193,6 +197,7 @@
     AsyncWriteStream& stream_;
     boost::asio::detail::consuming_buffers<
       const_buffer, ConstBufferSequence> buffers_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -212,6 +217,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffer_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -222,6 +228,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -231,6 +238,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -241,7 +249,7 @@
         std::size_t bytes_transferred, int start = 0)
     {
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -265,6 +273,7 @@
   //private:
     AsyncWriteStream& stream_;
     boost::asio::mutable_buffer buffer_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -284,6 +293,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffer_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -294,6 +304,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -303,6 +314,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -313,7 +325,7 @@
         std::size_t bytes_transferred, int start = 0)
     {
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -337,6 +349,7 @@
   //private:
     AsyncWriteStream& stream_;
     boost::asio::const_buffer buffer_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -354,6 +367,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -364,6 +378,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -373,6 +388,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -389,7 +405,7 @@
       std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
       std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -416,6 +432,7 @@
   //private:
     AsyncWriteStream& stream_;
     boost::array<Elem, 2> buffers_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -435,6 +452,7 @@
           CompletionCondition>(completion_condition),
         stream_(stream),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -445,6 +463,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -454,6 +473,7 @@
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -470,7 +490,7 @@
       std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
       std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -497,6 +517,7 @@
   //private:
     AsyncWriteStream& stream_;
     std::array<Elem, 2> buffers_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -523,6 +544,17 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline bool asio_handler_is_continuation(
+ write_op<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncWriteStream,
       typename ConstBufferSequence, typename CompletionCondition,
       typename WriteHandler>
@@ -652,6 +684,14 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename Allocator, typename WriteHandler>
+ inline bool asio_handler_is_continuation(
+ write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+ {
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename Allocator, typename WriteHandler>
   inline void asio_handler_invoke(Function& function,
       write_streambuf_handler<Allocator, WriteHandler>* this_handler)

Modified: trunk/boost/asio/impl/write_at.hpp
==============================================================================
--- trunk/boost/asio/impl/write_at.hpp (original)
+++ trunk/boost/asio/impl/write_at.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -23,6 +23,7 @@
 #include <boost/asio/detail/consuming_buffers.hpp>
 #include <boost/asio/detail/dependent_type.hpp>
 #include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_cont_helpers.hpp>
 #include <boost/asio/detail/handler_invoke_helpers.hpp>
 #include <boost/asio/detail/handler_type_requirements.hpp>
 #include <boost/asio/detail/throw_error.hpp>
@@ -151,6 +152,7 @@
         device_(device),
         offset_(offset),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -162,6 +164,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -172,6 +175,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -181,7 +185,7 @@
     void operator()(const boost::system::error_code& ec,
         std::size_t bytes_transferred, int start = 0)
     {
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         buffers_.prepare(this->check_for_completion(ec, total_transferred_));
@@ -208,6 +212,7 @@
     boost::uint64_t offset_;
     boost::asio::detail::consuming_buffers<
       const_buffer, ConstBufferSequence> buffers_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -228,6 +233,7 @@
         device_(device),
         offset_(offset),
         buffer_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -239,6 +245,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -249,6 +256,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -259,7 +267,7 @@
         std::size_t bytes_transferred, int start = 0)
     {
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -284,6 +292,7 @@
     AsyncRandomAccessWriteDevice& device_;
     boost::uint64_t offset_;
     boost::asio::mutable_buffer buffer_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -304,6 +313,7 @@
         device_(device),
         offset_(offset),
         buffer_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -315,6 +325,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -325,6 +336,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffer_(other.buffer_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -335,7 +347,7 @@
         std::size_t bytes_transferred, int start = 0)
     {
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -360,6 +372,7 @@
     AsyncRandomAccessWriteDevice& device_;
     boost::uint64_t offset_;
     boost::asio::const_buffer buffer_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -379,6 +392,7 @@
         device_(device),
         offset_(offset),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -390,6 +404,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -400,6 +415,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -416,7 +432,7 @@
       std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
       std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -445,6 +461,7 @@
     AsyncRandomAccessWriteDevice& device_;
     boost::uint64_t offset_;
     boost::array<Elem, 2> buffers_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -466,6 +483,7 @@
         device_(device),
         offset_(offset),
         buffers_(buffers),
+ start_(0),
         total_transferred_(0),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
     {
@@ -477,6 +495,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
@@ -487,6 +506,7 @@
         device_(other.device_),
         offset_(other.offset_),
         buffers_(other.buffers_),
+ start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
@@ -503,7 +523,7 @@
       std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
       std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
       std::size_t n = 0;
- switch (start)
+ switch (start_ = start)
       {
         case 1:
         n = this->check_for_completion(ec, total_transferred_);
@@ -532,6 +552,7 @@
     AsyncRandomAccessWriteDevice& device_;
     boost::uint64_t offset_;
     std::array<Elem, 2> buffers_;
+ int start_;
     std::size_t total_transferred_;
     WriteHandler handler_;
   };
@@ -558,6 +579,17 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline bool asio_handler_is_continuation(
+ write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename AsyncRandomAccessWriteDevice,
       typename ConstBufferSequence, typename CompletionCondition,
       typename WriteHandler>
@@ -703,6 +735,14 @@
         pointer, size, this_handler->handler_);
   }
 
+ template <typename Allocator, typename WriteHandler>
+ inline bool asio_handler_is_continuation(
+ write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
+ {
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
   template <typename Function, typename Allocator, typename WriteHandler>
   inline void asio_handler_invoke(Function& function,
       write_at_streambuf_op<Allocator, WriteHandler>* this_handler)

Modified: trunk/boost/asio/spawn.hpp
==============================================================================
--- trunk/boost/asio/spawn.hpp (original)
+++ trunk/boost/asio/spawn.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -62,7 +62,8 @@
 #else // defined(GENERATING_DOCUMENTATION)
 typedef basic_yield_context<
   detail::wrapped_handler<
- io_service::strand, void(*)()> > yield_context;
+ io_service::strand, void(*)(),
+ detail::is_continuation_if_running> > yield_context;
 #endif // defined(GENERATING_DOCUMENTATION)
 
 template <typename Handler, typename Function>

Modified: trunk/boost/asio/ssl/detail/io.hpp
==============================================================================
--- trunk/boost/asio/ssl/detail/io.hpp (original)
+++ trunk/boost/asio/ssl/detail/io.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -96,6 +96,7 @@
     : next_layer_(next_layer),
       core_(core),
       op_(op),
+ start_(0),
       bytes_transferred_(0),
       handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
   {
@@ -106,6 +107,7 @@
     : next_layer_(other.next_layer_),
       core_(other.core_),
       op_(other.op_),
+ start_(other.start_),
       want_(other.want_),
       ec_(other.ec_),
       bytes_transferred_(other.bytes_transferred_),
@@ -117,6 +119,7 @@
     : next_layer_(other.next_layer_),
       core_(other.core_),
       op_(other.op_),
+ start_(other.start_),
       want_(other.want_),
       ec_(other.ec_),
       bytes_transferred_(other.bytes_transferred_),
@@ -128,7 +131,7 @@
   void operator()(boost::system::error_code ec,
       std::size_t bytes_transferred = ~std::size_t(0), int start = 0)
   {
- switch (start)
+ switch (start_ = start)
     {
     case 1: // Called after at least one async operation.
       do
@@ -275,6 +278,7 @@
   Stream& next_layer_;
   stream_core& core_;
   Operation op_;
+ int start_;
   engine::want want_;
   boost::system::error_code ec_;
   std::size_t bytes_transferred_;
@@ -297,6 +301,14 @@
       pointer, size, this_handler->handler_);
 }
 
+template <typename Stream, typename Operation, typename Handler>
+inline bool asio_handler_is_continuation(
+ io_op<Stream, Operation, Handler>* this_handler)
+{
+ return this_handler->start_ == 0 ? true
+ : boost_asio_handler_cont_helpers::is_continuation(this_handler->handler_);
+}
+
 template <typename Function, typename Stream,
     typename Operation, typename Handler>
 inline void asio_handler_invoke(Function& function,

Modified: trunk/boost/asio/strand.hpp
==============================================================================
--- trunk/boost/asio/strand.hpp (original)
+++ trunk/boost/asio/strand.hpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -215,11 +215,23 @@
 #if defined(GENERATING_DOCUMENTATION)
   unspecified
 #else
- detail::wrapped_handler<strand, Handler>
+ detail::wrapped_handler<strand, Handler, detail::is_continuation_if_running>
 #endif
   wrap(Handler handler)
   {
- return detail::wrapped_handler<io_service::strand, Handler>(*this, handler);
+ return detail::wrapped_handler<io_service::strand, Handler,
+ detail::is_continuation_if_running>(*this, handler);
+ }
+
+ /// Determine whether the strand is running in the current thread.
+ /**
+ * @return @c true if the current thread is executing a handler that was
+ * submitted to the strand using post(), dispatch() or wrap(). Otherwise
+ * returns @c false.
+ */
+ bool running_in_this_thread() const
+ {
+ return service_.running_in_this_thread(impl_);
   }
 
 private:

Modified: trunk/libs/asio/test/strand.cpp
==============================================================================
--- trunk/libs/asio/test/strand.cpp (original)
+++ trunk/libs/asio/test/strand.cpp 2013-05-16 23:07:51 EDT (Thu, 16 May 2013)
@@ -32,6 +32,8 @@
 
 void increment_without_lock(strand* s, int* count)
 {
+ BOOST_CHECK(!s->running_in_this_thread());
+
   int original_count = *count;
 
   s->dispatch(boost::bind(increment, count));
@@ -43,6 +45,8 @@
 
 void increment_with_lock(strand* s, int* count)
 {
+ BOOST_CHECK(s->running_in_this_thread());
+
   int original_count = *count;
 
   s->dispatch(boost::bind(increment, count));


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk