LeviLamina
Loading...
Searching...
No Matches
CoroPromise.h
1#pragma once
2
3#include <coroutine>
4
5#include "ll/api/Expected.h"
6#include "ll/api/base/Concepts.h"
7#include "ll/api/coro/ForwardAwaiter.h"
8#include "ll/api/coro/SleepAwaiter.h"
9#include "ll/api/coro/YieldAwaiter.h"
10
11namespace ll::coro {
12
13template <class T>
14class CoroTask;
15
17 std::coroutine_handle<> handle;
18 void* local{};
19 ExecutorRef exec{};
20
21 constexpr CoroPromiseBase() noexcept = default;
22
23 struct FinalAwaiter {
24 constexpr bool await_ready() const noexcept { return false; }
25 template <std::derived_from<CoroPromiseBase> P>
26 constexpr auto await_suspend(std::coroutine_handle<P> h) noexcept {
27 return h.promise().handle;
28 }
29 constexpr void await_resume() noexcept {}
30 };
31 constexpr std::suspend_always initial_suspend() noexcept { return {}; }
32 constexpr FinalAwaiter final_suspend() noexcept { return {}; }
33
34 template <concepts::Awaitable T>
35 constexpr decltype(auto) await_transform(T&& awaitable) {
36 if constexpr (requires(T a, ExecutorRef e) { a.setExecutor(e); }) {
37 std::forward<T>(awaitable).setExecutor(exec);
38 }
39 return std::forward<T>(awaitable);
40 }
41
42 constexpr ForwardAwaiter<NonNullExecutorRef> await_transform(CurrentExecutor) { return {exec.value()}; }
43
44 constexpr YieldAwaiter await_transform(Yield const&) { return {exec}; }
45
46 template <class R, class P>
47 constexpr SleepAwaiter await_transform(std::chrono::duration<R, P> const& dur) {
48 return {dur, exec};
49 }
50 template <class C, class D>
51 constexpr SleepAwaiter await_transform(std::chrono::time_point<C, D> const& time) {
52 return {time, exec};
53 }
54};
55template <class T>
57 using ExpectedResult = std::conditional_t<concepts::IsLeviExpected<T>, T, Expected<T>>;
58
59 std::optional<ExpectedResult> res{};
60
61 constexpr CoroPromise() noexcept = default;
62
63 template <class V>
64 void return_value(V&& value) noexcept(std::is_nothrow_constructible_v<T, V>)
65 requires(std::is_constructible_v<T, V>)
66 {
67 res.emplace(std::forward<V>(value));
68 }
69 void unhandled_exception() noexcept { res.emplace(makeExceptionError()); }
70
71 constexpr CoroTask<T> get_return_object() noexcept;
72
73 constexpr ExpectedResult& result() noexcept { return *res; }
74
75 constexpr ExpectedResult const& result() const noexcept { return *res; }
76};
77template <>
78struct CoroPromise<void> : public CoroPromiseBase {
79 using ExpectedResult = Expected<>;
80
81 ExpectedResult res{};
82
83 constexpr CoroPromise() noexcept = default;
84
85 void return_void() noexcept {}
86
87 void unhandled_exception() noexcept { res = makeExceptionError(); }
88
89 constexpr CoroTask<void> get_return_object() noexcept;
90
91 constexpr ExpectedResult& result() noexcept { return res; }
92
93 constexpr ExpectedResult const& result() const noexcept { return res; }
94};
95} // namespace ll::coro
Definition CoroTask.h:12
Definition optional_ref.h:10
Definition CoroPromise.h:23
Definition CoroPromise.h:16
Definition CoroPromise.h:56