From a2be4d3ee5b81d056bf7b984f3afeca1be655185 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sat, 10 Mar 2018 17:33:14 -0800 Subject: [PATCH] ircd::ctx: Add when_any() / when_all(). --- include/ircd/ctx/future.h | 60 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/include/ircd/ctx/future.h b/include/ircd/ctx/future.h index c75f3dd1d..11d11c6c2 100644 --- a/include/ircd/ctx/future.h +++ b/include/ircd/ctx/future.h @@ -20,6 +20,8 @@ namespace ircd::ctx template struct scoped_future; enum class future_status; + template future when_any(it first, const it &last); + template future when_all(it first, const it &last); } enum class ircd::ctx::future_status @@ -359,3 +361,61 @@ ircd::ctx::wait_until(const future &f, future_status::ready: future_status::deferred; } + +template +ircd::ctx::future +ircd::ctx::when_all(it first, + const it &last) +{ + promise p; + future ret(p); + for(; first != last; ++first) + if(pending(first->st)) + first->st.then = [p](shared_state_base &) mutable + { + if(!p.valid()) + return; + + if(refcount(*p.st) < 2) + return p.set_value(); + + return remove(*p.st, p); + }; + + if(refcount(*p.st) <= 1) + p.set_value(); + + return ret; +} + +template +ircd::ctx::future +ircd::ctx::when_any(it first, + const it &last) +{ + promise p; + future ret(p); + for(auto first_(first); first_ != last; ++first_) + if(ready(first_->st)) + { + set_observed(first_->st); + p.set_value(first_); + return ret; + } + + for(; first != last; ++first) + if(pending(first->st)) + first->st.then = [p, first](shared_state_base &) mutable + { + if(!p.valid()) + return; + + set_observed(first->st); + p.set_value(first); + }; + + if(refcount(*p.st) <= 1) + p.set_value(first); + + return ret; +}