Add first cut of new handler_traits.
diff --git a/asio/include/Makefile.am b/asio/include/Makefile.am
index 4b81b3d..37679d8 100644
--- a/asio/include/Makefile.am
+++ b/asio/include/Makefile.am
@@ -58,6 +58,7 @@
 	asio/detail/handler_alloc_helpers.hpp \
 	asio/detail/handler_invoke_helpers.hpp \
 	asio/detail/handler_tracking.hpp \
+	asio/detail/handler_traits.hpp \
 	asio/detail/handler_type_requirements.hpp \
 	asio/detail/hash_map.hpp \
 	asio/detail/impl/descriptor_ops.ipp \
@@ -219,6 +220,7 @@
 	asio/error.hpp \
 	asio/handler_alloc_hook.hpp \
 	asio/handler_invoke_hook.hpp \
+	asio/handler_traits.hpp \
 	asio.hpp \
 	asio/impl/connect.hpp \
 	asio/impl/error_code.ipp \
diff --git a/asio/include/asio.hpp b/asio/include/asio.hpp
index 398fbeb..4182bad 100644
--- a/asio/include/asio.hpp
+++ b/asio/include/asio.hpp
@@ -44,6 +44,7 @@
 #include "asio/error_code.hpp"
 #include "asio/handler_alloc_hook.hpp"
 #include "asio/handler_invoke_hook.hpp"
+#include "asio/handler_traits.hpp"
 #include "asio/io_service.hpp"
 #include "asio/ip/address.hpp"
 #include "asio/ip/address_v4.hpp"
diff --git a/asio/include/asio/detail/completion_handler.hpp b/asio/include/asio/detail/completion_handler.hpp
index 628b712..2a2aa79 100644
--- a/asio/include/asio/detail/completion_handler.hpp
+++ b/asio/include/asio/detail/completion_handler.hpp
@@ -17,9 +17,8 @@
 
 #include "asio/detail/config.hpp"
 #include "asio/detail/fenced_block.hpp"
-#include "asio/detail/handler_alloc_helpers.hpp"
-#include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/operation.hpp"
+#include "asio/handler_traits.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -62,7 +61,8 @@
     {
       asio::detail::fenced_block b;
       ASIO_HANDLER_INVOCATION_BEGIN(());
-      asio_handler_invoke_helpers::invoke(handler, handler);
+      ptr::traits_type::get_invoker(handler).invoke(
+          ASIO_MOVE_CAST(Handler)(handler));
       ASIO_HANDLER_INVOCATION_END;
     }
   }
diff --git a/asio/include/asio/detail/deadline_timer_service.hpp b/asio/include/asio/detail/deadline_timer_service.hpp
index 6eb0434..3cca342 100644
--- a/asio/include/asio/detail/deadline_timer_service.hpp
+++ b/asio/include/asio/detail/deadline_timer_service.hpp
@@ -182,8 +182,7 @@
     // Allocate and construct an operation to wrap the handler.
     typedef wait_handler<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
-      asio_handler_alloc_helpers::allocate(
-        sizeof(op), handler), 0 };
+      op::ptr::allocate(handler), 0 };
     p.p = new (p.v) op(handler);
 
     impl.might_have_pending_waits = true;
diff --git a/asio/include/asio/detail/handler_alloc_helpers.hpp b/asio/include/asio/detail/handler_alloc_helpers.hpp
index 9ae80de..0f70626 100644
--- a/asio/include/asio/detail/handler_alloc_helpers.hpp
+++ b/asio/include/asio/detail/handler_alloc_helpers.hpp
@@ -17,6 +17,7 @@
 
 #include "asio/detail/config.hpp"
 #include <boost/detail/workaround.hpp>
+#include <boost/limits.hpp>
 #include <boost/utility/addressof.hpp>
 #include "asio/detail/noncopyable.hpp"
 #include "asio/handler_alloc_hook.hpp"
@@ -54,31 +55,131 @@
 
 } // namespace asio_handler_alloc_helpers
 
