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:
parent
3fae228c1a
commit
4871928bfa
2 changed files with 121 additions and 117 deletions
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
110
ircd/ctx.cc
110
ircd/ctx.cc
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue