0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-17 23:40:57 +01:00

ircd::ctx: Partial de-inline of dock methods.

This commit is contained in:
Jason Volk 2019-01-13 13:57:34 -08:00
parent 3fae228c1a
commit 4871928bfa
2 changed files with 121 additions and 117 deletions

View file

@ -21,6 +21,8 @@ namespace ircd::ctx
/// ///
class ircd::ctx::dock class ircd::ctx::dock
{ {
using predicate = std::function<bool ()>;
list q; list q;
void notify(ctx &) noexcept; void notify(ctx &) noexcept;
@ -29,13 +31,13 @@ class ircd::ctx::dock
bool empty() const; bool empty() const;
size_t size() const; size_t size() const;
template<class time_point, class predicate> bool wait_until(time_point&& tp, predicate&& pred); template<class time_point> bool wait_until(time_point&&, const predicate &);
template<class time_point> bool wait_until(time_point&& tp); template<class time_point> bool wait_until(time_point&&);
template<class duration, class predicate> bool wait_for(const duration &dur, predicate&& pred); template<class duration> bool wait_for(const duration &, const predicate &);
template<class duration> bool wait_for(const duration &dur); template<class duration> bool wait_for(const duration &);
template<class predicate> void wait(predicate&& pred); void wait(const predicate &);
void wait(); void wait();
void notify_all() noexcept; void notify_all() noexcept;
@ -43,89 +45,6 @@ class ircd::ctx::dock
void notify() noexcept; void notify() noexcept;
}; };
/// Wake up the next context waiting on the dock
///
/// Unlike notify_one(), the next context in the queue is repositioned in the
/// back before being woken up for fairness.
inline void
ircd::ctx::dock::notify()
noexcept
{
ctx *c;
if(!(c = q.pop_front()))
return;
q.push_back(c);
notify(*c);
}
/// Wake up the next context waiting on the dock
inline void
ircd::ctx::dock::notify_one()
noexcept
{
if(!q.empty())
notify(*q.front());
}
/// Wake up all contexts waiting on the dock.
///
/// We post all notifications without requesting direct context
/// switches. This ensures everyone gets notified in a single
/// transaction without any interleaving during this process.
inline void
ircd::ctx::dock::notify_all()
noexcept
{
q.for_each([this](ctx &c)
{
notify(c);
});
}
inline void
ircd::ctx::dock::wait()
{
assert(current);
const unwind::exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current);
ircd::ctx::wait();
}
template<class predicate>
void
ircd::ctx::dock::wait(predicate&& pred)
{
if(pred())
return;
assert(current);
const unwind::exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current); do
{
ircd::ctx::wait();
}
while(!pred());
}
/// Returns true if notified; false if timed out /// Returns true if notified; false if timed out
template<class duration> template<class duration>
bool bool
@ -149,11 +68,10 @@ ircd::ctx::dock::wait_for(const duration &dur)
} }
/// Returns true if predicate passed; false if timed out /// Returns true if predicate passed; false if timed out
template<class duration, template<class duration>
class predicate>
bool bool
ircd::ctx::dock::wait_for(const duration &dur, ircd::ctx::dock::wait_for(const duration &dur,
predicate&& pred) const predicate &pred)
{ {
static const duration zero(0); static const duration zero(0);
@ -208,11 +126,10 @@ ircd::ctx::dock::wait_until(time_point&& tp)
} }
/// Returns true if predicate passed; false if timed out /// Returns true if predicate passed; false if timed out
template<class time_point, template<class time_point>
class predicate>
bool bool
ircd::ctx::dock::wait_until(time_point&& tp, ircd::ctx::dock::wait_until(time_point&& tp,
predicate&& pred) const predicate &pred)
{ {
if(pred()) if(pred())
return true; return true;
@ -243,26 +160,3 @@ ircd::ctx::dock::wait_until(time_point&& tp,
} }
while(1); while(1);
} }
inline void
ircd::ctx::dock::notify(ctx &ctx)
noexcept
{
ircd::ctx::notify(ctx);
}
/// The number of contexts waiting in the queue.
inline size_t
ircd::ctx::dock::size()
const
{
return q.size();
}
/// The number of contexts waiting in the queue.
inline bool
ircd::ctx::dock::empty()
const
{
return q.empty();
}

View file

@ -2349,6 +2349,116 @@ noexcept
then = {}; then = {};
} }
///////////////////////////////////////////////////////////////////////////////
//
// dock.h
//
/// Wake up the next context waiting on the dock
///
/// Unlike notify_one(), the next context in the queue is repositioned in the
/// back before being woken up for fairness.
void
ircd::ctx::dock::notify()
noexcept
{
ctx *c;
if(!(c = q.pop_front()))
return;
q.push_back(c);
notify(*c);
}
/// Wake up the next context waiting on the dock
void
ircd::ctx::dock::notify_one()
noexcept
{
if(!q.empty())
notify(*q.front());
}
/// Wake up all contexts waiting on the dock.
///
/// We post all notifications without requesting direct context
/// switches. This ensures everyone gets notified in a single
/// transaction without any interleaving during this process.
void
ircd::ctx::dock::notify_all()
noexcept
{
q.for_each([this](ctx &c)
{
notify(c);
});
}
void
ircd::ctx::dock::wait()
{
assert(current);
const unwind::exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current);
ircd::ctx::wait();
}
void
ircd::ctx::dock::wait(const predicate &pred)
{
if(pred())
return;
assert(current);
const unwind::exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current); do
{
ircd::ctx::wait();
}
while(!pred());
}
void
ircd::ctx::dock::notify(ctx &ctx)
noexcept
{
ircd::ctx::notify(ctx);
}
/// The number of contexts waiting in the queue.
size_t
ircd::ctx::dock::size()
const
{
return q.size();
}
/// The number of contexts waiting in the queue.
bool
ircd::ctx::dock::empty()
const
{
return q.empty();
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// ctx_list.h // ctx_list.h