0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-19 18:38:21 +02:00

ircd::ctx: Fix inconsistent refcount() behavior.

This commit is contained in:
Jason Volk 2019-09-08 16:34:41 -07:00
parent f942c3ffc6
commit 42d56a7bac
2 changed files with 24 additions and 16 deletions

View file

@ -80,7 +80,8 @@ ircd::ctx::when_any(it first,
if(is(state(closure(first)), future_state::PENDING))
when::set_any_then(p, first, closure);
if(promise<it>::refcount(p.state()) <= 1)
assert(promise<it>::refcount(p) >= 1);
if(promise<it>::refcount(p) == 1)
p.set_value(last);
return ret;
@ -118,7 +119,8 @@ ircd::ctx::when_all(it first,
if(is(state(closure(first)), future_state::PENDING))
when::set_all_then(p, first, closure);
if(promise<void>::refcount(p.state()) <= 1)
assert(promise<void>::refcount(p) >= 1);
if(promise<void>::refcount(p) == 1)
p.set_value();
return ret;
@ -174,7 +176,8 @@ ircd::ctx::when::all_then(promise<void> &p)
if(!p.valid())
return;
if(promise<void>::refcount(p.state()) < 2)
assert(promise<void>::refcount(p) >= 1);
if(promise<void>::refcount(p) == 1)
return p.set_value();
return p.remove();

View file

@ -1989,10 +1989,7 @@ noexcept
ircd::ctx::promise_base::~promise_base()
noexcept
{
if(!valid())
return;
if(promise_base::refcount(state()) == 1)
if(promise_base::refcount(*this) == 1)
set_exception(make_exception_ptr<broken_promise>());
remove();
@ -2024,10 +2021,18 @@ ircd::ctx::promise_base::remove()
void
ircd::ctx::promise_base::make_ready()
{
const critical_assertion ca;
assert(valid());
promise_base *p
{
promise_base::head(*this)
};
assert(p);
shared_state_base *next
{
shared_state_base::head(*this)
shared_state_base::head(*p)
};
// First we have to chase the linked list of promises reachable
@ -2110,7 +2115,7 @@ ircd::ctx::promise_base::head(const promise_base &p)
{
return p.st && head(*p.st)?
head(*p.st):
nullptr;
std::addressof(p);
}
const ircd::ctx::promise_base *
@ -2409,11 +2414,10 @@ noexcept
shared_state_base::refcount(*this)
};
assert(refcount >= 1);
if(refcount <= 1)
if(refcount == 1)
invalidate_promises(*this);
remove(*this);
else if(refcount > 1)
remove(*this);
}
//
@ -2425,6 +2429,9 @@ size_t
ircd::ctx::shared_state_base::refcount(const shared_state_base &st)
{
size_t ret{0};
if(!is(st, future_state::PENDING))
return ret;
for(const auto *next(head(st)); next; next = next->next)
++ret;
@ -2509,9 +2516,7 @@ ircd::ctx::remove(shared_state_base &st)
else
invalidate_promises(st);
}
assert(last);
for(auto *next(last->next); next; last = next, next = next->next)
else for(auto *next(last->next); next; last = next, next = next->next)
if(next == &st)
{
last->next = next->next;