mirror of
https://github.com/matrix-construct/construct
synced 2025-01-13 16:33:53 +01:00
ircd::ctx: Cleanup future when suite related.
This commit is contained in:
parent
27b0dfffa4
commit
3242c1929b
1 changed files with 71 additions and 24 deletions
|
@ -371,25 +371,45 @@ ircd::ctx::wait_until(const future<T> &f,
|
|||
future_status::deferred;
|
||||
}
|
||||
|
||||
/// Returns a future which becomes ready when all of the futures in the
|
||||
/// collection become ready. This future has a void payload to minimize
|
||||
/// its cost since this indication is positively unate.
|
||||
template<class it>
|
||||
ircd::ctx::future<void>
|
||||
ircd::ctx::when_all(it first,
|
||||
const it &last)
|
||||
{
|
||||
static const auto then
|
||||
{
|
||||
[](promise<void> &p)
|
||||
{
|
||||
if(!p.valid())
|
||||
return;
|
||||
|
||||
if(refcount(*p.st) < 2)
|
||||
return p.set_value();
|
||||
|
||||
return remove(*p.st, p);
|
||||
}
|
||||
};
|
||||
|
||||
promise<void> p;
|
||||
const auto set_then
|
||||
{
|
||||
[&p](auto &f)
|
||||
{
|
||||
f.st.then = [p]
|
||||
(shared_state_base &) mutable
|
||||
{
|
||||
then(p);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
future<void> 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);
|
||||
};
|
||||
set_then(*first);
|
||||
|
||||
if(refcount(*p.st) <= 1)
|
||||
p.set_value();
|
||||
|
@ -397,31 +417,58 @@ ircd::ctx::when_all(it first,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/// Returns a future which becomes ready when any of the futures in the
|
||||
/// iteration become ready or are already ready. The future that when_any()
|
||||
/// eventually indicates is then considered "observed" which means you
|
||||
/// are required to do nothing when including it in the next invocation of
|
||||
/// when_any() and it won't be considered ready or pending again and the
|
||||
/// collection does not have to be modified in any way.
|
||||
///
|
||||
/// The returned future's payload is an iterator into the collection as if
|
||||
/// it were the result of an std::find() etc; thus to know its index an
|
||||
/// std::distance often satisfactory.
|
||||
template<class it>
|
||||
ircd::ctx::future<it>
|
||||
ircd::ctx::when_any(it first,
|
||||
const it &last)
|
||||
{
|
||||
promise<it> p;
|
||||
future<it> ret(p);
|
||||
for(auto first_(first); first_ != last; ++first_)
|
||||
if(ready(first_->st))
|
||||
static const auto then
|
||||
{
|
||||
[](promise<it> &p, it &f)
|
||||
{
|
||||
set_observed(first_->st);
|
||||
p.set_value(first_);
|
||||
if(!p.valid())
|
||||
return;
|
||||
|
||||
set_observed(f->st);
|
||||
p.set_value(f);
|
||||
}
|
||||
};
|
||||
|
||||
promise<it> p;
|
||||
const auto set_then
|
||||
{
|
||||
[&p](it &f)
|
||||
{
|
||||
f->st.then = [p, f] // alloc
|
||||
(shared_state_base &) mutable
|
||||
{
|
||||
then(p, f);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
future<it> ret(p);
|
||||
for(auto f(first); f != last; ++f)
|
||||
if(ready(f->st))
|
||||
{
|
||||
set_observed(f->st);
|
||||
p.set_value(f);
|
||||
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);
|
||||
};
|
||||
set_then(first);
|
||||
|
||||
if(refcount(*p.st) <= 1)
|
||||
p.set_value(first);
|
||||
|
|
Loading…
Reference in a new issue