mirror of
https://github.com/matrix-construct/construct
synced 2024-12-27 07:54:05 +01:00
ircd::ctx: Replace the std::deque with a ctx::list for ctx::dock's queue.
This commit is contained in:
parent
df0e59a5e0
commit
dcd36f8200
1 changed files with 46 additions and 53 deletions
|
@ -28,16 +28,13 @@ namespace ircd::ctx
|
||||||
enum class cv_status;
|
enum class cv_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/// dock is a condition variable which has no requirement for locking because
|
||||||
// a dock is a condition variable which has no requirement for locking because
|
/// the context system does not require mutual exclusion for coherence.
|
||||||
// the context system does not require mutual exclusion for coherence, however
|
///
|
||||||
// we have to create our own queue here rather than piggyback a mutex's.
|
|
||||||
//
|
|
||||||
class ircd::ctx::dock
|
class ircd::ctx::dock
|
||||||
{
|
{
|
||||||
std::deque<ctx *> q;
|
list q;
|
||||||
|
|
||||||
void remove_self();
|
|
||||||
void notify(ctx &) noexcept;
|
void notify(ctx &) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -81,12 +78,11 @@ inline void
|
||||||
ircd::ctx::dock::notify()
|
ircd::ctx::dock::notify()
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
if(q.empty())
|
ctx *c;
|
||||||
|
if(!(c = q.pop_front()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto c(q.front());
|
q.push_back(c);
|
||||||
q.pop_front();
|
|
||||||
q.emplace_back(c);
|
|
||||||
notify(*c);
|
notify(*c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,35 +91,35 @@ inline void
|
||||||
ircd::ctx::dock::notify_one()
|
ircd::ctx::dock::notify_one()
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
if(q.empty())
|
if(!q.empty())
|
||||||
return;
|
notify(*q.front());
|
||||||
|
|
||||||
notify(*q.front());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wake up all contexts waiting on the dock.
|
/// Wake up all contexts waiting on the dock.
|
||||||
///
|
///
|
||||||
/// We copy the queue and post all notifications without requesting direct context
|
/// We post all notifications without requesting direct context
|
||||||
/// switches. This ensures everyone gets notified in a single transaction without
|
/// switches. This ensures everyone gets notified in a single
|
||||||
/// any interleaving during this process.
|
/// transaction without any interleaving during this process.
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::dock::notify_all()
|
ircd::ctx::dock::notify_all()
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
const auto copy(q);
|
q.for_each([](ctx &c)
|
||||||
for(const auto &c : copy)
|
{
|
||||||
ircd::ctx::notify(*c);
|
ircd::ctx::notify(c);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::dock::wait()
|
ircd::ctx::dock::wait()
|
||||||
{
|
{
|
||||||
const unwind remove
|
assert(current);
|
||||||
|
const unwind remove{[this]
|
||||||
{
|
{
|
||||||
std::bind(&dock::remove_self, this)
|
q.remove(current);
|
||||||
};
|
}};
|
||||||
|
|
||||||
q.emplace_back(&cur());
|
q.push_back(current);
|
||||||
ircd::ctx::wait();
|
ircd::ctx::wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,12 +130,13 @@ ircd::ctx::dock::wait(predicate&& pred)
|
||||||
if(pred())
|
if(pred())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const unwind remove
|
assert(current);
|
||||||
|
const unwind remove{[this]
|
||||||
{
|
{
|
||||||
std::bind(&dock::remove_self, this)
|
q.remove(current);
|
||||||
};
|
}};
|
||||||
|
|
||||||
q.emplace_back(&cur()); do
|
q.push_back(current); do
|
||||||
{
|
{
|
||||||
ircd::ctx::wait();
|
ircd::ctx::wait();
|
||||||
}
|
}
|
||||||
|
@ -152,12 +149,13 @@ ircd::ctx::dock::wait_for(const duration &dur)
|
||||||
{
|
{
|
||||||
static const duration zero(0);
|
static const duration zero(0);
|
||||||
|
|
||||||
const unwind remove
|
assert(current);
|
||||||
|
const unwind remove{[this]
|
||||||
{
|
{
|
||||||
std::bind(&dock::remove_self, this)
|
q.remove(current);
|
||||||
};
|
}};
|
||||||
|
|
||||||
q.emplace_back(&cur());
|
q.push_back(current);
|
||||||
return ircd::ctx::wait<std::nothrow_t>(dur) > zero? cv_status::no_timeout:
|
return ircd::ctx::wait<std::nothrow_t>(dur) > zero? cv_status::no_timeout:
|
||||||
cv_status::timeout;
|
cv_status::timeout;
|
||||||
}
|
}
|
||||||
|
@ -173,12 +171,13 @@ ircd::ctx::dock::wait_for(const duration &dur,
|
||||||
if(pred())
|
if(pred())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const unwind remove
|
assert(current);
|
||||||
|
const unwind remove{[this]
|
||||||
{
|
{
|
||||||
std::bind(&dock::remove_self, this)
|
q.remove(current);
|
||||||
};
|
}};
|
||||||
|
|
||||||
q.emplace_back(&cur()); do
|
q.push_back(current); do
|
||||||
{
|
{
|
||||||
const bool expired(ircd::ctx::wait<std::nothrow_t>(dur) <= zero);
|
const bool expired(ircd::ctx::wait<std::nothrow_t>(dur) <= zero);
|
||||||
|
|
||||||
|
@ -195,12 +194,13 @@ template<class time_point>
|
||||||
ircd::ctx::cv_status
|
ircd::ctx::cv_status
|
||||||
ircd::ctx::dock::wait_until(time_point&& tp)
|
ircd::ctx::dock::wait_until(time_point&& tp)
|
||||||
{
|
{
|
||||||
const unwind remove
|
assert(current);
|
||||||
|
const unwind remove{[this]
|
||||||
{
|
{
|
||||||
std::bind(&dock::remove_self, this)
|
q.remove(current);
|
||||||
};
|
}};
|
||||||
|
|
||||||
q.emplace_back(&cur());
|
q.push_back(current);
|
||||||
return ircd::ctx::wait_until<std::nothrow_t>(tp)? cv_status::timeout:
|
return ircd::ctx::wait_until<std::nothrow_t>(tp)? cv_status::timeout:
|
||||||
cv_status::no_timeout;
|
cv_status::no_timeout;
|
||||||
}
|
}
|
||||||
|
@ -214,12 +214,13 @@ ircd::ctx::dock::wait_until(time_point&& tp,
|
||||||
if(pred())
|
if(pred())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const unwind remove
|
assert(current);
|
||||||
|
const unwind remove{[this]
|
||||||
{
|
{
|
||||||
std::bind(&dock::remove_self, this)
|
q.remove(current);
|
||||||
};
|
}};
|
||||||
|
|
||||||
q.emplace_back(&cur()); do
|
q.push_back(current); do
|
||||||
{
|
{
|
||||||
const bool expired
|
const bool expired
|
||||||
{
|
{
|
||||||
|
@ -249,14 +250,6 @@ noexcept
|
||||||
ircd::ctx::notify(ctx);
|
ircd::ctx::notify(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
ircd::ctx::dock::remove_self()
|
|
||||||
{
|
|
||||||
const auto it(std::find(begin(q), end(q), &cur()));
|
|
||||||
assert(it != end(q));
|
|
||||||
q.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The number of contexts waiting in the queue.
|
/// The number of contexts waiting in the queue.
|
||||||
inline size_t
|
inline size_t
|
||||||
ircd::ctx::dock::size()
|
ircd::ctx::dock::size()
|
||||||
|
|
Loading…
Reference in a new issue