Skip to content

Commit

Permalink
feat: add then<>(..., []() -> Awaitable {})
Browse files Browse the repository at this point in the history
  • Loading branch information
yulon committed Sep 8, 2023
1 parent 1359231 commit ddb338d
Showing 1 changed file with 77 additions and 10 deletions.
87 changes: 77 additions & 10 deletions include/rua/sync/then.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,40 @@

namespace rua {

template <typename R, typename Awaitable, typename Callback>
inline enable_if_t<!is_awaitable<R>::value, future<R>>
_then(Awaitable &&awaitable, Callback &&callback) {
auto aw = wrap_awaiter(std::forward<Awaitable>(awaitable));
if (aw->await_ready()) {
return expected_invoke(std::forward<Callback>(callback), [&]() {
return aw->await_resume();
});
}

struct ctx_t {
awaiter_wrapper<Awaitable &&> aw;
decay_t<Callback> cb;
};

auto prm = new newable_promise<R, ctx_t>(
ctx_t{std::move(aw), std::forward<Callback>(callback)});

if (await_suspend(*prm->extend().aw, [prm]() {
prm->fulfill(expected_invoke(prm->extend().cb, [prm]() {
return prm->extend().aw->await_resume();
}));
})) {
return future<R>(*prm);
}

auto r_exp = expected_invoke(
prm->extend().cb, [prm]() { return prm->extend().aw->await_resume(); });

prm->unuse();

return r_exp;
}

template <
typename Awaitable,
typename Callback,
Expand All @@ -19,37 +53,70 @@ template <
std::declval<
warp_expected_t<decay_t<await_result_t<Awaitable &&>>>>())),
typename R = unwarp_expected_t<ExpR>>
inline future<R> then(Awaitable &&awaitable, Callback &&callback) {
inline decltype(_then<R>(
std::declval<Awaitable &&>(), std::declval<Callback &&>()))
then(Awaitable &&awaitable, Callback &&callback) {
return _then<R>(
std::forward<Awaitable>(awaitable), std::forward<Callback>(callback));
}

template <
typename R,
typename Awaitable,
typename Callback,
typename R2 = unwarp_expected_t<decay_t<await_result_t<R>>>>
inline enable_if_t<is_awaitable<R>::value, future<R2>>
_then(Awaitable &&awaitable, Callback &&callback) {
auto aw = wrap_awaiter(std::forward<Awaitable>(awaitable));
if (aw->await_ready()) {
return expected_invoke(std::forward<Callback>(callback), [&]() {
auto r_exp = expected_invoke(std::forward<Callback>(callback), [&]() {
return aw->await_resume();
});

if (!r_exp) {
return r_exp.error();
}

return _then<R2>(*std::move(r_exp), [](expected<R2> r2_exp) {
return std::move(r2_exp);
});
}

struct ctx_t {
awaiter_wrapper<Awaitable &&> aw;
decay_t<Callback> cb;
};

auto prm = new newable_promise<R, ctx_t>(
auto prm = new newable_promise<R2, ctx_t>(
ctx_t{std::move(aw), std::forward<Callback>(callback)});

if (await_suspend(*prm->extend().aw, [prm]() {
prm->fulfill(expected_invoke(prm->extend().cb, [prm]() {
auto r_exp = expected_invoke(prm->extend().cb, [prm]() {
return prm->extend().aw->await_resume();
}));
});
if (!r_exp) {
prm->fulfill(r_exp.error());
return;
}
then(*std::move(r_exp), [prm](expected<R2> r2_exp) {
prm->fulfill(std::move(r2_exp));
});
})) {
return future<R>(*prm);
return future<R2>(*prm);
}

auto exp = expected_invoke(prm->extend().cb, [prm]() mutable {
return prm->extend().aw->await_resume();
});
auto r_exp = expected_invoke(
prm->extend().cb, [prm]() { return prm->extend().aw->await_resume(); });

prm->unuse();

return exp;
if (!r_exp) {
return r_exp.error();
}

return _then<R2>(*std::move(r_exp), [](expected<R2> r2_exp) {
return std::move(r2_exp);
});
}

namespace await_operators {
Expand Down

0 comments on commit ddb338d

Please sign in to comment.