63#include "promises.hpp"
70template<
typename T>
struct TFuture;
82 std::suspend_never initial_suspend() {
return {}; }
85 std::coroutine_handle<>
Caller = std::noop_coroutine();
100 void return_value(
const T& t) {
104 void return_value(T&& t) {
108 void unhandled_exception() {
109 ErrorOr = std::current_exception();
113 std::optional<std::variant<T, std::exception_ptr>>
ErrorOr;
126 TFutureBase() =
default;
128 : Coro(Coro.from_promise(promise))
130 TFutureBase(TFutureBase&& other)
132 *
this = std::move(other);
134 TFutureBase(
const TFutureBase&) =
delete;
135 TFutureBase& operator=(
const TFutureBase&) =
delete;
136 TFutureBase& operator=(TFutureBase&& other) {
137 if (
this != &other) {
138 std::swap(Coro, other.Coro);
143 ~TFutureBase() {
if (Coro) { Coro.destroy(); } }
145 bool await_ready()
const {
146 return Coro.promise().ErrorOr != std::nullopt;
153 std::coroutine_handle<> raw() {
157 void await_suspend(std::coroutine_handle<> caller) {
158 Coro.promise().Caller = caller;
164 std::coroutine_handle<TPromise<T>> Coro =
nullptr;
167template<>
struct TFuture<void>;
179 auto& errorOr = *this->Coro.promise().ErrorOr;
180 if (
auto* res = std::get_if<T>(&errorOr)) {
181 return std::move(*res);
183 std::rethrow_exception(std::get<std::exception_ptr>(errorOr));
198 template<
typename Func>
200 auto prev = std::move(*
this);
201 auto ret =
co_await prev;
226 void unhandled_exception() {
227 ErrorOr = std::current_exception();
230 std::optional<std::exception_ptr> ErrorOr;
237struct TFuture<void> :
public TFutureBase<void> {
238 void await_resume() {
239 auto& errorOr = *this->Coro.promise().ErrorOr;
241 std::rethrow_exception(errorOr);
252 template<
typename Func>
254 auto prev = std::move(*
this);
262 auto prev = std::move(*
this);
279 bool await_ready()
noexcept {
return false; }
280 std::coroutine_handle<> await_suspend(std::coroutine_handle<
TPromise<T>> h)
noexcept {
281 return h.promise().Caller;
283 void await_resume()
noexcept { }
303 auto waiting = std::move(futures);
304 std::vector<T> ret; ret.reserve(waiting.size());
305 for (
auto& f : waiting) {
306 ret.emplace_back(std::move(
co_await f));
318 auto waiting = std::move(futures);
319 for (
auto& f : waiting) {
337 std::vector<TFuture<T>> all = std::move(futures);
339 auto it = std::find_if(all.begin(), all.end(), [](
auto& f) { return f.done(); });
340 if (it != all.end()) {
341 co_return it->await_resume();
344 auto self =
co_await Self();
345 for (
auto& f : all) {
346 f.await_suspend(self);
348 co_await std::suspend_always();
349 co_return std::find_if(all.begin(), all.end(), [](
auto& f) { return f.done(); })->await_resume();
359 std::vector<TFuture<void>> all = std::move(futures);
361 if (std::find_if(all.begin(), all.end(), [](
auto& f) { return f.done(); }) != all.end()) {
365 auto self =
co_await Self();
366 for (
auto& f : all) {
367 f.await_suspend(self);
369 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:336
TFuture< std::vector< T > > All(std::vector< TFuture< T > > &&futures)
Awaits the completion of all futures and collects their results.
Definition corochain.hpp:302
Final awaiter for a coroutine.
Definition corochain.hpp:278
auto Accept(Func func) -> TFuture< void >
Registers a continuation to be executed after the coroutine completes.
Definition corochain.hpp:253
Future type for coroutines returning a value of type T.
Definition corochain.hpp:177
auto Apply(Func func) -> TFuture< decltype(func(std::declval< T >()))>
Applies a function to the result of the coroutine.
Definition corochain.hpp:199
TFuture< void > Ignore()
Awaits the coroutine and ignores its result.
Definition corochain.hpp:261
Base promise type for coroutines.
Definition corochain.hpp:81
std::coroutine_handle Caller
Handle to the caller coroutine (initialized to a no-operation coroutine).
Definition corochain.hpp:85
Promise for coroutines that return a value of type T.
Definition corochain.hpp:97
std::optional< std::variant< T, std::exception_ptr > > ErrorOr
Optional container that holds either the result or an exception.
Definition corochain.hpp:113