-#define ASIO_DEFINE_HANDLER_PTR(op) \
-  struct ptr \
-  { \
-    Handler* h; \
-    void* v; \
-    op* p; \
-    ~ptr() \
-    { \
-      reset(); \
-    } \
-    void reset() \
-    { \
-      if (p) \
-      { \
-        p->~op(); \
-        p = 0; \
-      } \
-      if (v) \
-      { \
-        asio_handler_alloc_helpers::deallocate(v, sizeof(op), *h); \
-        v = 0; \
-      } \
-    } \
-  } \
-  /**/
+namespace asio {
+namespace detail {
+
+// The default allocator simply forwards to the old-style allocation hook.
+template <typename T, typename Context>
+class default_handler_allocator
+{
+public:
+  typedef T value_type;
+  typedef value_type* pointer;
+  typedef const value_type* const_pointer;
+  typedef value_type& reference;
+  typedef const value_type& const_reference;
+  typedef std::size_t size_type;
+  typedef std::ptrdiff_t difference_type;
+
+  template <typename U>
+  struct rebind
+  {
+    typedef default_handler_allocator<U, Context> other;
+  };
+
+  explicit default_handler_allocator(Context* context)
+    : context_(context)
+  {
+  }
+
+  template <typename U>
+  default_handler_allocator(const default_handler_allocator<U, Context>& other)
+    : context_(other.context_)
+  {
+  }
+
+  static pointer address(reference r)
+  {
+    return &r;
+  }
+
+  static const_pointer address(const_reference r)
+  {
+    return &r;
+  }
+
+  static size_type max_size()
+  {
+    return (std::numeric_limits<size_type>::max)();
+  }
+
+  static void construct(const pointer p, const value_type& v)
+  {
+    new (p) T(v);
+  }
+
+  static void destroy(const pointer p)
+  {
+    p->~T();
+  }
+
+  bool operator==(const default_handler_allocator& other) const
+  {
+    return context_ == other.context_;
+  }
+
+  bool operator!=(const default_handler_allocator& other) const
+  {
+    return context_ != other.context_;
+  }
+
+  pointer allocate(size_type n, const void* = 0)
+  {
+    return static_cast<pointer>(
+        asio_handler_alloc_helpers::allocate(n * sizeof(T), *context_));
+  }
+
+  void deallocate(pointer p, size_type n)
+  {
+    return asio_handler_alloc_helpers::deallocate(p, n * sizeof(T), *context_);
+  }
+
+//private:
+  Context* context_;
+};
+
+// The default allocator specialised for void.
+template <typename Context>
+class default_handler_allocator<void, Context>
+{
+public:
+  typedef void value_type;
+  typedef void* pointer;
+  typedef const void* const_pointer;
+
+  template <typename U>
+  struct rebind
+  {
+    typedef default_handler_allocator<U, Context> other;
+  };
+
+  explicit default_handler_allocator(Context* context)
+    : context_(context)
+  {
+  }
+
+  template <typename U>
+  default_handler_allocator(const default_handler_allocator<U, Context>& other)
+    : context_(other.context_)
+  {
+  }
+
+  bool operator==(const default_handler_allocator& other) const
+  {
+    return context_ == other.context_;
+  }
+
+  bool operator!=(const default_handler_allocator& other) const
+  {
+    return context_ != other.context_;
+  }
+
+//private:
+  Context* context_;
+};
+
+} // namespace detail
+} // namespace asio
 
 #include "asio/detail/pop_options.hpp"
 
diff --git a/asio/include/asio/detail/handler_invoke_helpers.hpp b/asio/include/asio/detail/handler_invoke_helpers.hpp
index 5b122d9..2b30079 100644
--- a/asio/include/asio/detail/handler_invoke_helpers.hpp
+++ b/asio/include/asio/detail/handler_invoke_helpers.hpp
@@ -42,6 +42,32 @@
 
 } // namespace asio_handler_invoke_helpers
 
