Add use_await.as_default_on() helper.
diff --git a/asio/include/asio/use_await.hpp b/asio/include/asio/use_await.hpp
index 299f1e5..d9095a6 100644
--- a/asio/include/asio/use_await.hpp
+++ b/asio/include/asio/use_await.hpp
@@ -23,12 +23,50 @@
#include <tuple>
#include <utility>
#include "asio/async_result.hpp"
+#include "asio/is_executor.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
-struct use_await_t {};
+struct use_await_t
+{
+ template <typename InnerExecutor>
+ struct executor_with_default : InnerExecutor
+ {
+ typedef use_await_t default_completion_token_type;
+
+ executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT
+ : InnerExecutor(ex)
+ {
+ }
+ };
+
+ template <typename T>
+ struct as_default_on_t
+ {
+ typedef typename T::template rebind_executor<
+ executor_with_default<typename T::executor_type> >::other type;
+ };
+
+ template <typename T>
+ static typename as_default_on_t<typename decay<T>::type>::type
+ as_default_on(ASIO_MOVE_ARG(T) object)
+ {
+ return typename as_default_on_t<typename decay<T>::type>::type(
+ ASIO_MOVE_CAST(T)(object));
+ }
+};
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename InnerExecutor>
+struct is_executor<use_await_t::executor_with_default<InnerExecutor> >
+ : is_executor<InnerExecutor>
+{
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
template <typename R, typename... Args>
class async_result<use_await_t, R(Args...)>
diff --git a/asio/src/examples/cpp17/coroutines_ts/use_await_as_default.cpp b/asio/src/examples/cpp17/coroutines_ts/use_await_as_default.cpp
new file mode 100644
index 0000000..a234f8f
--- /dev/null
+++ b/asio/src/examples/cpp17/coroutines_ts/use_await_as_default.cpp
@@ -0,0 +1,149 @@
+//
+// use_await.cpp
+// ~~~~~~~~~~~~~
+//
+// 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)
+//
+
+#include <atomic>
+#include <experimental/coroutine>
+#include <new>
+#include <tuple>
+#include <type_traits>
+
+//------------------------------------------------------------------------------
+
+class simple_coro
+{
+public:
+ simple_coro(const simple_coro&) = delete;
+ simple_coro& operator=(const simple_coro&) = delete;
+
+ explicit simple_coro(std::experimental::coroutine_handle<> coro)
+ : coro_(coro)
+ {
+ }
+
+ simple_coro(simple_coro&& other) noexcept
+ : coro_(std::exchange(other.coro_, nullptr))
+ {
+ }
+
+ simple_coro& operator=(simple_coro&& other) noexcept
+ {
+ simple_coro tmp(std::move(other));
+ std::swap(coro_, tmp.coro_);
+ return *this;
+ }
+
+ ~simple_coro()
+ {
+ if (coro_)
+ coro_.destroy();
+ }
+
+ void resume()
+ {
+ coro_.resume();
+ }
+
+private:
+ std::experimental::coroutine_handle<> coro_;
+};
+
+struct simple_promise
+{
+ simple_coro get_return_object()
+ {
+ return simple_coro{std::experimental::coroutine_handle<simple_promise>::from_promise(*this)};
+ };
+
+ auto initial_suspend()
+ {
+ return std::experimental::suspend_always();
+ }
+
+ auto final_suspend()
+ {
+ return std::experimental::suspend_always();
+ }
+
+ void return_void()
+ {
+ }
+
+ void unhandled_exception()
+ {
+ std::terminate();
+ }
+};
+
+namespace std { namespace experimental {
+
+template <typename... Args>
+struct coroutine_traits<simple_coro, Args...>
+{
+ using promise_type = simple_promise;
+};
+
+}} // namespace std::experimental
+
+//------------------------------------------------------------------------------
+
+#include <asio/ts/net.hpp>
+#include <asio/signal_set.hpp>
+#include <asio/use_await.hpp>
+#include <list>
+#include <iostream>
+
+using asio::ip::tcp;
+using asio::use_await;
+
+simple_coro listener(asio::io_context& ctx)
+{
+ auto acceptor = use_await.as_default_on(tcp::acceptor(ctx, {tcp::v4(), 54321}));
+ for (;;)
+ {
+ if (auto [_, socket] = co_await acceptor.async_accept(); socket.is_open())
+ {
+ for (;;)
+ {
+ char data[1024];
+ auto [e1, n] = co_await socket.async_read_some(asio::buffer(data));
+ if (e1) break;
+ auto [e2, _] = co_await asio::async_write(socket, asio::buffer(data, n));
+ if (e2) break;
+ }
+ }
+ }
+}
+
+simple_coro stopper(asio::io_context& ctx)
+{
+ asio::signal_set signals(ctx, SIGINT);
+ auto [_, n] = co_await signals.async_wait(use_await);
+ std::cout << "got sig " << n << "\n";
+ ctx.stop();
+}
+
+simple_coro poster(asio::io_context& ctx)
+{
+ co_await asio::post(ctx, use_await);
+}
+
+int main()
+{
+ asio::io_context ctx(1);
+ std::list<simple_coro> coros;
+ /*tcp::acceptor acceptor(ctx, {tcp::v4(), 54321});
+ for (std::size_t i = 0; i < 2; ++i)
+ coros.push_back(listener(acceptor));
+ coros.push_back(stopper(ctx));*/
+ coros.push_back(poster(ctx));
+ for (auto& coro : coros)
+ coro.resume();
+ ctx.run();
+}