1//
2// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8#ifndef BOOST_COBALT_TASK_HPP
9#define BOOST_COBALT_TASK_HPP
10
11#include <boost/cobalt/detail/handler.hpp>
12#include <boost/cobalt/detail/task.hpp>
13#include <boost/cobalt/op.hpp>
14
15#include <boost/asio/append.hpp>
16#include <boost/asio/deferred.hpp>
17
18namespace boost::cobalt
19{
20
21// tag::outline[]
22template<typename Return>
23struct [[nodiscard]] task
24{
25 task(task &&lhs) noexcept = default;
26 task& operator=(task &&) noexcept = default;
27
28 // enable `co_await`
29 auto operator co_await ();
30
31 // end::outline[]
32 task(const task &) = delete;
33 task& operator=(const task &) = delete;
34
35 using promise_type = detail::task_promise<Return>;
36
37 private:
38 template<typename>
39 friend struct detail::task_promise;
40
41 task(detail::task_promise<Return> * task) : receiver_(task)
42 {
43 }
44
45 detail::task_receiver<Return> receiver_;
46 friend struct detail::async_initiate_spawn;
47 // tag::outline[]
48};
49// end::outline[]
50
51
52struct use_task_t
53{
54 /// Default constructor.
55 constexpr use_task_t()
56 {
57 }
58
59 /// Adapts an executor to add the @c use_task_t completion token as the
60 /// default.
61 template <typename InnerExecutor>
62 struct executor_with_default : InnerExecutor
63 {
64 /// Specify @c use_task_t as the default completion token type.
65 typedef use_task_t default_completion_token_type;
66
67 executor_with_default(const InnerExecutor& ex) noexcept
68 : InnerExecutor(ex)
69 {
70 }
71
72 /// Construct the adapted executor from the inner executor type.
73 template <typename InnerExecutor1>
74 executor_with_default(const InnerExecutor1& ex,
75 typename std::enable_if<
76 std::conditional<
77 !std::is_same<InnerExecutor1, executor_with_default>::value,
78 std::is_convertible<InnerExecutor1, InnerExecutor>,
79 std::false_type
80 >::type::value>::type = 0) noexcept
81 : InnerExecutor(ex)
82 {
83 }
84 };
85
86 /// Type alias to adapt an I/O object to use @c use_task_t as its
87 /// default completion token type.
88 template <typename T>
89 using as_default_on_t = typename T::template rebind_executor<
90 executor_with_default<typename T::executor_type> >::other;
91
92 /// Function helper to adapt an I/O object to use @c use_task_t as its
93 /// default completion token type.
94 template <typename T>
95 static typename std::decay_t<T>::template rebind_executor<
96 executor_with_default<typename std::decay_t<T>::executor_type>
97 >::other
98 as_default_on(T && object)
99 {
100 return typename std::decay_t<T>::template rebind_executor<
101 executor_with_default<typename std::decay_t<T>::executor_type>
102 >::other(std::forward<T>(object));
103 }
104
105};
106
107constexpr use_task_t use_task{};
108
109template<typename T>
110inline auto task<T>::operator co_await () {return receiver_.get_awaitable();}
111
112}
113
114
115namespace boost::asio
116{
117
118template<typename ... Args>
119struct async_result<boost::cobalt::use_task_t, void(Args...)>
120{
121 using return_type = cobalt::task<
122 typename decltype(cobalt::interpret_as_result(std::declval<std::tuple<Args...>>()))::value_type>;
123
124 template <typename Initiation, typename... InitArgs>
125 static auto initiate(Initiation initiation,
126 boost::cobalt::use_task_t,
127 InitArgs ... args) -> return_type
128
129 {
130 co_return co_await async_initiate<
131 const cobalt::use_op_t&, void(Args...)>(
132 std::move(initiation),
133 cobalt::use_op, std::move(args)...);
134 }
135};
136
137}
138
139
140#endif //BOOST_COBALT_COBALT_HPP
141

source code of boost/libs/cobalt/include/boost/cobalt/task.hpp