2018-03-11 19:35:40 +01:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
2018-01-14 08:10:44 +01:00
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
2018-03-11 19:35:40 +01:00
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
2018-01-14 08:10:44 +01:00
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
2018-03-11 19:35:40 +01:00
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
2018-01-14 08:10:44 +01:00
|
|
|
|
|
|
|
#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.
|
|
|
|
///
|
2018-04-20 00:14:49 +02:00
|
|
|
struct ircd::ctx::list
|
2018-01-14 08:10:44 +01:00
|
|
|
{
|
2018-04-20 00:14:49 +02:00
|
|
|
struct node;
|
2019-09-10 19:42:25 +02:00
|
|
|
using closure_bool_const = std::function<bool (const ctx &)>;
|
|
|
|
using closure_const = std::function<void (const ctx &)>;
|
|
|
|
using closure_bool = std::function<bool (ctx &)>;
|
|
|
|
using closure = std::function<void (ctx &)>;
|
2018-04-20 00:14:49 +02:00
|
|
|
|
|
|
|
private:
|
2018-01-14 08:10:44 +01:00
|
|
|
ctx *head {nullptr};
|
|
|
|
ctx *tail {nullptr};
|
|
|
|
|
2020-08-23 04:37:51 +02:00
|
|
|
static const node &get(const ctx &) noexcept;
|
|
|
|
static node &get(ctx &) noexcept;
|
2020-07-12 03:21:38 +02:00
|
|
|
|
2018-01-14 08:10:44 +01:00
|
|
|
// Get next or prev entry in ctx
|
2019-09-10 19:19:50 +02:00
|
|
|
static const ctx *next(const ctx *const &) noexcept;
|
|
|
|
static const ctx *prev(const ctx *const &) noexcept;
|
|
|
|
static ctx *&next(ctx *const &) noexcept;
|
|
|
|
static ctx *&prev(ctx *const &) noexcept;
|
2018-01-14 08:10:44 +01:00
|
|
|
|
|
|
|
public:
|
2019-09-10 19:19:50 +02:00
|
|
|
const ctx *front() const noexcept;
|
|
|
|
const ctx *back() const noexcept;
|
|
|
|
ctx *front() noexcept;
|
|
|
|
ctx *back() noexcept;
|
2018-01-14 08:10:44 +01:00
|
|
|
|
|
|
|
// iteration
|
2019-09-10 19:42:25 +02:00
|
|
|
bool for_each(const closure_bool_const &) const;
|
|
|
|
void for_each(const closure_const &) const;
|
|
|
|
bool for_each(const closure_bool &);
|
|
|
|
void for_each(const closure &);
|
2018-01-14 08:10:44 +01:00
|
|
|
|
|
|
|
// reverse iteration
|
2019-09-10 19:42:25 +02:00
|
|
|
bool rfor_each(const closure_bool_const &) const;
|
|
|
|
void rfor_each(const closure_const &) const;
|
|
|
|
bool rfor_each(const closure_bool &);
|
|
|
|
void rfor_each(const closure &);
|
2018-01-14 08:10:44 +01:00
|
|
|
|
2019-09-10 19:19:50 +02:00
|
|
|
bool empty() const noexcept;
|
|
|
|
size_t size() const noexcept;
|
2018-01-14 08:10:44 +01:00
|
|
|
|
2019-09-10 19:19:50 +02:00
|
|
|
void push_front(ctx *const & = current) noexcept;
|
|
|
|
void push_back(ctx *const & = current) noexcept;
|
|
|
|
void push(ctx *const & = current) noexcept; // push_back
|
2018-01-14 08:10:44 +01:00
|
|
|
|
2019-09-10 19:19:50 +02:00
|
|
|
ctx *pop_front() noexcept;
|
|
|
|
ctx *pop_back() noexcept;
|
|
|
|
ctx *pop() noexcept; // pop_front
|
2018-01-14 08:10:44 +01:00
|
|
|
|
2019-09-10 19:19:50 +02:00
|
|
|
void remove(ctx *const & = current) noexcept;
|
2018-01-14 08:10:44 +01:00
|
|
|
|
|
|
|
list() = default;
|
2018-01-17 11:49:55 +01:00
|
|
|
list(list &&) noexcept;
|
|
|
|
list(const list &) = delete;
|
|
|
|
list &operator=(list &&) noexcept;
|
|
|
|
list &operator=(const list &) = delete;
|
2018-01-14 08:10:44 +01:00
|
|
|
~list() noexcept;
|
|
|
|
};
|
|
|
|
|
2018-04-20 00:14:49 +02:00
|
|
|
struct ircd::ctx::list::node
|
|
|
|
{
|
|
|
|
ctx *prev {nullptr};
|
|
|
|
ctx *next {nullptr};
|
|
|
|
};
|
|
|
|
|
2018-01-17 11:49:55 +01:00
|
|
|
inline
|
|
|
|
ircd::ctx::list::list(list &&o)
|
|
|
|
noexcept
|
|
|
|
:head{std::move(o.head)}
|
|
|
|
,tail{std::move(o.tail)}
|
|
|
|
{
|
|
|
|
o.head = nullptr;
|
|
|
|
o.tail = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
|
|
|
ircd::ctx::list &
|
|
|
|
ircd::ctx::list::operator=(list &&o)
|
|
|
|
noexcept
|
|
|
|
{
|
|
|
|
this->~list();
|
2018-11-14 02:45:08 +01:00
|
|
|
head = std::move(o.head);
|
|
|
|
tail = std::move(o.tail);
|
|
|
|
o.head = nullptr;
|
|
|
|
o.tail = nullptr;
|
2018-01-17 11:49:55 +01:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-01-14 08:10:44 +01:00
|
|
|
inline
|
|
|
|
ircd::ctx::list::~list()
|
|
|
|
noexcept
|
|
|
|
{
|
2018-01-17 11:58:57 +01:00
|
|
|
assert(empty());
|
2018-01-14 08:10:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline ircd::ctx::ctx *
|
|
|
|
ircd::ctx::list::pop()
|
2019-09-10 19:19:50 +02:00
|
|
|
noexcept
|
2018-01-14 08:10:44 +01:00
|
|
|
{
|
|
|
|
return pop_front();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
ircd::ctx::list::push(ctx *const &c)
|
2019-09-10 19:19:50 +02:00
|
|
|
noexcept
|
2018-01-14 08:10:44 +01:00
|
|
|
{
|
|
|
|
push_back(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
ircd::ctx::list::empty()
|
2019-09-10 19:19:50 +02:00
|
|
|
const noexcept
|
2018-01-14 08:10:44 +01:00
|
|
|
{
|
2018-01-17 11:58:57 +01:00
|
|
|
assert((!head && !tail) || (head && tail));
|
2018-01-14 08:10:44 +01:00
|
|
|
return !head;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline ircd::ctx::ctx *
|
|
|
|
ircd::ctx::list::back()
|
2019-09-10 19:19:50 +02:00
|
|
|
noexcept
|
2018-01-14 08:10:44 +01:00
|
|
|
{
|
|
|
|
return tail;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline ircd::ctx::ctx *
|
|
|
|
ircd::ctx::list::front()
|
2019-09-10 19:19:50 +02:00
|
|
|
noexcept
|
2018-01-14 08:10:44 +01:00
|
|
|
{
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const ircd::ctx::ctx *
|
|
|
|
ircd::ctx::list::back()
|
2019-09-10 19:19:50 +02:00
|
|
|
const noexcept
|
2018-01-14 08:10:44 +01:00
|
|
|
{
|
|
|
|
return tail;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const ircd::ctx::ctx *
|
|
|
|
ircd::ctx::list::front()
|
2019-09-10 19:19:50 +02:00
|
|
|
const noexcept
|
2018-01-14 08:10:44 +01:00
|
|
|
{
|
|
|
|
return head;
|
|
|
|
}
|
2020-07-12 03:21:38 +02:00
|
|
|
|
|
|
|
inline ircd::ctx::ctx *&
|
|
|
|
ircd::ctx::list::prev(ctx *const &c)
|
|
|
|
noexcept
|
|
|
|
{
|
|
|
|
assert(c);
|
|
|
|
return get(*c).prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline ircd::ctx::ctx *&
|
|
|
|
ircd::ctx::list::next(ctx *const &c)
|
|
|
|
noexcept
|
|
|
|
{
|
|
|
|
assert(c);
|
|
|
|
return get(*c).next;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const ircd::ctx::ctx *
|
|
|
|
ircd::ctx::list::prev(const ctx *const &c)
|
|
|
|
noexcept
|
|
|
|
{
|
|
|
|
assert(c);
|
|
|
|
return get(*c).prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const ircd::ctx::ctx *
|
|
|
|
ircd::ctx::list::next(const ctx *const &c)
|
|
|
|
noexcept
|
|
|
|
{
|
|
|
|
assert(c);
|
|
|
|
return get(*c).next;
|
|
|
|
}
|