0
0
Fork 0
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:
Jason Volk 2018-01-13 23:14:23 -08:00
parent df0e59a5e0
commit dcd36f8200

View file

@ -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()