mirror of
https://github.com/matrix-construct/construct
synced 2024-11-17 23:40:57 +01:00
ircd::ctx: Candidate fixes for view sequencing.
This commit is contained in:
parent
b49cdb84e8
commit
543a1988b9
1 changed files with 50 additions and 40 deletions
|
@ -36,8 +36,9 @@ template<class T,
|
||||||
class ircd::ctx::view
|
class ircd::ctx::view
|
||||||
:public mutex
|
:public mutex
|
||||||
{
|
{
|
||||||
T *t {nullptr};
|
|
||||||
dock q;
|
dock q;
|
||||||
|
T *t {nullptr};
|
||||||
|
size_t wanting {0};
|
||||||
size_t waiting {0};
|
size_t waiting {0};
|
||||||
|
|
||||||
bool ready() const;
|
bool ready() const;
|
||||||
|
@ -61,6 +62,7 @@ ircd::ctx::view<T, mutex>::~view()
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
assert(!waiting);
|
assert(!waiting);
|
||||||
|
assert(!wanting);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T,
|
template<class T,
|
||||||
|
@ -68,16 +70,21 @@ template<class T,
|
||||||
void
|
void
|
||||||
ircd::ctx::view<T, mutex>::operator()(T &t)
|
ircd::ctx::view<T, mutex>::operator()(T &t)
|
||||||
{
|
{
|
||||||
if(!waiting)
|
const auto produce{[this]
|
||||||
return;
|
(T *const &t, size_t &semaphore)
|
||||||
|
{
|
||||||
|
q.wait([this, &semaphore]
|
||||||
|
{
|
||||||
|
return semaphore == 0;
|
||||||
|
});
|
||||||
|
|
||||||
this->t = &t;
|
const std::lock_guard<view> lock{*this};
|
||||||
q.notify_all();
|
this->t = t;
|
||||||
q.wait([this] { return !waiting; });
|
q.notify_all();
|
||||||
const std::lock_guard<view> lock{*this};
|
}};
|
||||||
this->t = nullptr;
|
|
||||||
assert(!waiting);
|
produce(&t, wanting);
|
||||||
q.notify_all();
|
produce(nullptr, waiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T,
|
template<class T,
|
||||||
|
@ -86,24 +93,26 @@ template<class lock>
|
||||||
T &
|
T &
|
||||||
ircd::ctx::view<T, mutex>::wait(lock &l)
|
ircd::ctx::view<T, mutex>::wait(lock &l)
|
||||||
{
|
{
|
||||||
for(assert(l.owns_lock()); ready(); l.lock())
|
const auto consume{[this, &l]
|
||||||
|
(const bool &r, size_t &semaphore)
|
||||||
{
|
{
|
||||||
l.unlock();
|
const unwind uw{[this, &l, &semaphore]
|
||||||
q.wait();
|
{
|
||||||
}
|
--semaphore;
|
||||||
|
q.notify_all();
|
||||||
|
}};
|
||||||
|
|
||||||
const unwind ul{[this]
|
++semaphore;
|
||||||
{
|
assert(l.owns_lock());
|
||||||
--waiting;
|
const unlock_guard<lock> ul{l};
|
||||||
q.notify_all();
|
q.wait([this, &r]
|
||||||
|
{
|
||||||
|
return ready() == r;
|
||||||
|
});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
for(++waiting; !ready(); l.lock())
|
consume(false, wanting);
|
||||||
{
|
consume(true, waiting);
|
||||||
l.unlock();
|
|
||||||
q.wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(t != nullptr);
|
assert(t != nullptr);
|
||||||
return *t;
|
return *t;
|
||||||
}
|
}
|
||||||
|
@ -127,26 +136,27 @@ T &
|
||||||
ircd::ctx::view<T, mutex>::wait_until(lock &l,
|
ircd::ctx::view<T, mutex>::wait_until(lock &l,
|
||||||
time_point&& tp)
|
time_point&& tp)
|
||||||
{
|
{
|
||||||
for(assert(l.owns_lock()); ready(); l.lock())
|
const auto consume{[this, &l, &tp]
|
||||||
|
(const bool &r, size_t &semaphore)
|
||||||
{
|
{
|
||||||
l.unlock();
|
const unwind uw{[this, &l, &semaphore]
|
||||||
if(!q.wait_until(tp))
|
{
|
||||||
throw timeout{};
|
--semaphore;
|
||||||
}
|
q.notify_all();
|
||||||
|
}};
|
||||||
|
|
||||||
const unwind ul{[this]
|
++semaphore;
|
||||||
{
|
assert(l.owns_lock());
|
||||||
--waiting;
|
const unlock_guard<lock> ul{l};
|
||||||
q.notify_all();
|
if(!q.wait_until(tp, [this, &r]
|
||||||
|
{
|
||||||
|
return ready() == r;
|
||||||
|
}))
|
||||||
|
throw timeout{};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
for(++waiting; !ready(); l.lock())
|
consume(false, wanting);
|
||||||
{
|
consume(true, waiting);
|
||||||
l.unlock();
|
|
||||||
if(!q.wait_until(tp))
|
|
||||||
throw timeout{};
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(t != nullptr);
|
assert(t != nullptr);
|
||||||
return *t;
|
return *t;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue