// // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net) // // 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_COBALT_TASK_HPP #define BOOST_COBALT_TASK_HPP #include #include #include #include #include namespace boost::cobalt { // tag::outline[] template struct [[nodiscard]] task { task(task &&lhs) noexcept = default; task& operator=(task &&) noexcept = default; // enable `co_await` auto operator co_await (); // end::outline[] task(const task &) = delete; task& operator=(const task &) = delete; using promise_type = detail::task_promise; private: template friend struct detail::task_promise; task(detail::task_promise * task) : receiver_(task) { } detail::task_receiver receiver_; friend struct detail::async_initiate_spawn; // tag::outline[] }; // end::outline[] struct use_task_t { /// Default constructor. constexpr use_task_t() { } /// Adapts an executor to add the @c use_task_t completion token as the /// default. template struct executor_with_default : InnerExecutor { /// Specify @c use_task_t as the default completion token type. typedef use_task_t default_completion_token_type; executor_with_default(const InnerExecutor& ex) noexcept : InnerExecutor(ex) { } /// Construct the adapted executor from the inner executor type. template executor_with_default(const InnerExecutor1& ex, typename std::enable_if< std::conditional< !std::is_same::value, std::is_convertible, std::false_type >::type::value>::type = 0) noexcept : InnerExecutor(ex) { } }; /// Type alias to adapt an I/O object to use @c use_task_t as its /// default completion token type. template using as_default_on_t = typename T::template rebind_executor< executor_with_default >::other; /// Function helper to adapt an I/O object to use @c use_task_t as its /// default completion token type. template static typename std::decay_t::template rebind_executor< executor_with_default::executor_type> >::other as_default_on(T && object) { return typename std::decay_t::template rebind_executor< executor_with_default::executor_type> >::other(std::forward(object)); } }; constexpr use_task_t use_task{}; template inline auto task::operator co_await () {return receiver_.get_awaitable();} } namespace boost::asio { template struct async_result { using return_type = cobalt::task< typename decltype(cobalt::interpret_as_result(std::declval>()))::value_type>; template static auto initiate(Initiation initiation, boost::cobalt::use_task_t, InitArgs ... args) -> return_type { co_return co_await async_initiate< const cobalt::use_op_t&, void(Args...)>( std::move(initiation), cobalt::use_op, std::move(args)...); } }; } #endif //BOOST_COBALT_COBALT_HPP