You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/CryCommon/intrusive_list.hpp

181 lines
6.1 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef _INTRUSIVE_LIST_HPP
#define _INTRUSIVE_LIST_HPP
#if !defined(WIN32)
#include <stdint.h>
#endif //!defined(WIN32)
namespace util
{
// Simple lightweight intrusive list utility
//
template<typename Host>
struct list
{
typedef Host value_type;
list* next;
list* prev;
// Default (initializing) constructor
list()
{
next = this;
prev = this;
}
// Inserts this list into a given list item between
// prev and next (note: they need to be sequential!)
void insert(list* _prev, list* _next)
{
_next->prev = this;
this->next = _next;
this->prev = _prev;
_prev->next = this;
}
// Should only be called on heads
void clear() { next = prev = this; }
// Removes from a list, then inserts this list item into a given list between
// prev and next (note: they need to be sequential!)
void re_insert(list* _prev, list* _next)
{
erase();
insert(_prev, _next);
}
// Remove this list instance from a list
// Safe to be called even if not attached to a list
void erase()
{
next->prev = prev;
prev->next = next;
next = prev = this;
}
// Predicate to determine if a list structure is linked to a list
bool empty() const { return prev == this && next == this; }
bool linked() const { return !empty(); }
// Get the host instance of the instrusive list
template<list Host::* member>
Host* item()
{
return ((Host*)((uintptr_t)(this) - (uintptr_t)(&(((Host*)0)->*member))));
}
template<list Host::* member>
const Host* item() const
{
return ((Host*)((uintptr_t)(this) - (uintptr_t)(&(((Host*)0)->*member))));
}
template<list (Host::* Member)[2]>
Host * item(int threadId)
{
uintptr_t value = (uintptr_t)this - (uintptr_t)&((((Host*)(NULL))->*Member)[threadId]);
return alias_cast<Host*>(value);
}
// Insert & relink functions
void insert_tail(list* _list) { insert(_list->prev, _list); }
void insert_tail(list& _list) { insert_tail(&_list); }
void insert_head(list* _list) { insert(_list, _list->next); }
void insert_head(list& _list) { insert_head(&_list); }
void relink_tail(list* _list) { erase(); insert_tail(_list); }
void relink_tail(list& _list) { relink_tail(&_list); }
void relink_head(list* _list) { erase(); insert_head(_list); }
void relink_head(list& _list) { relink_head(&_list); }
static inline void splice(const list* _list, list* prev, list* next)
{
list* first = _list->next;
list* last = _list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
void splice_front(const list* _list)
{
if (!_list->empty())
{
splice(_list, this, this->next);
_list->clear();
}
}
void splice_tail(list* _list)
{
if (!_list->empty())
{
splice(_list, this->prev, this);
_list->clear();
}
}
// Accessors
list<Host>* tail() { return prev; }
const list<Host>* tail() const { return prev; }
list<Host>* head() { return head; }
const list<Host>* head() const { return head; }
};
// utility to extract the host type of an intrusive list at compile time
template<typename List>
struct list_value_type
{
typedef typename List::value_type value_type;
};
// Loops over the list in forward manner, pos will be of type list<T>*
# define list_for_each(pos, head) \
for (typeof(head)pos = (head)->next; pos != (head); \
pos = pos->next)
// Loops over the list in backward manner, pos will be of type list<T>*
# define list_for_each_backwards(pos, head) \
for (typeof(head)pos = (head)->prev; pos != (head); \
pos = pos->prev)
// Loops over the list in forward manner while safeguarding
// against list removal during iteration. pos will be of type list<T>*
# define list_for_each_safe(pos, head) \
for (typeof(head)pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
// Loops over the list in forward manner. pos will be of type list<T>*
# define list_for_each_entry(pos, head, member) \
for (util::list_value_type<typeof((head))>::value_type* pos = \
(head)->next->item<member>(); \
&(pos->*(member)) != &list; \
pos = ((pos->*(member)).next->item<member>()))
// Loops over the list in forward manner while safeguarding against list
// removal during iteratation. pos will be of type T*
# define list_for_each_entry_safe(pos, head, member) \
for (util::list_value_type<typeof((head))>::value_type* pos = \
(head)->next->item<member>(), \
* n = ((pos->*(member)).next->item<member>()); \
&(pos->*(member)) != &list; \
pos = n, n = ((n->*(member)).next->item<member>()))
} // end namespace util
#endif // ifndef _INTRUSIVE_LIST_HPP