|
Packit Service |
d40955 |
/*
|
|
Packit Service |
d40955 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
d40955 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
d40955 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
d40955 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
d40955 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
d40955 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
d40955 |
* GNU General Public License for more details.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
d40955 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
d40955 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
d40955 |
* 02110-1301, USA.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/ringNode.h#1 $
|
|
Packit Service |
d40955 |
*/
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#ifndef RING_NODE_H
|
|
Packit Service |
d40955 |
#define RING_NODE_H
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#include "types.h"
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* A ring node is a member of a doubly-linked circular list.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* Each node is usually embedded within a data structure that contains the
|
|
Packit Service |
d40955 |
* relevant payload. In addition the ring head is also represented by a
|
|
Packit Service |
d40955 |
* node where the next field designates the first element of the ring and the
|
|
Packit Service |
d40955 |
* prev field designates the last.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* An empty ring contains next and prev fields that point back to the ring
|
|
Packit Service |
d40955 |
* head itself.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* Typical iteration over a ring, from the front and back:
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* for (RingNode *n = head->next; n != head; n = n->next) { ... }
|
|
Packit Service |
d40955 |
* for (RingNode *p = head->prev; p != head; p = p->prev) { ... }
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
typedef struct ringNode RingNode;
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
struct ringNode {
|
|
Packit Service |
d40955 |
RingNode *next;
|
|
Packit Service |
d40955 |
RingNode *prev;
|
|
Packit Service |
d40955 |
};
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Initialize a ring to be empty.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param head The head of the ring
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void initializeRing(RingNode *head)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
head->next = head->prev = head;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a ring is empty.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param head The head of the ring
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return true if the ring is empty
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool isRingEmpty(const RingNode *head)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return (head->next == head);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Check whether a ring contains exactly one node.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param head The head of the ring
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return true if the ring contains exactly one member
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline bool isRingSingleton(const RingNode *head)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return (!isRingEmpty(head) && (head->prev == head->next));
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Unsplice a contiguous chain of at least one node from its ring.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param first the first entry in the ring to unsplice
|
|
Packit Service |
d40955 |
* @param last the last entry in the ring to unsplice,
|
|
Packit Service |
d40955 |
* may be the same as ``first``
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* The effect of this is to create two rings, the one designated
|
|
Packit Service |
d40955 |
* by first through last, and the other consisting of anything remaining.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void unspliceRingChain(RingNode *first,
|
|
Packit Service |
d40955 |
RingNode *last)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
first->prev->next = last->next;
|
|
Packit Service |
d40955 |
last->next->prev = first->prev;
|
|
Packit Service |
d40955 |
first->prev = last;
|
|
Packit Service |
d40955 |
last->next = first;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Remove a ring node from its ring.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param node the ring node
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return the removed node, for convenience
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline RingNode *unspliceRingNode(RingNode *node)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
unspliceRingChain(node, node);
|
|
Packit Service |
d40955 |
return node;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Splice a contiguous chain of at least one node after the specified entry,
|
|
Packit Service |
d40955 |
* which may be the head of a ring.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param first the first entry in a contiguous span of nodes
|
|
Packit Service |
d40955 |
* @param last the last entry in a contiguous span of nodes,
|
|
Packit Service |
d40955 |
* may be the same as ``first``
|
|
Packit Service |
d40955 |
* @param where the entry after which ``first`` through ``last``
|
|
Packit Service |
d40955 |
* shall appear
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* The effect of this is to unsplice first through last (if necessary) and
|
|
Packit Service |
d40955 |
* insert them after ``where`` so that the previous nodes after ``where``
|
|
Packit Service |
d40955 |
* now appear after ``last``.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void spliceRingChainAfter(RingNode *first,
|
|
Packit Service |
d40955 |
RingNode *last,
|
|
Packit Service |
d40955 |
RingNode *where)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
if (last->next != first) {
|
|
Packit Service |
d40955 |
unspliceRingChain(first, last);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
last->next = where->next;
|
|
Packit Service |
d40955 |
first->prev = where;
|
|
Packit Service |
d40955 |
where->next->prev = last;
|
|
Packit Service |
d40955 |
where->next = first;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Splice a contiguous chain of at least one node before the specified entry,
|
|
Packit Service |
d40955 |
* which may be the tail of a list.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param first the first entry in a contiguous span of nodes
|
|
Packit Service |
d40955 |
* @param last the last entry in a contiguous span of nodes,
|
|
Packit Service |
d40955 |
* may be the same as ``first``
|
|
Packit Service |
d40955 |
* @param where the entry before which ``first`` through ``last``
|
|
Packit Service |
d40955 |
* shall appear
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* The effect of this is to unsplice first through last (if necessary) and
|
|
Packit Service |
d40955 |
* insert them before ``where`` so that the previous nodes before ``where``
|
|
Packit Service |
d40955 |
* now appear before ``first``.
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void spliceRingChainBefore(RingNode *first,
|
|
Packit Service |
d40955 |
RingNode *last,
|
|
Packit Service |
d40955 |
RingNode *where)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
if (last->next != first) {
|
|
Packit Service |
d40955 |
unspliceRingChain(first, last);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
first->prev = where->prev;
|
|
Packit Service |
d40955 |
last->next = where;
|
|
Packit Service |
d40955 |
where->prev->next = first;
|
|
Packit Service |
d40955 |
where->prev = last;
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Push a single node on the end of a ring.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param head The ring head
|
|
Packit Service |
d40955 |
* @param node The node to push
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline void pushRingNode(RingNode *head, RingNode *node)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
spliceRingChainBefore(node, node, head);
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Pop a single node off the end of a ring.
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @param head The ring head
|
|
Packit Service |
d40955 |
*
|
|
Packit Service |
d40955 |
* @return NULL if the ring was empty, otherwise the node that was
|
|
Packit Service |
d40955 |
* removed from the ring (``head->prev``)
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline RingNode *popRingNode(RingNode *head)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return (isRingEmpty(head) ? NULL : unspliceRingNode(head->prev));
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
/**
|
|
Packit Service |
d40955 |
* Remove a single node off the front of the list
|
|
Packit Service |
d40955 |
**/
|
|
Packit Service |
d40955 |
static inline RingNode *chopRingNode(RingNode *head)
|
|
Packit Service |
d40955 |
{
|
|
Packit Service |
d40955 |
return (isRingEmpty(head) ? NULL : unspliceRingNode(head->next));
|
|
Packit Service |
d40955 |
}
|
|
Packit Service |
d40955 |
|
|
Packit Service |
d40955 |
#endif // RING_NODE_H
|