/******************************************************************//**
@file include/ut0lst.h
List utilities
Created 9/10/1995 Heikki Tuuri
Rewritten by Sunny Bains Dec 2011.
***********************************************************************/
#pragma once
/* Do not include univ.i because univ.i includes this. */
#include"ut0dbg.h"
/* This module implements the two-way linear list. Note that a single listnodemaybelongtotwoormorelists,butisonlyononelist
at a time. */
/*******************************************************************//**
The two way list node.
@param TYPE the list node type name */ template <typename Type> struct ut_list_node {
Type* prev; /*!< pointer to the previous
node, NULL if start of list */
Type* next; /*!< pointer to next node,
NULL if end of list */
/** Macro used for legacy reasons */ #define UT_LIST_NODE_T(t) ut_list_node<t>
/*******************************************************************//**
The two-way list base node. The base node contains pointers to both ends
of the list and a count of nodes in the list (excluding the base node
from the count). We also store a pointer to the member field so that it
doesn't have to be specified when doing list operations.
@param Type the type of the list element
@param NodePtr field member pointer that points to the list node */ template <typename Type, typename NodePtr> struct ut_list_base { typedef Type elem_type; typedef NodePtr node_ptr; typedef ut_list_node<Type> node_type;
ulint count; /*!< count of nodes in list */
elem_type* start; /*!< pointer to list start,
NULL if empty */
elem_type* end; /*!< pointer to list end,
NULL if empty */
node_ptr node; /*!< Pointer to member field
that is used as a link node */ #ifdef UNIV_DEBUG
ulint init; /*!< UT_LIST_INITIALISED if thelistwasinitialisedwith
UT_LIST_INIT() */ #endif/* UNIV_DEBUG */
/*******************************************************************//**
Note: This is really the list constructor. We should be able to use
placement new here.
Initializes the base node of a two-way list.
@param b the list base node
@param pmf point to member field that will be used as the link node */ #define UT_LIST_INIT(b, pmf) \
{ \
(b).count = 0; \
(b).start = 0; \
(b).end = 0; \
(b).node = pmf; \
UT_LIST_INITIALISE(b); \
}
/** Functor for accessing the embedded node within a list element. This is requiredbecausesomelistscanhavethenodeembeddedinsideanested struct/union.Seelock0priv.h(tablelocks)foranexample.Itprovidesa
specialised functor to grant access to the list node. */ template <typename Type> struct GenericGetNode {
/*******************************************************************//**
Adds the node as the first element in a two-way linked list.
@param list the base node (not a pointer to it)
@param elem the element to add */ template <typename List> void
ut_list_prepend(
List& list, typename List::elem_type* elem)
{ typename List::node_type& elem_node = elem->*list.node;
UT_LIST_IS_INITIALISED(list);
elem_node.prev = 0;
elem_node.next = list.start;
if (list.start != 0) { typename List::node_type& base_node =
list.start->*list.node;
ut_ad(list.start != elem);
base_node.prev = elem;
}
list.start = elem;
if (list.end == 0) {
list.end = elem;
}
++list.count;
}
/*******************************************************************//**
Adds the node as the first element in a two-way linked list.
@param LIST the base node (not a pointer to it)
@param ELEM the element to add */ #define UT_LIST_ADD_FIRST(LIST, ELEM) ut_list_prepend(LIST, ELEM)
/*******************************************************************//**
Adds the node as the last element in a two-way linked list.
@param list list
@param elem the element to add
@param get_node to get the list node for that element */ template <typename List, typename Functor> void
ut_list_append(
List& list, typename List::elem_type* elem,
Functor get_node)
{ typename List::node_type& node = get_node(*elem);
UT_LIST_IS_INITIALISED(list);
node.next = 0;
node.prev = list.end;
if (list.end != 0) { typename List::node_type& base_node = get_node(*list.end);
ut_ad(list.end != elem);
base_node.next = elem;
}
list.end = elem;
if (list.start == 0) {
list.start = elem;
}
++list.count;
}
/*******************************************************************//**
Adds the node as the last element in a two-way linked list.
@param list list
@param elem the element to add */ template <typename List> void
ut_list_append(
List& list, typename List::elem_type* elem)
{
ut_list_append(
list, elem,
GenericGetNode<typename List::elem_type>(list.node));
}
/*******************************************************************//**
Adds the node as the last element in a two-way linked list.
@param LIST list base node (not a pointer to it)
@param ELEM the element to add */ #define UT_LIST_ADD_LAST(LIST, ELEM) ut_list_append(LIST, ELEM)
/*******************************************************************//**
Inserts a ELEM2 after ELEM1 in a list.
@param list the base node
@param elem1 node after which ELEM2 is inserted
@param elem2 node being inserted after ELEM1 */ template <typename List> void
ut_list_insert(
List& list, typename List::elem_type* elem1, typename List::elem_type* elem2)
{
ut_ad(elem1 != elem2);
UT_LIST_IS_INITIALISED(list);
if (elem1_node.next != NULL) { typename List::node_type& next_node =
elem1_node.next->*list.node;
next_node.prev = elem2;
}
elem1_node.next = elem2;
if (list.end == elem1) {
list.end = elem2;
}
++list.count;
}
/*******************************************************************//**
Inserts a ELEM2 after ELEM1 in a list.
@param LIST list base node (not a pointer to it)
@param ELEM1 node after which ELEM2 is inserted
@param ELEM2 node being inserted after ELEM1 */ #define UT_LIST_INSERT_AFTER(LIST, ELEM1, ELEM2) \
ut_list_insert(LIST, ELEM1, ELEM2)
/*******************************************************************//**
Inserts a ELEM2 after ELEM1 in a list.
@param list the base node
@param elem1 node after which ELEM2 is inserted
@param elem2 node being inserted after ELEM1
@param get_node to get the list node for that element */
if (elem1_node.next != NULL) { typename List::node_type& next_node =
get_node(*elem1_node.next);
next_node.prev = elem2;
}
elem1_node.next = elem2;
if (list.end == elem1) {
list.end = elem2;
}
++list.count;
} /*******************************************************************//**
Removes a node from a two-way linked list.
@param list the base node (not a pointer to it)
@param node member node within list element that is to be removed
@param get_node functor to get the list node from elem */ template <typename List, typename Functor> void
ut_list_remove(
List& list, typename List::node_type& node,
Functor get_node)
{
ut_a(list.count > 0);
UT_LIST_IS_INITIALISED(list);
if (node.next != NULL) { typename List::node_type& next_node =
get_node(*node.next);
/*******************************************************************//**
Removes a node from a two-way linked list.
@param list the base node (not a pointer to it)
@param elem element to be removed from the list
@param get_node functor to get the list node from elem */ template <typename List, typename Functor> void
ut_list_remove(
List& list, typename List::elem_type* elem,
Functor get_node)
{
ut_list_remove(list, get_node(*elem), get_node);
}
/*******************************************************************//**
Removes a node from a two-way linked list.
@param list the base node (not a pointer to it)
@param elem element to be removed from the list */ template <typename List> void
ut_list_remove(
List& list, typename List::elem_type* elem)
{
ut_list_remove(
list, elem->*list.node,
GenericGetNode<typename List::elem_type>(list.node));
}
/*******************************************************************//**
Removes a node from a two-way linked list.
@param LIST the base node (not a pointer to it)
@param ELEM node to be removed from the list */ #define UT_LIST_REMOVE(LIST, ELEM) ut_list_remove(LIST, ELEM)
/********************************************************************//**
Gets the next node in a two-way list.
@param NAME list name
@param N pointer to a node
@return the successor of N in NAME, or NULL */ #define UT_LIST_GET_NEXT(NAME, N) (((N)->NAME).next)
/********************************************************************//**
Gets the previous node in a two-way list.
@param NAME list name
@param N pointer to a node
@return the predecessor of N in NAME, or NULL */ #define UT_LIST_GET_PREV(NAME, N) (((N)->NAME).prev)
/********************************************************************//**
Alternative macro to get the number of nodes in a two-way list, i.e.,
its length.
@param BASE the base node (not a pointer to it).
@return the number of nodes in the list */ #define UT_LIST_GET_LEN(BASE) (BASE).count
/********************************************************************//**
Gets the first node in a two-way list.
@param BASE the base node (not a pointer to it)
@return first node, or NULL if the list is empty */ #define UT_LIST_GET_FIRST(BASE) (BASE).start
/********************************************************************//**
Gets the last node in a two-way list.
@param BASE the base node (not a pointer to it)
@return last node, or NULL if the list is empty */ #define UT_LIST_GET_LAST(BASE) (BASE).end
/** Iterate over all the elements and call the functor for each element. @param[in]listbasenode(notapointertoit)
@param[in,out] functor Functor that is called for each element in the list */ template <typename List, class Functor> inlinevoid ut_list_map(const List& list, Functor& functor)
{
ulint count = 0;
/** Iterate over all the elements and call the functor for each element. @param[in]listbasenode(notapointertoit)
@param[in] functor Functor that is called for each element in the list */ template <typename List, class Functor> inlinevoid ut_list_map(const List& list, const Functor& functor)
{
ulint count = 0;
/** Check the consistency of a doubly linked list. @param[in]listbasenode(notapointertoit)
@param[in,out] functor Functor that is called for each element in the list */ template <typename List, class Functor> void ut_list_validate(const List& list, Functor& functor)
{
ut_list_map(list, functor); #ifdef UNIV_DEBUG /* Validate the list backwards. */
ulint count = list.count;
/** Check the consistency of a doubly linked list. @param[in]listbasenode(notapointertoit)
@param[in] functor Functor that is called for each element in the list */ template <typename List, class Functor> inlinevoid ut_list_validate(const List& list, const Functor& functor)
{
ut_list_map(list, functor); #ifdef UNIV_DEBUG /* Validate the list backwards. */
ulint count = list.count;
/** Check if the given element exists in the list. @param[in,out]listthelistobject
@param[in] elem the element of the list which will be checked */ template <typename List> inlinebool ut_list_exists(const List& list, typename List::elem_type* elem)
{ for (typename List::elem_type* e1 = UT_LIST_GET_FIRST(list); e1;
e1 = (e1->*list.node).next) { if (elem == e1) { returntrue;
}
} returnfalse;
} #endif
/** Move the given element to the beginning of the list. @param[in,out]listthelistobject @param[in]elemtheelementofthelistwhichwillbemoved
to the beginning of the list. */ template <typename List> void
ut_list_move_to_front(
List& list, typename List::elem_type* elem)
{
ut_ad(ut_list_exists(list, elem));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.