+namespace asio {
+namespace detail {
+
+// The default invoker simply forwards to the old-style invocation hook.
+template <typename Context>
+class default_handler_invoker
+{
+public:
+  explicit default_handler_invoker(Context* context)
+    : context_(context)
+  {
+  }
+
+  template <typename Function>
+  void invoke(Function function)
+  {
+    asio_handler_invoke_helpers::invoke(function, *context_);
+  }
+
+private:
+  Context* context_;
+};
+
+} // namespace detail
+} // namespace asio
+
 #include "asio/detail/pop_options.hpp"
 
 #endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
diff --git a/asio/include/asio/detail/handler_traits.hpp b/asio/include/asio/detail/handler_traits.hpp
new file mode 100644
index 0000000..778664c
--- /dev/null
+++ b/asio/include/asio/detail/handler_traits.hpp
@@ -0,0 +1,160 @@
+//
+// detail/handler_traits.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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 ASIO_DETAIL_HANDLER_TRAITS_HPP
+#define ASIO_DETAIL_HANDLER_TRAITS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+// Type trait for determining whether a handler has an invoker_type typedef.
+
+char (&invoker_type_test(...))[2];
+
+template <typename T> char invoker_type_test(
+    T*, typename T::invoker_type* = 0);
+
+template <typename T>
+struct has_invoker_type
+{
+  enum { value = (sizeof((invoker_type_test)(static_cast<T*>(0))) == 1) };
+};
+
+// Type trait for determining whether a handler has an allocator_type typedef.
+
+char (&allocator_type_test(...))[2];
+
+template <typename T> char allocator_type_test(
+    T*, typename T::allocator_type* = 0);
+
+template <typename T>
+struct has_allocator_type
+{
+  enum { value = (sizeof((allocator_type_test)(static_cast<T*>(0))) == 1) };
+};
+
+// Traits base class for selectively forwarding the invoker typedef and
+// accessor function to the handler class.
+
+template <typename Handler, bool HasInvoker = has_invoker_type<Handler>::value>
+struct handler_traits_invoker;
+
+template <typename Handler>
+struct handler_traits_invoker<Handler, true>
+{
+  typedef typename Handler::invoker_type invoker_type;
+
+  static invoker_type get_invoker(Handler& handler)
+  {
+    return handler.get_invoker();
+  }
+};
+
+template <typename Handler>
+struct handler_traits_invoker<Handler, false>
+{
+  typedef default_handler_invoker<Handler> invoker_type;
+
+  static invoker_type get_invoker(Handler& handler)
+  {
+    return invoker_type(boost::addressof(handler));
+  }
+};
+
+// Traits base class for selectively forwarding the allocator typedef and
+// accessor function to the handler class.
+
+template <typename Handler, bool HasAllocator = has_allocator_type<Handler>::value>
+struct handler_traits_allocator;
+
+template <typename Handler>
+struct handler_traits_allocator<Handler, true>
+{
+  typedef typename Handler::allocator_type allocator_type;
+
+  static allocator_type get_allocator(Handler& handler)
+  {
+    return handler.get_allocator();
+  }
+};
+
+template <typename Handler>
+struct handler_traits_allocator<Handler, false>
+{
+  typedef default_handler_allocator<void, Handler> allocator_type;
+
+  static allocator_type get_allocator(Handler& handler)
+  {
+    return allocator_type(boost::addressof(handler));
+  }
+};
+
+// The default handler traits.
+
+template <typename Handler>
+struct handler_traits :
+  handler_traits_invoker<Handler>,
+  handler_traits_allocator<Handler>
+{
+};
+
+} // namespace detail
+} // namespace asio
+
+#define ASIO_DEFINE_HANDLER_PTR(op) \
+  struct ptr \
+  { \
+    typedef asio::handler_traits<Handler> traits_type; \
+    typedef typename traits_type::allocator_type any_allocator_type; \
+    typedef typename any_allocator_type::template rebind< \
+        op>::other allocator_type; \
+    Handler* h; \
+    void* v; \
+    op* p; \
+    static op* allocate(Handler& handler) \
+    { \
+      allocator_type allocator = traits_type::get_allocator(handler); \
+      return allocator.allocate(1); \
+    } \
+    ~ptr() \
+    { \
+      reset(); \
+    } \
+    void reset() \
+    { \
+      if (p) \
+      { \
+        p->~op(); \
+        p = 0; \
+      } \
+      if (v) \
+      { \
+        allocator_type allocator = traits_type::get_allocator(*h); \
+        allocator.deallocate(static_cast<op*>(v), 1); \
+        v = 0; \
+      } \
+    } \
+  } \
+  /**/
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_HANDLER_TRAITS_HPP
diff --git a/asio/include/asio/detail/impl/task_io_service.hpp b/asio/include/asio/detail/impl/task_io_service.hpp
index bd0cd25..59bb96e 100644
--- a/asio/include/asio/detail/impl/task_io_service.hpp
+++ b/asio/include/asio/detail/impl/task_io_service.hpp
@@ -18,8 +18,7 @@
 #include "asio/detail/call_stack.hpp"
 #include "asio/detail/completion_handler.hpp"
 #include "asio/detail/fenced_block.hpp"
