File indexing completed on 2025-12-16 09:44:27
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_COBALT_TASK_HPP
0009 #define BOOST_COBALT_TASK_HPP
0010
0011 #include <boost/cobalt/detail/handler.hpp>
0012 #include <boost/cobalt/detail/task.hpp>
0013 #include <boost/cobalt/op.hpp>
0014
0015 #include <boost/asio/append.hpp>
0016 #include <boost/asio/deferred.hpp>
0017
0018 namespace boost::cobalt
0019 {
0020
0021
0022 template<typename Return>
0023 struct [[nodiscard]] task
0024 {
0025 task(task &&lhs) noexcept = default;
0026 task& operator=(task &&) noexcept = default;
0027
0028
0029 auto operator co_await ();
0030
0031
0032 task(const task &) = delete;
0033 task& operator=(const task &) = delete;
0034
0035 using promise_type = detail::task_promise<Return>;
0036
0037 constexpr task(noop<Return> n) : receiver_(std::move(n)){}
0038
0039 private:
0040 template<typename>
0041 friend struct detail::task_promise;
0042
0043 task(detail::task_promise<Return> * task) : receiver_(task)
0044 {
0045 }
0046
0047 detail::task_receiver<Return> receiver_;
0048 friend struct detail::async_initiate_spawn;
0049
0050 };
0051
0052
0053
0054 struct use_task_t
0055 {
0056
0057 constexpr use_task_t()
0058 {
0059 }
0060
0061
0062
0063 template <typename InnerExecutor>
0064 struct executor_with_default : InnerExecutor
0065 {
0066
0067 typedef use_task_t default_completion_token_type;
0068
0069 executor_with_default(const InnerExecutor& ex) noexcept
0070 : InnerExecutor(ex)
0071 {
0072 }
0073
0074
0075 template <typename InnerExecutor1>
0076 executor_with_default(const InnerExecutor1& ex,
0077 typename std::enable_if<
0078 std::conditional<
0079 !std::is_same<InnerExecutor1, executor_with_default>::value,
0080 std::is_convertible<InnerExecutor1, InnerExecutor>,
0081 std::false_type
0082 >::type::value>::type = 0) noexcept
0083 : InnerExecutor(ex)
0084 {
0085 }
0086 };
0087
0088
0089
0090 template <typename T>
0091 using as_default_on_t = typename T::template rebind_executor<
0092 executor_with_default<typename T::executor_type> >::other;
0093
0094
0095
0096 template <typename T>
0097 static typename std::decay_t<T>::template rebind_executor<
0098 executor_with_default<typename std::decay_t<T>::executor_type>
0099 >::other
0100 as_default_on(T && object)
0101 {
0102 return typename std::decay_t<T>::template rebind_executor<
0103 executor_with_default<typename std::decay_t<T>::executor_type>
0104 >::other(std::forward<T>(object));
0105 }
0106
0107 };
0108
0109 constexpr use_task_t use_task{};
0110
0111 template<typename T>
0112 inline auto task<T>::operator co_await () {return receiver_.get_awaitable();}
0113
0114 }
0115
0116
0117 namespace boost::asio
0118 {
0119
0120 template<typename ... Args>
0121 struct async_result<boost::cobalt::use_task_t, void(Args...)>
0122 {
0123 using return_type = cobalt::task<
0124 typename decltype(cobalt::interpret_as_result(std::declval<std::tuple<Args...>>()))::value_type>;
0125
0126 template <typename Initiation, typename... InitArgs>
0127 static auto initiate(Initiation initiation,
0128 boost::cobalt::use_task_t,
0129 InitArgs ... args) -> return_type
0130
0131 {
0132 co_return co_await async_initiate<
0133 const cobalt::use_op_t&, void(Args...)>(
0134 std::move(initiation),
0135 cobalt::use_op, std::move(args)...);
0136 }
0137 };
0138
0139 }
0140
0141
0142 #endif