Add prototype implementation of intermediate_storage trait.
diff --git a/asio/include/Makefile.am b/asio/include/Makefile.am
index b1f6cfd..6cd7cf1 100644
--- a/asio/include/Makefile.am
+++ b/asio/include/Makefile.am
@@ -342,6 +342,7 @@
 	asio/impl/use_future.hpp \
 	asio/impl/write_at.hpp \
 	asio/impl/write.hpp \
+	asio/intermediate_storage.hpp \
 	asio/io_context.hpp \
 	asio/io_context_strand.hpp \
 	asio/io_service.hpp \
diff --git a/asio/include/asio.hpp b/asio/include/asio.hpp
index 4b47b92..0428a55 100644
--- a/asio/include/asio.hpp
+++ b/asio/include/asio.hpp
@@ -65,6 +65,7 @@
 #include "asio/handler_continuation_hook.hpp"
 #include "asio/handler_invoke_hook.hpp"
 #include "asio/high_resolution_timer.hpp"
+#include "asio/intermediate_storage.hpp"
 #include "asio/io_context.hpp"
 #include "asio/io_context_strand.hpp"
 #include "asio/io_service.hpp"
diff --git a/asio/include/asio/basic_socket_acceptor.hpp b/asio/include/asio/basic_socket_acceptor.hpp
index 06af261..b9550b3 100644
--- a/asio/include/asio/basic_socket_acceptor.hpp
+++ b/asio/include/asio/basic_socket_acceptor.hpp
@@ -2376,6 +2376,14 @@
   basic_socket_acceptor& operator=(
       const basic_socket_acceptor&) ASIO_DELETED;
 
+#if defined(ASIO_WINDOWS_RUNTIME)
+  typedef detail::null_socket_service<Protocol> service_type;
+#elif defined(ASIO_HAS_IOCP)
+  typedef detail::win_iocp_socket_service<Protocol> service_type;
+#else
+  typedef detail::reactive_socket_service<Protocol> service_type;
+#endif
+
   class initiate_async_wait
   {
   public:
@@ -2413,6 +2421,13 @@
   public:
     typedef Executor executor_type;
 
+    template <typename AcceptHandler, typename Socket, typename>
+    struct intermediate_storage
+      : service_type::template async_accept_storage<
+          Socket, AcceptHandler, executor_type>
+    {
+    };
+
     explicit initiate_async_accept(basic_socket_acceptor* self)
       : self_(self)
     {
@@ -2447,6 +2462,14 @@
   public:
     typedef Executor executor_type;
 
+    template <typename MoveAcceptHandler,
+        typename Executor1, typename, typename>
+    struct intermediate_storage
+      : service_type::template async_move_accept_storage<
+          Executor1, MoveAcceptHandler, executor_type>
+    {
+    };
+
     explicit initiate_async_move_accept(basic_socket_acceptor* self)
       : self_(self)
     {
@@ -2476,16 +2499,7 @@
     basic_socket_acceptor* self_;
   };
 
-#if defined(ASIO_WINDOWS_RUNTIME)
-  detail::io_object_impl<
-    detail::null_socket_service<Protocol>, Executor> impl_;
-#elif defined(ASIO_HAS_IOCP)
-  detail::io_object_impl<
-    detail::win_iocp_socket_service<Protocol>, Executor> impl_;
-#else
-  detail::io_object_impl<
-    detail::reactive_socket_service<Protocol>, Executor> impl_;
-#endif
+  detail::io_object_impl<service_type, Executor> impl_;
 };
 
 } // namespace asio
diff --git a/asio/include/asio/basic_stream_socket.hpp b/asio/include/asio/basic_stream_socket.hpp
index e248006..ef26dd4 100644
--- a/asio/include/asio/basic_stream_socket.hpp
+++ b/asio/include/asio/basic_stream_socket.hpp
@@ -973,11 +973,26 @@
   }
 
 private:
+#if defined(ASIO_WINDOWS_RUNTIME)
+  typedef detail::null_socket_service<Protocol> service_type;
+#elif defined(ASIO_HAS_IOCP)
+  typedef detail::win_iocp_socket_service<Protocol> service_type;
+#else
+  typedef detail::reactive_socket_service<Protocol> service_type;
+#endif
+
   class initiate_async_send
   {
   public:
     typedef Executor executor_type;
 
+    template <typename WriteHandler, typename ConstBufferSequence, typename>
+    struct intermediate_storage
+      : service_type::template async_send_storage<
+          ConstBufferSequence, WriteHandler, executor_type>
+    {
+    };
+
     explicit initiate_async_send(basic_stream_socket* self)
       : self_(self)
     {
@@ -1012,6 +1027,13 @@
   public:
     typedef Executor executor_type;
 
+    template <typename ReadHandler, typename MutableBufferSequence, typename>
+    struct intermediate_storage
+      : service_type::template async_receive_storage<
+          MutableBufferSequence, ReadHandler, executor_type>
+    {
+    };
+
     explicit initiate_async_receive(basic_stream_socket* self)
       : self_(self)
     {
diff --git a/asio/include/asio/basic_waitable_timer.hpp b/asio/include/asio/basic_waitable_timer.hpp
index 635b668..00f3a6c 100644
--- a/asio/include/asio/basic_waitable_timer.hpp
+++ b/asio/include/asio/basic_waitable_timer.hpp
@@ -723,6 +723,14 @@
   public:
     typedef Executor executor_type;
 
+    template <typename WaitHandler>
+    struct intermediate_storage
+      : detail::deadline_timer_service<
+          detail::chrono_time_traits<Clock, WaitTraits> >::template
+            async_wait_storage<WaitHandler, executor_type>
+    {
+    };
+
     explicit initiate_async_wait(basic_waitable_timer* self)
       : self_(self)
     {
diff --git a/asio/include/asio/detail/deadline_timer_service.hpp b/asio/include/asio/detail/deadline_timer_service.hpp
index 28ee3e4..47494e9 100644
--- a/asio/include/asio/detail/deadline_timer_service.hpp
+++ b/asio/include/asio/detail/deadline_timer_service.hpp
@@ -225,6 +225,13 @@
     }
   }
 
+  // Storage required for an asynchronous wait.
+  template <typename Handler, typename IoExecutor>
+  struct async_wait_storage
+    : intermediate_storage<wait_handler<Handler, IoExecutor> >
+  {
+  };
+
   // Start an asynchronous wait on the timer.
   template <typename Handler, typename IoExecutor>
   void async_wait(implementation_type& impl,
diff --git a/asio/include/asio/detail/handler_work.hpp b/asio/include/asio/detail/handler_work.hpp
index 02528a7..da773b6 100644
--- a/asio/include/asio/detail/handler_work.hpp
+++ b/asio/include/asio/detail/handler_work.hpp
@@ -18,6 +18,7 @@
 #include "asio/detail/config.hpp"
 #include "asio/associated_executor.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/intermediate_storage.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -106,6 +107,15 @@
 };
 
 } // namespace detail
+
+template <typename Handler, typename IoExecutor, typename HandlerExecutor>
+struct intermediate_storage<
+  detail::handler_work<Handler, IoExecutor, HandlerExecutor> >
+    : intermediate_storage<HandlerExecutor, Handler,
+      typename associated_allocator<Handler>::type>
+{
+};
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/detail/reactive_socket_accept_op.hpp b/asio/include/asio/detail/reactive_socket_accept_op.hpp
index e4e5fd7..8e6b23e 100644
--- a/asio/include/asio/detail/reactive_socket_accept_op.hpp
+++ b/asio/include/asio/detail/reactive_socket_accept_op.hpp
@@ -223,6 +223,45 @@
 #endif // defined(ASIO_HAS_MOVE)
 
 } // namespace detail
+
+template <typename Socket, typename Protocol,
+    typename Handler, typename IoExecutor>
+struct intermediate_storage<
+    detail::reactive_socket_accept_op<
+      Socket, Protocol, Handler, IoExecutor> >
+  : intermediate_storage_union<
+      typename aligned_storage<
+        sizeof(detail::reactive_socket_accept_op<
+          Socket, Protocol, Handler, IoExecutor>)
+      >::type,
+      typename intermediate_storage<
+        detail::handler_work<Handler, IoExecutor>
+      >::type
+    >
+{
+};
+
+#if defined(ASIO_HAS_MOVE)
+
+template <typename Protocol, typename PeerIoExecutor,
+    typename Handler, typename IoExecutor>
+struct intermediate_storage<
+    detail::reactive_socket_move_accept_op<
+      Protocol, PeerIoExecutor, Handler, IoExecutor> >
+  : intermediate_storage_union<
+      typename aligned_storage<
+        sizeof(detail::reactive_socket_move_accept_op<
+          Protocol, PeerIoExecutor, Handler, IoExecutor>)
+      >::type,
+      typename intermediate_storage<
+        detail::handler_work<Handler, IoExecutor>
+      >::type
+    >
+{
+};
+
+#endif // defined(ASIO_HAS_MOVE)
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/detail/reactive_socket_recv_op.hpp b/asio/include/asio/detail/reactive_socket_recv_op.hpp
index 02e566e..56b6c23 100644
--- a/asio/include/asio/detail/reactive_socket_recv_op.hpp
+++ b/asio/include/asio/detail/reactive_socket_recv_op.hpp
@@ -130,6 +130,23 @@
 };
 
 } // namespace detail
+
+template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
+struct intermediate_storage<
+    detail::reactive_socket_recv_op<
+      MutableBufferSequence, Handler, IoExecutor> >
+  : intermediate_storage_union<
+      typename aligned_storage<
+        sizeof(detail::reactive_socket_recv_op<
+          MutableBufferSequence, Handler, IoExecutor>)
+      >::type,
+      typename intermediate_storage<
+        detail::handler_work<Handler, IoExecutor>
+      >::type
+    >
+{
+};
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/detail/reactive_socket_send_op.hpp b/asio/include/asio/detail/reactive_socket_send_op.hpp
index 4eab816..ea3d86b 100644
--- a/asio/include/asio/detail/reactive_socket_send_op.hpp
+++ b/asio/include/asio/detail/reactive_socket_send_op.hpp
@@ -129,6 +129,23 @@
 };
 
 } // namespace detail
+
+template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
+struct intermediate_storage<
+    detail::reactive_socket_send_op<
+      ConstBufferSequence, Handler, IoExecutor> >
+  : intermediate_storage_union<
+      typename aligned_storage<
+        sizeof(detail::reactive_socket_send_op<
+          ConstBufferSequence, Handler, IoExecutor>)
+      >::type,
+      typename intermediate_storage<
+        detail::handler_work<Handler, IoExecutor>
+      >::type
+    >
+{
+};
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/detail/reactive_socket_service.hpp b/asio/include/asio/detail/reactive_socket_service.hpp
index 2ed833c..b47733f 100644
--- a/asio/include/asio/detail/reactive_socket_service.hpp
+++ b/asio/include/asio/detail/reactive_socket_service.hpp
@@ -412,6 +412,15 @@
     return ec;
   }
 
+  // Storage required for an asynchronous accept.
+  template <typename Socket, typename Handler, typename IoExecutor>
+  struct async_accept_storage
+    : intermediate_storage<
+        reactive_socket_accept_op<
+          Socket, Protocol, Handler, IoExecutor> >
+  {
+  };
+
   // Start an asynchronous accept. The peer and peer_endpoint objects must be
   // valid until the accept's handler is invoked.
   template <typename Socket, typename Handler, typename IoExecutor>
@@ -436,6 +445,15 @@
   }
 
 #if defined(ASIO_HAS_MOVE)
+  // Storage required for an asynchronous move accept.
+  template <typename PeerIoExecutor, typename Handler, typename IoExecutor>
+  struct async_move_accept_storage
+    : intermediate_storage<
+        reactive_socket_move_accept_op<
+          Protocol, PeerIoExecutor, Handler, IoExecutor> >
+  {
+  };
+
   // Start an asynchronous accept. The peer_endpoint object must be valid until
   // the accept's handler is invoked.
   template <typename PeerIoExecutor, typename Handler, typename IoExecutor>
diff --git a/asio/include/asio/detail/reactive_socket_service_base.hpp b/asio/include/asio/detail/reactive_socket_service_base.hpp
index 0445b78..4da939f 100644
--- a/asio/include/asio/detail/reactive_socket_service_base.hpp
+++ b/asio/include/asio/detail/reactive_socket_service_base.hpp
@@ -254,6 +254,16 @@
     return 0;
   }
 
+  // Storage required for an asynchronous send.
+  template <typename ConstBufferSequence,
+      typename Handler, typename IoExecutor>
+  struct async_send_storage
+    : intermediate_storage<
+        reactive_socket_send_op<
+          ConstBufferSequence, Handler, IoExecutor> >
+  {
+  };
+
   // Start an asynchronous send. The data being sent must be valid for the
   // lifetime of the asynchronous operation.
   template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
@@ -326,6 +336,16 @@
     return 0;
   }
 
+  // Storage required for an asynchronous receive.
+  template <typename MutableBufferSequence,
+      typename Handler, typename IoExecutor>
+  struct async_receive_storage
+    : intermediate_storage<
+        reactive_socket_recv_op<
+          MutableBufferSequence, Handler, IoExecutor> >
+  {
+  };
+
   // Start an asynchronous receive. The buffer for the data being received
   // must be valid for the lifetime of the asynchronous operation.
   template <typename MutableBufferSequence,
diff --git a/asio/include/asio/detail/type_traits.hpp b/asio/include/asio/detail/type_traits.hpp
index 0f7ee6e..b797620 100644
--- a/asio/include/asio/detail/type_traits.hpp
+++ b/asio/include/asio/detail/type_traits.hpp
@@ -21,6 +21,7 @@
 # include <type_traits>
 #else // defined(ASIO_HAS_TYPE_TRAITS)
 # include <boost/type_traits/add_const.hpp>
+# include <boost/type_traits/aligned_storage.hpp>
 # include <boost/type_traits/conditional.hpp>
 # include <boost/type_traits/decay.hpp>
 # include <boost/type_traits/integral_constant.hpp>
@@ -41,6 +42,7 @@
 
 #if defined(ASIO_HAS_STD_TYPE_TRAITS)
 using std::add_const;
+using std::aligned_storage;
 using std::conditional;
 using std::decay;
 using std::declval;
@@ -65,6 +67,7 @@
 using std::true_type;
 #else // defined(ASIO_HAS_STD_TYPE_TRAITS)
 using boost::add_const;
+using boost::aligned_storage;
 template <bool Condition, typename Type = void>
 struct enable_if : boost::enable_if_c<Condition, Type> {};
 using boost::conditional;
diff --git a/asio/include/asio/detail/wait_handler.hpp b/asio/include/asio/detail/wait_handler.hpp
index be49a96..fa33de9 100644
--- a/asio/include/asio/detail/wait_handler.hpp
+++ b/asio/include/asio/detail/wait_handler.hpp
@@ -80,6 +80,20 @@
 };
 
 } // namespace detail
