0
0
Fork 0
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:
Jason Volk 2018-03-27 01:34:35 -07:00
parent b49cdb84e8
commit 543a1988b9

View file

@ -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;
} }