65#include "promises.hpp"
70template<
typename T>
struct TFinalAwaiter;
72template<
typename T>
struct TFuture;
84 std::suspend_never initial_suspend() {
return {}; }
87 std::coroutine_handle<>
Caller = std::noop_coroutine();
102 void return_value(
const T& t) {
106 void return_value(T&& t) {
110 void unhandled_exception() {
111 ErrorOr = std::unexpected(std::current_exception());
115 std::optional<std::expected<T, std::exception_ptr>>
ErrorOr;
130 : Coro(Coro.from_promise(promise))
134 *
this = std::move(other);
139 if (
this != &other) {
143 Coro = std::exchange(other.Coro,
nullptr);
150 bool await_ready()
const {
151 return Coro.promise().ErrorOr.has_value();
158 std::coroutine_handle<> raw() {
162 void await_suspend(std::coroutine_handle<> caller) {
163 Coro.promise().Caller = caller;
169 std::coroutine_handle<TPromise<T>> Coro =
nullptr;
172template<>
struct TFuture<void>;
184 auto& errorOr = *this->Coro.promise().ErrorOr;
185 if (errorOr.has_value()) {
186 return std::move(errorOr.value());
188 std::rethrow_exception(errorOr.error());
203 template<
typename Func>
205 auto prev = std::move(*
this);
206 auto ret =
co_await prev;
231 void unhandled_exception() {
232 ErrorOr = std::current_exception();
235 std::optional<std::exception_ptr>
ErrorOr;
243 void await_resume() {
244 auto& errorOr = *this->Coro.promise().ErrorOr;
246 std::rethrow_exception(errorOr);
257 template<
typename Func>
259 auto prev = std::move(*
this);
267 auto prev = std::move(*
this);
284 bool await_ready()
noexcept {
return false; }
285 std::coroutine_handle<> await_suspend(std::coroutine_handle<
TPromise<T>> h)
noexcept {
286 return h.promise().Caller;
288 void await_resume()
noexcept { }
293TFuture<T> TPromise<T>::get_return_object() {
return { TFuture<T>{*
this} }; }
297TFinalAwaiter<T> TPromiseBase<T>::final_suspend() noexcept {
return {}; }
308 auto waiting = std::move(futures);
309 std::vector<T> ret; ret.reserve(waiting.size());
310 for (
auto& f : waiting) {
311 ret.emplace_back(std::move(
co_await f));
323 auto waiting = std::move(futures);
324 for (
auto& f : waiting) {
342 std::vector<TFuture<T>> all = std::move(futures);
344 auto it = std::find_if(all.begin(), all.end(), [](
auto& f) { return f.done(); });
345 if (it != all.end()) {
346 co_return it->await_resume();
349 auto self =
co_await Self();
350 for (
auto& f : all) {
351 f.await_suspend(self);
353 co_await std::suspend_always();
354 co_return std::find_if(all.begin(), all.end(), [](
auto& f) { return f.done(); })->await_resume();
364 std::vector<TFuture<void>> all = std::move(futures);
366 if (std::find_if(all.begin(), all.end(), [](
auto& f) { return f.done(); }) != all.end()) {
370 auto self =
co_await Self();
371 for (
auto& f : all) {
372 f.await_suspend(self);
374 co_await std::suspend_always();
A minimal example of a coroutine "awaitable" object.
TFuture< T > Any(std::vector< TFuture< T > > &&futures)
Awaits the completion of any one of the given futures and returns its result.
Definition corochain.hpp:341
TFuture< std::vector< T > > All(std::vector< TFuture< T > > &&futures)
Awaits the completion of all futures and collects their results.
Definition corochain.hpp:307
Final awaiter for a coroutine.
Definition corochain.hpp:283
Base future type for coroutines.
Definition corochain.hpp:127
auto Accept(Func func) -> TFuture< void >
Registers a continuation to be executed after the coroutine completes.
Definition corochain.hpp:258
Future type for coroutines returning a value of type T.
Definition corochain.hpp:182
auto Apply(Func func) -> TFuture< decltype(func(std::declval< T >()))>
Applies a function to the result of the coroutine.
Definition corochain.hpp:204
TFuture< void > Ignore()
Awaits the coroutine and ignores its result.
Definition corochain.hpp:266
Base promise type for coroutines.
Definition corochain.hpp:83
std::coroutine_handle Caller
Handle to the caller coroutine (initialized to a no-operation coroutine).
Definition corochain.hpp:87
Promise for coroutines that return a value of type T.
Definition corochain.hpp:99
std::optional< std::expected< T, std::exception_ptr > > ErrorOr
Optional container that holds either the result or an exception.
Definition corochain.hpp:115