Files
moslab-code/src/l4/pkg/l4re-core/cxx/lib/tl/include/hlist
2025-09-12 15:55:45 +02:00

272 lines
6.3 KiB
C++

// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* (c) 2011 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include "bits/list_basics.h"
#include "type_traits"
namespace cxx {
/**
* Basic element type for a double-linked H_list.
*
* \tparam ELEM_TYPE Base class of the list element.
*/
template<typename ELEM_TYPE>
class H_list_item_t
{
public:
/**
* Constructor.
*
* Creates an element that is not in any list.
*/
H_list_item_t() : _n(0), _pn(0) {}
/**
* Destructor.
*
* Automatically removes the element from any list it still might be
* enchained in.
*/
~H_list_item_t() noexcept { l_remove(); }
private:
H_list_item_t(H_list_item_t const &) = delete;
template<typename T, typename P> friend class H_list;
template<typename T, typename X> friend struct Bits::Basic_list_policy;
void l_remove() noexcept
{
if (!_pn)
return;
*_pn = _n;
if (_n)
_n->_pn = _pn;
_pn = 0;
}
H_list_item_t *_n, **_pn;
};
/** Untyped list item. */
typedef H_list_item_t<void> H_list_item;
/**
* General double-linked list of unspecified cxx::H_list_item elements.
*
* Most of the time, you want to use H_list_t.
*/
template< typename T, typename POLICY = Bits::Basic_list_policy< T, H_list_item> >
class H_list : public Bits::Basic_list<POLICY>
{
private:
typedef typename POLICY::Item_type Item;
typedef Bits::Basic_list<POLICY> Base;
H_list(H_list const &);
void operator = (H_list const &);
public:
typedef typename Base::Iterator Iterator;
// BSS allocation
explicit H_list(bool x) : Base(x) {}
H_list() : Base() {}
/**
* Return an iterator for an arbitrary list element
*
* \param c List element to start the iteration.
*
* \return A mutable forward iterator.
*
* \pre The element must be in a list.
*/
static Iterator iter(T *c) { return Base::__iter(c->Item::_pn); }
/// Check if the given element is currently part of a list.
static bool in_list(T const *e) { return e->Item::_pn; }
/// Add element to the front of the list.
void add(T *e)
{
if (this->_f)
this->_f->_pn = &e->Item::_n;
e->Item::_n = this->_f;
e->Item::_pn = &this->_f;
this->_f = static_cast<Item*>(e);
}
/// Add element to the front of the list.
void push_front(T *e) { add(e); }
/**
* Remove and return the head element of the list.
*
* \pre The list must not be empty or the behaviour will be undefined.
*/
T *pop_front()
{
T *r = this->front();
remove(r);
return r;
}
/**
* Insert an element at the iterator position.
*
* \param e New Element to be inserted
* \param pred Iterator pointing to the element after which the
* element will be inserted. If end() is given, the
* element will be inserted at the beginning of the queue.
*
* \return Iterator pointing to the newly inserted element.
*/
Iterator insert(T *e, Iterator const &pred)
{
Item **x = &this->_f;
if (pred != Base::end())
x = &(*pred)->_n;
e->Item::_n = *x;
if (*x)
(*x)->_pn = &(e->Item::_n);
e->Item::_pn = x;
*x = static_cast<Item*>(e);
return iter(e);
}
/**
* Insert an element after the iterator position.
*
* \param e New element to be inserted.
* \param pred Iterator pointing to the element after which the
* element will be inserted. Must not be end().
*
* \return Iterator pointing to the newly inserted element.
*
* \pre The list must not be empty.
*/
static Iterator insert_after(T *e, Iterator const &pred)
{
Item **x = &(*pred)->_n;
e->Item::_n = *x;
if (*x)
(*x)->_pn = &(e->Item::_n);
e->Item::_pn = x;
*x = static_cast<Item*>(e);
return iter(e);
}
/**
* Insert an element before the iterator position.
*
* \param e New element to be inserted.
* \param succ Iterator pointing to the element before which the
* element will be inserted. Must not be end().
*/
static void insert_before(T *e, Iterator const &succ)
{
Item **x = Base::__get_internal(succ);
e->Item::_n = *x;
e->Item::_pn = x;
if (*x)
(*x)->_pn = &e->Item::_n;
*x = static_cast<Item*>(e);
}
/**
* Replace an element in a list with a new element.
*
* \param p Element in list to be replaced.
* \param e Replacement element, must not yet be in a list.
*
* \pre `p` and `e` must not be NULL.
*
* After the operation the p element is no longer in the
* list and may be reused.
*/
static void replace(T *p, T *e)
{
e->Item::_n = p->Item::_n;
e->Item::_pn = p->Item::_pn;
*(p->Item::_pn) = static_cast<Item*>(e);
if (e->Item::_n)
e->Item::_n->_pn = &(e->Item::_n);
p->Item::_pn = 0;
}
/**
* Remove the given element from its list.
*
* \param e Element to be removed. Must be in a list.
*/
static void remove(T *e)
{ e->Item::l_remove(); }
/**
* Remove the element at the given iterator position.
*
* \param e Iterator pointing to the element to be removed. Must not
* point to end().
*
* \return New iterator pointing to the element after the removed one.
*
* \note The hlist implementation guarantees that the original iterator
* is still valid after the element has been removed. In fact, the
* iterator returned is the same as the one supplied in the `e`
* parameter.
*/
static Iterator erase(Iterator const &e)
{ e->Item::l_remove(); return e; }
};
/**
* Double-linked list of typed H_list_item_t elements.
*
* \note H_lists are not self-cleaning. Elements that are still chained
* during destruction are not removed and will therefore be in an
* undefined state after the destruction.
*/
template< typename T >
struct H_list_t : H_list<T, Bits::Basic_list_policy< T, H_list_item_t<T> > >
{
H_list_t() = default;
H_list_t(bool b)
: H_list<T, Bits::Basic_list_policy< T, H_list_item_t<T> > >(b)
{};
};
template< typename T >
class H_list_bss : public H_list<T>
{
public:
H_list_bss() : H_list<T>(true) {}
};
template< typename T >
class H_list_t_bss : public H_list_t<T>
{
public:
H_list_t_bss() : H_list_t<T>(true) {}
};
}