mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd::ctx::dock: Add options for waiters; support queuing strategies.
This commit is contained in:
parent
96d5b6fe57
commit
e961b23d1e
2 changed files with 65 additions and 28 deletions
|
@ -23,11 +23,13 @@ namespace ircd::ctx
|
|||
/// dock is a condition variable which has no requirement for locking because
|
||||
/// the context system does not require mutual exclusion for coherence.
|
||||
///
|
||||
class ircd::ctx::dock
|
||||
struct ircd::ctx::dock
|
||||
{
|
||||
enum opts :uint;
|
||||
struct continuation;
|
||||
using predicate = std::function<bool ()>;
|
||||
|
||||
private:
|
||||
list q;
|
||||
|
||||
public:
|
||||
|
@ -35,14 +37,14 @@ class ircd::ctx::dock
|
|||
size_t size() const noexcept;
|
||||
bool waiting(const ctx &) const noexcept;
|
||||
|
||||
bool wait_until(const system_point, const predicate &);
|
||||
bool wait_until(const system_point);
|
||||
bool wait_until(const system_point, const predicate &, const opts = (opts)0);
|
||||
bool wait_until(const system_point, const opts = (opts)0);
|
||||
|
||||
template<class duration> bool wait_for(const duration, const predicate &);
|
||||
template<class duration> bool wait_for(const duration);
|
||||
template<class duration> bool wait_for(const duration, const predicate &, const opts = (opts)0);
|
||||
template<class duration> bool wait_for(const duration, const opts = (opts)0);
|
||||
|
||||
void wait(const predicate &);
|
||||
void wait();
|
||||
void wait(const predicate &, const opts = (opts)0);
|
||||
void wait(const opts = (opts)0);
|
||||
|
||||
void terminate_all() noexcept;
|
||||
void interrupt_all() noexcept;
|
||||
|
@ -53,19 +55,40 @@ class ircd::ctx::dock
|
|||
|
||||
namespace ircd::ctx
|
||||
{
|
||||
template<> bool dock::wait_for(const microseconds, const predicate &);
|
||||
template<> bool dock::wait_for(const microseconds);
|
||||
template<> bool dock::wait_for(const microseconds, const predicate &, const opts);
|
||||
template<> bool dock::wait_for(const microseconds, const opts);
|
||||
}
|
||||
|
||||
struct [[gnu::visibility("internal")]]
|
||||
ircd::ctx::dock::continuation
|
||||
{
|
||||
dock *const d;
|
||||
const opts *const o;
|
||||
|
||||
continuation(dock *);
|
||||
continuation(dock *, const opts &opts);
|
||||
~continuation() noexcept;
|
||||
};
|
||||
|
||||
/// Options. These are bitflags for forward compatibility with unrelated opts
|
||||
/// even though some flags are exclusive to others.
|
||||
enum ircd::ctx::dock::opts
|
||||
:uint
|
||||
{
|
||||
/// No options.
|
||||
NONE = 0x00,
|
||||
|
||||
/// Waiting context will add itself to back of queue. This is the default.
|
||||
FIFO = 0x01,
|
||||
|
||||
/// Waiting context will add itself to front of queue. The default is FIFO
|
||||
/// for fair queuing preventing starvation.
|
||||
LIFO = 0x02,
|
||||
|
||||
/// Waiting context will add itself to front if its ID is lower than the
|
||||
/// front, otherwise back.
|
||||
SORT = 0x04,
|
||||
};
|
||||
|
||||
/// Wake up the next context waiting on the dock
|
||||
inline void
|
||||
ircd::ctx::dock::notify_one()
|
||||
|
@ -80,18 +103,20 @@ noexcept
|
|||
template<class duration>
|
||||
inline bool
|
||||
ircd::ctx::dock::wait_for(const duration dur,
|
||||
const predicate &pred)
|
||||
const predicate &pred,
|
||||
const opts opts)
|
||||
{
|
||||
static_assert(!std::is_same<duration, microseconds>());
|
||||
return wait_for(duration_cast<microseconds>(dur), pred);
|
||||
return wait_for(duration_cast<microseconds>(dur), pred, opts);
|
||||
}
|
||||
|
||||
template<class duration>
|
||||
inline bool
|
||||
ircd::ctx::dock::wait_for(const duration dur)
|
||||
ircd::ctx::dock::wait_for(const duration dur,
|
||||
const opts opts)
|
||||
{
|
||||
static_assert(!std::is_same<duration, microseconds>());
|
||||
return wait_for(duration_cast<microseconds>(dur));
|
||||
return wait_for(duration_cast<microseconds>(dur), opts);
|
||||
}
|
||||
|
||||
|
||||
|
|
40
ircd/ctx.cc
40
ircd/ctx.cc
|
@ -2853,19 +2853,20 @@ noexcept
|
|||
}
|
||||
|
||||
void
|
||||
ircd::ctx::dock::wait()
|
||||
ircd::ctx::dock::wait(const opts opts)
|
||||
{
|
||||
const continuation c{this};
|
||||
const continuation c{this, opts};
|
||||
this_ctx::wait();
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ctx::dock::wait(const predicate &pred)
|
||||
ircd::ctx::dock::wait(const predicate &pred,
|
||||
const opts opts)
|
||||
{
|
||||
if(pred())
|
||||
return;
|
||||
|
||||
const continuation c{this}; do
|
||||
const continuation c{this, opts}; do
|
||||
{
|
||||
this_ctx::wait();
|
||||
}
|
||||
|
@ -2874,25 +2875,27 @@ ircd::ctx::dock::wait(const predicate &pred)
|
|||
|
||||
template<>
|
||||
bool
|
||||
ircd::ctx::dock::wait_for(const microseconds dur)
|
||||
ircd::ctx::dock::wait_for(const microseconds dur,
|
||||
const opts opts)
|
||||
{
|
||||
static const microseconds zero {0};
|
||||
|
||||
const continuation c{this};
|
||||
const continuation c{this, opts};
|
||||
return ircd::ctx::wait<std::nothrow_t>(dur) > zero;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
ircd::ctx::dock::wait_for(const microseconds dur,
|
||||
const predicate &pred)
|
||||
const predicate &pred,
|
||||
const opts opts)
|
||||
{
|
||||
static const microseconds zero {0};
|
||||
|
||||
if(pred())
|
||||
return true;
|
||||
|
||||
const continuation c{this}; do
|
||||
const continuation c{this, opts}; do
|
||||
{
|
||||
const bool expired
|
||||
{
|
||||
|
@ -2909,21 +2912,23 @@ ircd::ctx::dock::wait_for(const microseconds dur,
|
|||
}
|
||||
|
||||
bool
|
||||
ircd::ctx::dock::wait_until(const system_point tp)
|
||||
ircd::ctx::dock::wait_until(const system_point tp,
|
||||
const opts opts)
|
||||
{
|
||||
const continuation c{this};
|
||||
const continuation c{this, opts};
|
||||
return !ircd::ctx::wait_until<std::nothrow_t>(tp);
|
||||
}
|
||||
|
||||
/// Returns true if predicate passed; false if timed out
|
||||
bool
|
||||
ircd::ctx::dock::wait_until(const system_point tp,
|
||||
const predicate &pred)
|
||||
const predicate &pred,
|
||||
const opts opts)
|
||||
{
|
||||
if(pred())
|
||||
return true;
|
||||
|
||||
const continuation c{this}; do
|
||||
const continuation c{this, opts}; do
|
||||
{
|
||||
const bool expired
|
||||
{
|
||||
|
@ -2957,13 +2962,20 @@ const noexcept
|
|||
// dock::continuation
|
||||
//
|
||||
|
||||
ircd::ctx::dock::continuation::continuation(dock *const d)
|
||||
ircd::ctx::dock::continuation::continuation(dock *const d,
|
||||
const opts &opts)
|
||||
:d{d}
|
||||
,o{&opts}
|
||||
{
|
||||
assert(d);
|
||||
assert(current);
|
||||
|
||||
d->q.push_back(current);
|
||||
if(opts & opts::LIFO)
|
||||
d->q.push_front(current);
|
||||
else if(opts & opts::SORT)
|
||||
d->q.push_sort(current);
|
||||
else
|
||||
d->q.push_back(current);
|
||||
}
|
||||
|
||||
ircd::ctx::dock::continuation::~continuation()
|
||||
|
|
Loading…
Reference in a new issue