+
+template <typename Handler, typename IoExecutor>
+struct intermediate_storage<detail::wait_handler<Handler, IoExecutor> >
+  : intermediate_storage_union<
+      typename aligned_storage<
+        sizeof(detail::wait_handler<Handler, IoExecutor>)
+      >::type,
+      typename intermediate_storage<
+        detail::handler_work<Handler, IoExecutor>
+      >::type
+    >
+{
+};
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/detail/work_dispatcher.hpp b/asio/include/asio/detail/work_dispatcher.hpp
index 243b8e4..ddfd13a 100644
--- a/asio/include/asio/detail/work_dispatcher.hpp
+++ b/asio/include/asio/detail/work_dispatcher.hpp
@@ -19,6 +19,7 @@
 #include "asio/associated_executor.hpp"
 #include "asio/associated_allocator.hpp"
 #include "asio/executor_work_guard.hpp"
+#include "asio/intermediate_storage.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -66,6 +67,15 @@
 };
 
 } // namespace detail
+
+template <typename Handler>
+struct intermediate_storage<detail::work_dispatcher<Handler> >
+{
+  typedef typename intermediate_storage<
+    typename associated_executor<Handler>::type, Handler,
+      typename associated_allocator<Handler>::type>::type type;
+};
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/impl/io_context.hpp b/asio/include/asio/impl/io_context.hpp
index 2db6f15..9c6885a 100644
--- a/asio/include/asio/impl/io_context.hpp
+++ b/asio/include/asio/impl/io_context.hpp
@@ -24,6 +24,7 @@
 #include "asio/detail/service_registry.hpp"
 #include "asio/detail/throw_error.hpp"
 #include "asio/detail/type_traits.hpp"
+#include "asio/intermediate_storage.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -346,6 +347,14 @@
   return static_cast<asio::io_context&>(context());
 }
 
+template <typename Function, typename Allocator>
+struct intermediate_storage<io_context::executor_type, Function, Allocator>
+  : aligned_storage<
+      sizeof(detail::executor_op<typename decay<Function>::type,
+        typename decay<Allocator>::type, detail::operation>)>
+{
+};
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/impl/post.hpp b/asio/include/asio/impl/post.hpp
index 1e7d589..fb33cbf 100644
--- a/asio/include/asio/impl/post.hpp
+++ b/asio/include/asio/impl/post.hpp
@@ -77,6 +77,42 @@
 
 } // namespace detail
 
+template <typename CompletionHandler>
+struct intermediate_storage<detail::initiate_post, CompletionHandler>
+{
+  typedef typename intermediate_storage<
+    typename associated_executor<
+      typename decay<CompletionHandler>::type
+    >::type,
+    CompletionHandler,
+    typename associated_allocator<
+      typename decay<CompletionHandler>::type
+    >::type
+  >::type type;
+};
+
+template <typename Executor, typename CompletionHandler>
+struct intermediate_storage<
+    detail::initiate_post_with_executor<Executor>, CompletionHandler>
+{
+ typedef typename intermediate_storage_union<
+   typename intermediate_storage<
+     Executor,
+     detail::work_dispatcher<
+       typename decay<CompletionHandler>::type
+     >,
+     typename associated_allocator<
+       typename decay<CompletionHandler>::type
+     >::type
+   >::type,
+   typename intermediate_storage<
+     detail::work_dispatcher<
+       typename decay<CompletionHandler>::type
+     >
+   >::type
+ >::type type;
+};
+
 template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>
 ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(
     ASIO_MOVE_ARG(CompletionToken) token)
diff --git a/asio/include/asio/impl/system_executor.hpp b/asio/include/asio/impl/system_executor.hpp
index d7dc2c8..c600a9d 100644
--- a/asio/include/asio/impl/system_executor.hpp
+++ b/asio/include/asio/impl/system_executor.hpp
@@ -19,6 +19,7 @@
 #include "asio/detail/global.hpp"
 #include "asio/detail/recycling_allocator.hpp"
 #include "asio/detail/type_traits.hpp"
+#include "asio/intermediate_storage.hpp"
 #include "asio/system_context.hpp"
 
 #include "asio/detail/push_options.hpp"
@@ -78,6 +79,14 @@
   p.v = p.p = 0;
 }
 
+template <typename Function, typename Allocator>
+struct intermediate_storage<system_executor, Function, Allocator>
+  : aligned_storage<
+      sizeof(detail::executor_op<typename decay<Function>::type,
+        typename decay<Allocator>::type>)>
+{
+};
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/intermediate_storage.hpp b/asio/include/asio/intermediate_storage.hpp
new file mode 100644
index 0000000..c098260
--- /dev/null
+++ b/asio/include/asio/intermediate_storage.hpp
@@ -0,0 +1,130 @@
+//
+// intermediate_storage.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 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_INTERMEDIATE_STORAGE_HPP
+#define ASIO_INTERMEDIATE_STORAGE_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/type_traits.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename>
+struct intermediate_storage_check
+{
+  typedef void type;
+};
+
+template <typename T, typename Args, typename = void>
+struct intermediate_storage_impl
+{
+  typedef void type;
+};
+
+template <typename T, typename... Args>
+struct intermediate_storage_impl<T, void(Args...),
+  typename intermediate_storage_check<
+    typename T::template intermediate_storage<Args...>::type>::type>
+{
+  typedef typename T::template intermediate_storage<Args...>::type type;
+};
+
+} // namespace detail
+
+#if defined(GENERATING_DOCUMENTATION)
+
+/// Traits type used to determine the storage requirements of an operation.
+/**
+ * A program may specialise this traits type if the @c T template parameter in
+ * the specialisation is a user-defined type.
+ *
+ * Specialisations of this trait may provide a nested typedef @c type, which is
+ * a trivial standard-layout type suitable for use as uninitialised storage by
+ * the operation initiated by the type @c T. If the operation has no fixed-size
+ * storage requirement, this type is @c void.
+ */
+template <typename T, typename... Args>
+struct intermediate_storage
+{
+  /// If @c T has a nested class template @c intermediate_storage such that
+  /// <tt>T::template intermediate_storage<Args...>::type</tt> is a valid type,
+  /// <tt>T::intermediate_storage<Args...>::type</tt. Otherwise the typedef
+  /// @c type is @c void.
+  typedef see_below type;
+};
+#else
+template <typename T, typename... Args>
+struct intermediate_storage
+  : detail::intermediate_storage_impl<T, void(Args...)>
+{
+};
+#endif
+
+#if defined(ASIO_HAS_ALIAS_TEMPLATES)
+
+template <typename T, typename... Args>
+using intermediate_storage_t = typename intermediate_storage<T, Args...>::type;
+
+#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)
+
+/// Determine the appropriate intermediate storage type as a union of types.
+/**
+ * This helper template automatically determines the correct intermediate
+ * storage type as a union of two other types. If either or both of those
+ * types are void, then the "union" type is also void.
+ */
+template <typename T, typename U>
+struct intermediate_storage_union
+{
+#if defined(GENERATING_DOCUMENTATION)
+  /// If either of T or U are void, void. Otherwise a suitable union storage
+  /// type.
+  typedef see_below type;
+#else // defined(GENERATING_DOCUMENTATION)
+  union type
+  {
+    T t;
+    U u;
+  };
+#endif // defined(GENERATING_DOCUMENTATION)
+};
+
+#if !defined(GENERATING_DOCUMENTATION)
+template <typename T>
+struct intermediate_storage_union<T, void>
+{
+  typedef void type;
+};
+
+template <typename U>
+struct intermediate_storage_union<void, U>
+{
+  typedef void type;
+};
+
+template <>
+struct intermediate_storage_union<void, void>
+{
+  typedef void type;
+};
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_INTERMEDIATE_STORAGE_HPP
diff --git a/asio/include/asio/use_await.hpp b/asio/include/asio/use_await.hpp
index d9095a6..7aa69e4 100644
--- a/asio/include/asio/use_await.hpp
+++ b/asio/include/asio/use_await.hpp
@@ -71,53 +71,121 @@
 template <typename R, typename... Args>
 class async_result<use_await_t, R(Args...)>
 {
+private:
+  template <typename Initiation, typename... InitArgs>
+  struct awaitable
+  {
+    template <typename T>
+    class allocator;
+
+    struct handler
+    {
+      typedef allocator<void> allocator_type;
+
+      allocator_type get_allocator() const
+      {
+        return allocator_type(awaitable_);
+      }
+
+      void operator()(Args... results)
+      {
+        std::tuple<Args...> result(std::move(results)...);
+        awaitable_->result_ = &result;
+        awaitable_->owner_.resume();
+      }
+
+      awaitable* awaitable_; // The handler has no ownership of the coroutine.
+    };
+
+    using storage_type = intermediate_storage_t<
+        Initiation, handler, InitArgs...>;
+
+    template <typename T>
+    class allocator
+    {
+    public:
+      typedef T value_type;
+
+      explicit allocator(awaitable* a) noexcept
+        : awaitable_(a)
+      {
+      }
+
+      template <typename U>
+      allocator(const allocator<U>& a) noexcept
+        : awaitable_(a.awaitable_)
+      {
+      }
+
+      T* allocate(std::size_t n)
+      {
+        if constexpr (std::is_same_v<storage_type, void>)
+        {
+          return static_cast<T*>(::operator new(sizeof(T) * n));
+        }
+        else
+        {
+          return static_cast<T*>(static_cast<void*>(&awaitable_->storage_));
+        }
+      }
+
+      void deallocate(T* p, std::size_t)
+      {
+        if constexpr (std::is_same_v<storage_type, void>)
+        {
+          ::operator delete(p);
+        }
+      }
+
+    private:
+      template <typename> friend class allocator;
+      awaitable* awaitable_;
+    };
+
+    bool await_ready() const noexcept
+    {
+      return false;
+    }
+
+    void await_suspend(std::experimental::coroutine_handle<> h) noexcept
+    {
+      owner_ = h;
+      std::apply(
+          [&](auto&&... a)
+          {
+            initiation_(handler{this}, std::forward<decltype(a)>(a)...);
+          },
+          init_args_
+        );
+    }
+
+    std::tuple<Args...> await_resume()
+    {
+      return std::move(*static_cast<std::tuple<Args...>*>(result_));
+    }
+
+    Initiation initiation_;
+    std::tuple<InitArgs...> init_args_;
+    std::experimental::coroutine_handle<> owner_ = nullptr;
+    void* result_ = nullptr;
+    std::conditional_t<
+        std::is_same_v<storage_type, void>,
+        char, storage_type> storage_{};
+  };
+
 public:
   template <typename Initiation, typename... InitArgs>
   static auto initiate(Initiation initiation,
       use_await_t, InitArgs... init_args)
   {
-    struct awaitable
-    {
-      Initiation initiation_;
-      std::tuple<InitArgs...> init_args_;
-      void* result_ = nullptr;
-
-      bool await_ready() const noexcept
-      {
-        return false;
-      }
-
-      void await_suspend(std::experimental::coroutine_handle<> h) noexcept
-      {
-        std::apply(
-            [&](auto&&... a)
-            {
-              initiation_(
-                  [this, h](Args... results) mutable
-                  {
-                    std::tuple<Args...> result(std::move(results)...);
-                    result_ = &result;
-                    h.resume();
-                  },
-                  std::forward<decltype(a)>(a)...
-                );
-            },
-            init_args_
-          );
-      }
-
-      std::tuple<Args...> await_resume()
-      {
-        return std::move(*static_cast<std::tuple<Args...>*>(result_));
-      }
-    };
-
-    return awaitable{std::move(initiation),
+    return awaitable<Initiation, InitArgs...>{
+        std::move(initiation),
         std::forward_as_tuple(std::move(init_args)...)};
   }
 };
 
-/// A completion token object that indicates that an Awaitable should be returned.
+/// A completion token object that indicates that an Awaitable should be
+/// returned.
 #if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
 constexpr use_await_t use_await;
 #elif defined(ASIO_MSVC)