-#include "asio/detail/handler_alloc_helpers.hpp"
-#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/handler_traits.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -39,8 +38,7 @@
     // Allocate and construct an operation to wrap the handler.
     typedef completion_handler<Handler> op;
     typename op::ptr p = { boost::addressof(handler),
-      asio_handler_alloc_helpers::allocate(
-        sizeof(op), handler), 0 };
+      op::ptr::allocate(handler), 0 };
     p.p = new (p.v) op(handler);
 
     ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
@@ -56,8 +54,7 @@
   // Allocate and construct an operation to wrap the handler.
   typedef completion_handler<Handler> op;
   typename op::ptr p = { boost::addressof(handler),
-    asio_handler_alloc_helpers::allocate(
-      sizeof(op), handler), 0 };
+    op::ptr::allocate(handler), 0 };
   p.p = new (p.v) op(handler);
 
   ASIO_HANDLER_CREATION((p.p, "io_service", this, "post"));
diff --git a/asio/include/asio/detail/wait_handler.hpp b/asio/include/asio/detail/wait_handler.hpp
index a5e152c..56eee10 100644
--- a/asio/include/asio/detail/wait_handler.hpp
+++ b/asio/include/asio/detail/wait_handler.hpp
@@ -32,9 +32,9 @@
 public:
   ASIO_DEFINE_HANDLER_PTR(wait_handler);
 
-  wait_handler(Handler h)
+  wait_handler(Handler& h)
     : timer_op(&wait_handler::do_complete),
-      handler_(h)
+      handler_(ASIO_MOVE_CAST(Handler)(h))
   {
   }
 
@@ -53,8 +53,8 @@
     // with the handler. Consequently, a local copy of the handler is required
     // to ensure that any owning sub-object remains valid until after we have
     // deallocated the memory here.
-    detail::binder1<Handler, asio::error_code>
-      handler(h->handler_, h->ec_);
+    typedef detail::binder1<Handler, asio::error_code> binder;
+    binder handler(h->handler_, h->ec_);
     p.h = boost::addressof(handler.handler_);
     p.reset();
 
@@ -63,7 +63,8 @@
     {
       asio::detail::fenced_block b;
       ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
-      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+      ptr::traits_type::get_invoker(handler.handler_).invoke(
+          ASIO_MOVE_CAST(binder)(handler));
       ASIO_HANDLER_INVOCATION_END;
     }
   }
diff --git a/asio/include/asio/handler_traits.hpp b/asio/include/asio/handler_traits.hpp
new file mode 100644
index 0000000..3b81ef6
--- /dev/null
+++ b/asio/include/asio/handler_traits.hpp
@@ -0,0 +1,35 @@
+//
+// handler_traits.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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 ASIO_HANDLER_TRAITS_HPP
+#define ASIO_HANDLER_TRAITS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/handler_traits.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename Handler>
+struct handler_traits
+  : asio::detail::handler_traits<Handler>
+{
+};
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_HANDLER_TRAITS_HPP