mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 16:22:35 +01:00
ircd::ctx: Add custom intrinsic list structure for contexts.
This commit is contained in:
parent
7c4659a99f
commit
df0e59a5e0
3 changed files with 380 additions and 0 deletions
|
@ -110,6 +110,7 @@ namespace ircd::ctx { inline namespace this_ctx
|
|||
|
||||
#include "context.h"
|
||||
#include "prof.h"
|
||||
#include "list.h"
|
||||
#include "dock.h"
|
||||
#include "queue.h"
|
||||
#include "mutex.h"
|
||||
|
|
153
include/ircd/ctx/list.h
Normal file
153
include/ircd/ctx/list.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2018 Jason Volk
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_CTX_LIST_H
|
||||
|
||||
namespace ircd::ctx
|
||||
{
|
||||
struct list;
|
||||
}
|
||||
|
||||
/// A special linked-list for contexts. Each ircd::ctx has space for one and
|
||||
/// only one node on its internal ctx::ctx structure. It can only participate
|
||||
/// in one ctx::list at a time. This forms the structural basis for mutexes,
|
||||
/// condition variables and other interleaving primitives which form queues
|
||||
/// of contexts.
|
||||
///
|
||||
/// This device is strictly for context switching purposes. It is minimal,
|
||||
/// usage is specific to this purpose, and not a general list to be used
|
||||
/// elsewhere. Furthermore, this is too lightweight for even the
|
||||
/// ircd::allocator::node strategy. Custom operations are implemented for
|
||||
/// maximum space efficiency in both the object instance and the ctx::ctx.
|
||||
///
|
||||
class ircd::ctx::list
|
||||
{
|
||||
ctx *head {nullptr};
|
||||
ctx *tail {nullptr};
|
||||
|
||||
// Get next or prev entry in ctx
|
||||
static const ctx *next(const ctx *const &);
|
||||
static const ctx *prev(const ctx *const &);
|
||||
static ctx *next(ctx *const &);
|
||||
static ctx *prev(ctx *const &);
|
||||
|
||||
public:
|
||||
const ctx *front() const;
|
||||
const ctx *back() const;
|
||||
ctx *front();
|
||||
ctx *back();
|
||||
|
||||
// until convention
|
||||
bool until(const std::function<bool (const ctx &)> &) const;
|
||||
bool until(const std::function<bool (ctx &)> &);
|
||||
|
||||
// reverse until convention
|
||||
bool runtil(const std::function<bool (const ctx &)> &) const;
|
||||
bool runtil(const std::function<bool (ctx &)> &);
|
||||
|
||||
// iteration
|
||||
void for_each(const std::function<void (const ctx &)> &) const;
|
||||
void for_each(const std::function<void (ctx &)> &);
|
||||
|
||||
// reverse iteration
|
||||
void rfor_each(const std::function<void (const ctx &)> &) const;
|
||||
void rfor_each(const std::function<void (ctx &)> &);
|
||||
|
||||
bool empty() const;
|
||||
size_t size() const;
|
||||
|
||||
void push_front(ctx *const & = current);
|
||||
void push_back(ctx *const & = current);
|
||||
void push(ctx *const & = current); // push_back
|
||||
|
||||
ctx *pop_front();
|
||||
ctx *pop_back();
|
||||
ctx *pop(); // pop_front
|
||||
|
||||
void remove(ctx *const & = current);
|
||||
|
||||
list() = default;
|
||||
~list() noexcept;
|
||||
};
|
||||
|
||||
inline
|
||||
ircd::ctx::list::~list()
|
||||
noexcept
|
||||
{
|
||||
assert(!head && !tail);
|
||||
}
|
||||
|
||||
inline ircd::ctx::ctx *
|
||||
ircd::ctx::list::pop()
|
||||
{
|
||||
return pop_front();
|
||||
}
|
||||
|
||||
inline void
|
||||
ircd::ctx::list::push(ctx *const &c)
|
||||
{
|
||||
push_back(c);
|
||||
}
|
||||
|
||||
inline size_t
|
||||
ircd::ctx::list::size()
|
||||
const
|
||||
{
|
||||
size_t i{0};
|
||||
for_each([&i](const ctx &)
|
||||
{
|
||||
++i;
|
||||
});
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ircd::ctx::list::empty()
|
||||
const
|
||||
{
|
||||
return !head;
|
||||
}
|
||||
|
||||
inline ircd::ctx::ctx *
|
||||
ircd::ctx::list::back()
|
||||
{
|
||||
return tail;
|
||||
}
|
||||
|
||||
inline ircd::ctx::ctx *
|
||||
ircd::ctx::list::front()
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
inline const ircd::ctx::ctx *
|
||||
ircd::ctx::list::back()
|
||||
const
|
||||
{
|
||||
return tail;
|
||||
}
|
||||
|
||||
inline const ircd::ctx::ctx *
|
||||
ircd::ctx::list::front()
|
||||
const
|
||||
{
|
||||
return head;
|
||||
}
|
226
ircd/ctx.cc
226
ircd/ctx.cc
|
@ -43,6 +43,8 @@ struct ircd::ctx::ctx
|
|||
int64_t notes; // norm: 0 = asleep; 1 = awake; inc by others; dec by self
|
||||
ctx *adjoindre; // context waiting for this to join()
|
||||
microseconds awake; // monotonic counter
|
||||
ctx *next; // next node in a ctx::list
|
||||
ctx *prev; // prev node in a ctx::list
|
||||
|
||||
bool started() const { return stack_base != 0; }
|
||||
bool finished() const { return started() && yc == nullptr; }
|
||||
|
@ -89,6 +91,8 @@ ircd::ctx::ctx::ctx(const char *const &name,
|
|||
,notes{1}
|
||||
,adjoindre{nullptr}
|
||||
,awake{0us}
|
||||
,next{nullptr}
|
||||
,prev{nullptr}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1050,6 +1054,228 @@ ircd::ctx::ole::pop()
|
|||
return std::move(c);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ctx_list.h
|
||||
//
|
||||
|
||||
void
|
||||
ircd::ctx::list::remove(ctx *const &c)
|
||||
{
|
||||
assert(c);
|
||||
|
||||
if(c == head)
|
||||
{
|
||||
pop_front();
|
||||
return;
|
||||
}
|
||||
|
||||
if(c == tail)
|
||||
{
|
||||
pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(c->next && c->prev);
|
||||
c->next->prev = c->prev;
|
||||
c->prev->next = c->next;
|
||||
c->next = nullptr;
|
||||
c->prev = nullptr;
|
||||
}
|
||||
|
||||
ircd::ctx::ctx *
|
||||
ircd::ctx::list::pop_back()
|
||||
{
|
||||
const auto tail
|
||||
{
|
||||
this->tail
|
||||
};
|
||||
|
||||
if(!tail)
|
||||
return tail;
|
||||
|
||||
assert(!tail->next);
|
||||
if(!tail->prev)
|
||||
{
|
||||
this->head = nullptr;
|
||||
this->tail = nullptr;
|
||||
} else {
|
||||
assert(tail->prev->next == tail);
|
||||
tail->prev->next = nullptr;
|
||||
this->tail = tail->prev;
|
||||
}
|
||||
|
||||
tail->prev = nullptr;
|
||||
tail->next = nullptr;
|
||||
return tail;
|
||||
}
|
||||
|
||||
ircd::ctx::ctx *
|
||||
ircd::ctx::list::pop_front()
|
||||
{
|
||||
const auto head
|
||||
{
|
||||
this->head
|
||||
};
|
||||
|
||||
if(!head)
|
||||
return head;
|
||||
|
||||
assert(!head->prev);
|
||||
if(!head->next)
|
||||
{
|
||||
this->head = nullptr;
|
||||
this->tail = nullptr;
|
||||
} else {
|
||||
assert(head->next->prev == head);
|
||||
head->next->prev = nullptr;
|
||||
this->head = head->next;
|
||||
}
|
||||
|
||||
head->prev = nullptr;
|
||||
head->next = nullptr;
|
||||
return head;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ctx::list::push_front(ctx *const &c)
|
||||
{
|
||||
assert(c->next == nullptr);
|
||||
assert(c->prev == nullptr);
|
||||
|
||||
if(!head)
|
||||
{
|
||||
head = c;
|
||||
tail = c;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(head->prev == nullptr);
|
||||
head->prev = c;
|
||||
c->next = head;
|
||||
head = c;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ctx::list::push_back(ctx *const &c)
|
||||
{
|
||||
assert(c->next == nullptr);
|
||||
assert(c->prev == nullptr);
|
||||
|
||||
if(!tail)
|
||||
{
|
||||
assert(!head);
|
||||
head = c;
|
||||
tail = c;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(tail->next == nullptr);
|
||||
tail->next = c;
|
||||
c->prev = tail;
|
||||
tail = c;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ctx::list::rfor_each(const std::function<void (ctx &)> &closure)
|
||||
{
|
||||
for(ctx *tail{this->tail}; tail; tail = prev(tail))
|
||||
closure(*tail);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ctx::list::rfor_each(const std::function<void (const ctx &)> &closure)
|
||||
const
|
||||
{
|
||||
for(const ctx *tail{this->tail}; tail; tail = prev(tail))
|
||||
closure(*tail);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ctx::list::for_each(const std::function<void (ctx &)> &closure)
|
||||
{
|
||||
for(ctx *head{this->head}; head; head = next(head))
|
||||
closure(*head);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ctx::list::for_each(const std::function<void (const ctx &)> &closure)
|
||||
const
|
||||
{
|
||||
for(const ctx *head{this->head}; head; head = next(head))
|
||||
closure(*head);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::ctx::list::runtil(const std::function<bool (ctx &)> &closure)
|
||||
{
|
||||
for(ctx *tail{this->tail}; tail; tail = prev(tail))
|
||||
if(!closure(*tail))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::ctx::list::runtil(const std::function<bool (const ctx &)> &closure)
|
||||
const
|
||||
{
|
||||
for(const ctx *tail{this->tail}; tail; tail = prev(tail))
|
||||
if(!closure(*tail))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::ctx::list::until(const std::function<bool (ctx &)> &closure)
|
||||
{
|
||||
for(ctx *head{this->head}; head; head = next(head))
|
||||
if(!closure(*head))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::ctx::list::until(const std::function<bool (const ctx &)> &closure)
|
||||
const
|
||||
{
|
||||
for(const ctx *head{this->head}; head; head = next(head))
|
||||
if(!closure(*head))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ircd::ctx::ctx *
|
||||
ircd::ctx::list::prev(ctx *const &c)
|
||||
{
|
||||
assert(c);
|
||||
return c->prev;
|
||||
}
|
||||
|
||||
ircd::ctx::ctx *
|
||||
ircd::ctx::list::next(ctx *const &c)
|
||||
{
|
||||
assert(c);
|
||||
return c->next;
|
||||
}
|
||||
|
||||
const ircd::ctx::ctx *
|
||||
ircd::ctx::list::prev(const ctx *const &c)
|
||||
{
|
||||
assert(c);
|
||||
return c->prev;
|
||||
}
|
||||
|
||||
const ircd::ctx::ctx *
|
||||
ircd::ctx::list::next(const ctx *const &c)
|
||||
{
|
||||
assert(c);
|
||||
return c->next;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ircd/ios.h
|
||||
|
|
Loading…
Reference in a new issue