diff --git a/include/ircd/ctx/promise.h b/include/ircd/ctx/promise.h index a3490961f..a364511d5 100644 --- a/include/ircd/ctx/promise.h +++ b/include/ircd/ctx/promise.h @@ -196,11 +196,11 @@ ircd::ctx::promise::set_value(T&& val) { assert(valid()); assert(pending(*st)); + st->val = std::move(val); auto *const st{this->st}; invalidate(*st); set_ready(*st); - st->val = std::move(val); - st->cond.notify_all(); + notify(*st); } template @@ -209,11 +209,11 @@ ircd::ctx::promise::set_value(const T &val) { assert(valid()); assert(pending(*st)); + st->val = val; auto *const st{this->st}; invalidate(*st); set_ready(*st); - st->val = val; - st->cond.notify_all(); + notify(*st); } inline void @@ -224,7 +224,7 @@ ircd::ctx::promise::set_value() auto *const st{this->st}; invalidate(*st); set_ready(*st); - st->cond.notify_all(); + notify(*st); } template @@ -233,11 +233,11 @@ ircd::ctx::promise::set_exception(std::exception_ptr eptr) { assert(valid()); assert(pending(*st)); + st->eptr = std::move(eptr); auto *const st{this->st}; invalidate(*st); set_ready(*st); - st->eptr = std::move(eptr); - st->cond.notify_all(); + notify(*st); } inline void @@ -245,11 +245,11 @@ ircd::ctx::promise::set_exception(std::exception_ptr eptr) { assert(valid()); assert(pending(*st)); + st->eptr = std::move(eptr); auto *const st{this->st}; invalidate(*st); set_ready(*st); - st->eptr = std::move(eptr); - st->cond.notify_all(); + notify(*st); } template diff --git a/include/ircd/ctx/shared_state.h b/include/ircd/ctx/shared_state.h index f2cf18b2a..53a5ddb95 100644 --- a/include/ircd/ctx/shared_state.h +++ b/include/ircd/ctx/shared_state.h @@ -24,12 +24,14 @@ namespace ircd::ctx template bool pending(const shared_state &); template bool ready(const shared_state &); template void set_ready(shared_state &); + template void notify(shared_state &); } struct ircd::ctx::shared_state_base { mutable dock cond; std::exception_ptr eptr; + std::function then; }; template @@ -53,6 +55,24 @@ struct ircd::ctx::shared_state promise *p {nullptr}; }; +template +void +ircd::ctx::notify(shared_state &st) +{ + st.cond.notify_all(); + + if(!st.then) + return; + + if(!current) + return st.then(st); + + ircd::post([&st] + { + st.then(st); + }); +} + template void ircd::ctx::set_ready(shared_state &st)