15 using Handle = std::coroutine_handle<promise_type>;
19 using ExpectedResult =
typename CoroPromise<T>::ExpectedResult;
26 constexpr explicit CoroTask(Handle h) noexcept : handle(h) {}
32 constexpr void setExecutor(
ExecutorRef ex) { AwaiterBase::handle.promise().exec = ex; }
34 constexpr ExpectedResult await_resume()
noexcept {
return AwaiterBase::getResult(); }
39 constexpr T await_resume() {
40 if constexpr (std::is_same_v<T, ExpectedResult>) {
41 return AwaiterBase::getResult();
43 return AwaiterBase::getResult().value();
52 constexpr std::suspend_never initial_suspend()
noexcept {
return {}; }
53 constexpr std::suspend_never final_suspend()
noexcept {
return {}; }
54 constexpr void return_void()
noexcept {}
55 constexpr void unhandled_exception() { std::rethrow_exception(std::current_exception()); }
56 constexpr Launcher get_return_object()
noexcept {
return {}; }
64 CoroTask(
CoroTask&& other) noexcept : handle(std::exchange(other.handle,
nullptr)) {}
68 std::exchange(handle,
nullptr).destroy();
72 constexpr void setExecutor(ExecutorRef ex) { handle.promise().exec = ex; }
74 constexpr ExecutorRef getExecutor() {
return handle.promise().exec; }
76 bool done()
const {
return !handle || handle.done(); }
78 auto operator co_await() {
return ValueAwaiter(std::exchange(handle,
nullptr)); }
80 auto tryGet() {
return ExpectedAwaiter(std::exchange(handle,
nullptr)); }
82 template <std::invocable<ExpectedResult> F>
83 void launch(NonNullExecutorRef executor, F&& callback)
noexcept try {
84 setExecutor(executor);
85 [](CoroTask lazy, std::decay_t<F> cb) -> Launcher {
86 std::invoke(cb,
co_await lazy.tryGet());
87 }(std::move(*
this), std::forward<F>(callback));
89 std::invoke(std::forward<F>(callback), makeExceptionError());
91 void launch(NonNullExecutorRef executor)
noexcept {
92 launch(executor, [](
auto&&) {});
94 ExpectedResult syncLaunch(NonNullExecutorRef executor)
noexcept {
96 std::binary_semaphore cond{0};
97 launch(executor, [&](ExpectedResult&& result) {
98 value = std::move(result);