haiku/headers/private/kernel/util/DoublyLinkedQueue.h
Augustin Cavalier 254894210c LinkedLists: Rename MoveFrom method to TakeFrom.
"Move" now sounds like it has 'move' semantics (i.e. replaces this
structure's data with the other structure's data), while MoveFrom()
really had 'move+append' semantics (appends the other list's elements
to this list, and clears the other list.) To make this clearer, it's
here renamed to "TakeFrom".

This should reduce confusion with the other move-related APIs that
are starting to show up in the Haiku tree (e.g. "MoveFrom" in BRegion.)

Change-Id: Ib0a61a9c12fe8812020efd55a2a0818883883e2a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8634
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Reviewed-by: X512 X512 <danger_mail@list.ru>
2024-12-11 19:09:25 +00:00

369 lines
6.9 KiB
C++

/*
* Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2005-2006, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef KERNEL_UTIL_DOUBLY_LINKED_QUEUE_H
#define KERNEL_UTIL_DOUBLY_LINKED_QUEUE_H
#include <util/DoublyLinkedList.h>
/*!
A doubly linked queue is like a doubly linked list, but only has a pointer
to the head of the list, none to its tail.
*/
#ifdef __cplusplus
// for convenience
#define DOUBLY_LINKED_QUEUE_CLASS_NAME DoublyLinkedQueue<Element, GetLink>
template<typename Element,
typename GetLink = DoublyLinkedListStandardGetLink<Element> >
class DoublyLinkedQueue {
private:
typedef DoublyLinkedQueue<Element, GetLink> Queue;
typedef DoublyLinkedListLink<Element> Link;
public:
class Iterator {
public:
Iterator(Queue *queue)
:
fQueue(queue)
{
Rewind();
}
Iterator(const Iterator &other)
{
*this = other;
}
bool HasNext() const
{
return fNext;
}
Element *Next()
{
fCurrent = fNext;
if (fNext)
fNext = fQueue->GetNext(fNext);
return fCurrent;
}
Element *Remove()
{
Element *element = fCurrent;
if (fCurrent) {
fQueue->Remove(fCurrent);
fCurrent = NULL;
}
return element;
}
Iterator &operator=(const Iterator &other)
{
fQueue = other.fQueue;
fCurrent = other.fCurrent;
fNext = other.fNext;
return *this;
}
void Rewind()
{
fCurrent = NULL;
fNext = fQueue->First();
}
private:
Queue *fQueue;
Element *fCurrent;
Element *fNext;
};
class ConstIterator {
public:
ConstIterator(const Queue *queue)
:
fQueue(queue)
{
Rewind();
}
ConstIterator(const ConstIterator &other)
{
*this = other;
}
bool HasNext() const
{
return fNext;
}
Element *Next()
{
Element *element = fNext;
if (fNext)
fNext = fQueue->GetNext(fNext);
return element;
}
ConstIterator &operator=(const ConstIterator &other)
{
fQueue = other.fQueue;
fNext = other.fNext;
return *this;
}
void Rewind()
{
fNext = fQueue->First();
}
private:
const Queue *fQueue;
Element *fNext;
};
public:
DoublyLinkedQueue() : fFirst(NULL) {}
~DoublyLinkedQueue() {}
inline bool IsEmpty() const { return (fFirst == NULL); }
inline void Insert(Element *element);
inline void InsertBefore(Element *before, Element *element);
inline void Add(Element *element);
inline void Remove(Element *element);
inline void Swap(Element *a, Element *b);
inline void TakeFrom(DOUBLY_LINKED_QUEUE_CLASS_NAME *fromList);
inline void RemoveAll();
inline void MakeEmpty() { RemoveAll(); }
inline Element *First() const { return fFirst; }
inline Element *Head() const { return fFirst; }
inline Element *RemoveHead();
inline Element *GetPrevious(Element *element) const;
inline Element *GetNext(Element *element) const;
inline int32 Size() const;
// O(n)!
inline Iterator GetIterator() { return Iterator(this); }
inline ConstIterator GetIterator() const { return ConstIterator(this); }
private:
Element *fFirst;
static GetLink sGetLink;
};
// inline methods
// Insert
DOUBLY_LINKED_LIST_TEMPLATE_LIST
void
DOUBLY_LINKED_QUEUE_CLASS_NAME::Insert(Element *element)
{
if (element) {
Link *elLink = sGetLink(element);
elLink->previous = NULL;
elLink->next = fFirst;
if (fFirst)
sGetLink(fFirst)->previous = element;
fFirst = element;
}
}
// Insert
DOUBLY_LINKED_LIST_TEMPLATE_LIST
void
DOUBLY_LINKED_QUEUE_CLASS_NAME::InsertBefore(Element *before, Element *element)
{
if (before == NULL) {
Insert(element);
return;
}
if (element == NULL)
return;
Link *beforeLink = sGetLink(before);
Link *link = sGetLink(element);
link->next = before;
link->previous = beforeLink->previous;
if (link->previous != NULL)
sGetLink(link->previous)->next = element;
beforeLink->previous = element;
if (fFirst == before)
fFirst = element;
}
// Add
DOUBLY_LINKED_LIST_TEMPLATE_LIST
void
DOUBLY_LINKED_QUEUE_CLASS_NAME::Add(Element *element)
{
Insert(element);
}
// Remove
DOUBLY_LINKED_LIST_TEMPLATE_LIST
void
DOUBLY_LINKED_QUEUE_CLASS_NAME::Remove(Element *element)
{
if (element == NULL)
return;
#if DEBUG_DOUBLY_LINKED_LIST
ASSERT_PRINT(fFirst != NULL,
"queue: %p, element: %p\n", this, element);
#endif
Link *elLink = sGetLink(element);
if (element == fFirst)
fFirst = elLink->next;
else
sGetLink(elLink->previous)->next = elLink->next;
if (elLink->next)
sGetLink(elLink->next)->previous = elLink->previous;
elLink->next = elLink->previous = NULL;
}
// Swap
DOUBLY_LINKED_LIST_TEMPLATE_LIST
void
DOUBLY_LINKED_QUEUE_CLASS_NAME::Swap(Element *a, Element *b)
{
if (a && b && a != b) {
Link *aLink = sGetLink(a);
Link *bLink = sGetLink(b);
Element *aPrev = aLink->previous;
Element *bPrev = bLink->previous;
Element *aNext = aLink->next;
Element *bNext = bLink->next;
// place a
if (bPrev)
sGetLink(bPrev)->next = a;
else
fFirst = a;
if (bNext)
sGetLink(bNext)->previous = a;
aLink->previous = bPrev;
aLink->next = bNext;
// place b
if (aPrev)
sGetLink(aPrev)->next = b;
else
fFirst = b;
if (aNext)
sGetLink(aNext)->previous = b;
bLink->previous = aPrev;
bLink->next = aNext;
}
}
// TakeFrom
DOUBLY_LINKED_LIST_TEMPLATE_LIST
void
DOUBLY_LINKED_QUEUE_CLASS_NAME::TakeFrom(DOUBLY_LINKED_QUEUE_CLASS_NAME *fromList)
{
if (fromList && fromList->fFirst) {
if (fFirst) {
Element *element = fFirst;
Link *elLink;
while ((elLink = sGetLink(element))->next) {
element = elLink->next;
}
elLink->next = fromList->fFirst;
} else {
fFirst = fromList->fFirst;
}
fromList->fFirst = NULL;
}
}
// RemoveAll
DOUBLY_LINKED_LIST_TEMPLATE_LIST
void
DOUBLY_LINKED_QUEUE_CLASS_NAME::RemoveAll()
{
Element *element = fFirst;
while (element) {
Link *elLink = sGetLink(element);
element = elLink->next;
elLink->previous = NULL;
elLink->next = NULL;
}
fFirst = NULL;
}
// RemoveHead
DOUBLY_LINKED_LIST_TEMPLATE_LIST
Element *
DOUBLY_LINKED_QUEUE_CLASS_NAME::RemoveHead()
{
Element *element = Head();
Remove(element);
return element;
}
// GetPrevious
DOUBLY_LINKED_LIST_TEMPLATE_LIST
Element *
DOUBLY_LINKED_QUEUE_CLASS_NAME::GetPrevious(Element *element) const
{
Element *result = NULL;
if (element)
result = sGetLink(element)->previous;
return result;
}
// GetNext
DOUBLY_LINKED_LIST_TEMPLATE_LIST
Element *
DOUBLY_LINKED_QUEUE_CLASS_NAME::GetNext(Element *element) const
{
Element *result = NULL;
if (element)
result = sGetLink(element)->next;
return result;
}
// Size
DOUBLY_LINKED_LIST_TEMPLATE_LIST
int32
DOUBLY_LINKED_QUEUE_CLASS_NAME::Size() const
{
int32 count = 0;
for (Element* element = First(); element; element = GetNext(element))
count++;
return count;
}
// sGetLink
DOUBLY_LINKED_LIST_TEMPLATE_LIST
GetLink DOUBLY_LINKED_QUEUE_CLASS_NAME::sGetLink;
#endif /* __cplusplus */
#endif // _KERNEL_UTIL_DOUBLY_LINKED_QUEUE_H