|
@@ -0,0 +1,258 @@
|
|
|
+#pragma once
|
|
|
+
|
|
|
+namespace AK {
|
|
|
+
|
|
|
+class IntrusiveListNode;
|
|
|
+class IntrusiveListStorage {
|
|
|
+private:
|
|
|
+ friend class IntrusiveListNode;
|
|
|
+ template<class T, IntrusiveListNode T::*member>
|
|
|
+ friend class IntrusiveList;
|
|
|
+ IntrusiveListNode* m_first { nullptr };
|
|
|
+ IntrusiveListNode* m_last { nullptr };
|
|
|
+};
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+class IntrusiveList {
|
|
|
+public:
|
|
|
+ IntrusiveList();
|
|
|
+ ~IntrusiveList();
|
|
|
+
|
|
|
+ void clear();
|
|
|
+ bool is_empty() const;
|
|
|
+ void append(T& n);
|
|
|
+ void prepend(T& n);
|
|
|
+ void remove(T& n);
|
|
|
+ bool contains(const T&) const;
|
|
|
+ T* first() const;
|
|
|
+ T* last() const;
|
|
|
+
|
|
|
+ class Iterator {
|
|
|
+ public:
|
|
|
+ Iterator();
|
|
|
+ Iterator(T* value);
|
|
|
+
|
|
|
+ T* operator*() const;
|
|
|
+ T* operator->() const;
|
|
|
+ bool operator==(const Iterator& other) const;
|
|
|
+ bool operator!=(const Iterator& other) const { return !(*this == other); }
|
|
|
+ Iterator& operator++();
|
|
|
+ Iterator& erase();
|
|
|
+
|
|
|
+ private:
|
|
|
+ T* m_value { nullptr };
|
|
|
+ };
|
|
|
+
|
|
|
+ Iterator begin();
|
|
|
+ Iterator end();
|
|
|
+
|
|
|
+private:
|
|
|
+ static T* next(T* current);
|
|
|
+ static T* node_to_value(IntrusiveListNode& node);
|
|
|
+ IntrusiveListStorage m_storage;
|
|
|
+};
|
|
|
+
|
|
|
+class IntrusiveListNode {
|
|
|
+public:
|
|
|
+ ~IntrusiveListNode();
|
|
|
+ void remove();
|
|
|
+ bool is_in_list() const;
|
|
|
+
|
|
|
+private:
|
|
|
+ template<class T, IntrusiveListNode T::*member>
|
|
|
+ friend class IntrusiveList;
|
|
|
+ IntrusiveListStorage* m_storage = nullptr;
|
|
|
+ IntrusiveListNode* m_next = nullptr;
|
|
|
+ IntrusiveListNode* m_prev = nullptr;
|
|
|
+};
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline IntrusiveList<T, member>::Iterator::Iterator()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline IntrusiveList<T, member>::Iterator::Iterator(T* value)
|
|
|
+ : m_value(value)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline T* IntrusiveList<T, member>::Iterator::operator*() const
|
|
|
+{
|
|
|
+ return m_value;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline T* IntrusiveList<T, member>::Iterator::operator->() const
|
|
|
+{
|
|
|
+ return m_value;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline bool IntrusiveList<T, member>::Iterator::operator==(const Iterator& other) const
|
|
|
+{
|
|
|
+ return other.m_value == m_value;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline typename IntrusiveList<T, member>::Iterator& IntrusiveList<T, member>::Iterator::operator++()
|
|
|
+{
|
|
|
+ m_value = IntrusiveList<T, member>::next(m_value);
|
|
|
+ return *this;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline typename IntrusiveList<T, member>::Iterator& IntrusiveList<T, member>::Iterator::erase()
|
|
|
+{
|
|
|
+ T* old = m_value;
|
|
|
+ m_value = IntrusiveList<T, member>::next(m_value);
|
|
|
+ (old->*member).remove();
|
|
|
+ return *this;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline IntrusiveList<T, member>::IntrusiveList()
|
|
|
+
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline IntrusiveList<T, member>::~IntrusiveList()
|
|
|
+{
|
|
|
+ clear();
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline void IntrusiveList<T, member>::clear()
|
|
|
+{
|
|
|
+ while (m_storage.m_first)
|
|
|
+ m_storage.m_first->remove();
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline bool IntrusiveList<T, member>::is_empty() const
|
|
|
+{
|
|
|
+ return m_storage.m_first == nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline void IntrusiveList<T, member>::append(T& n)
|
|
|
+{
|
|
|
+ auto& nnode = n.*member;
|
|
|
+ if (nnode.m_storage)
|
|
|
+ nnode.remove();
|
|
|
+
|
|
|
+ nnode.m_storage = &m_storage;
|
|
|
+ nnode.m_prev = m_storage.m_last;
|
|
|
+ nnode.m_next = nullptr;
|
|
|
+
|
|
|
+ if (m_storage.m_last)
|
|
|
+ m_storage.m_last->m_next = &nnode;
|
|
|
+ m_storage.m_last = &nnode;
|
|
|
+ if (!m_storage.m_first)
|
|
|
+ m_storage.m_first = &nnode;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline void IntrusiveList<T, member>::prepend(T& n)
|
|
|
+{
|
|
|
+ auto& nnode = n.*member;
|
|
|
+ if (nnode.m_storage)
|
|
|
+ nnode.remove();
|
|
|
+
|
|
|
+ nnode.m_storage = &m_storage;
|
|
|
+ nnode.m_prev = nullptr;
|
|
|
+ nnode.m_next = m_storage.m_first;
|
|
|
+
|
|
|
+ if (m_storage.m_first)
|
|
|
+ m_storage.m_first->m_prev = &nnode;
|
|
|
+ m_storage.m_first = &nnode;
|
|
|
+ if (!m_storage.m_last)
|
|
|
+ m_storage.m_last = &nnode;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline void IntrusiveList<T, member>::remove(T& n)
|
|
|
+{
|
|
|
+ auto& nnode = n.*member;
|
|
|
+ if (nnode.m_storage)
|
|
|
+ nnode.remove();
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline bool IntrusiveList<T, member>::contains(const T& n) const
|
|
|
+{
|
|
|
+ auto& nnode = n.*member;
|
|
|
+ return nnode.m_storage == &m_storage;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline T* IntrusiveList<T, member>::first() const
|
|
|
+{
|
|
|
+ return m_storage.m_first ? node_to_value(*m_storage.m_first) : nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline T* IntrusiveList<T, member>::last() const
|
|
|
+{
|
|
|
+ return m_storage.m_last ? node_to_value(*m_storage.m_last) : nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline T* IntrusiveList<T, member>::next(T* current)
|
|
|
+{
|
|
|
+ auto& nextnode = (current->*member).m_next;
|
|
|
+ T* nextstruct = nextnode ? node_to_value(*nextnode) : nullptr;
|
|
|
+ return nextstruct;
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline typename IntrusiveList<T, member>::Iterator IntrusiveList<T, member>::begin()
|
|
|
+{
|
|
|
+ return m_storage.m_first ? Iterator(node_to_value(*m_storage.m_first)) : Iterator();
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline typename IntrusiveList<T, member>::Iterator IntrusiveList<T, member>::end()
|
|
|
+{
|
|
|
+ return Iterator();
|
|
|
+}
|
|
|
+
|
|
|
+template<class T, IntrusiveListNode T::*member>
|
|
|
+inline T* IntrusiveList<T, member>::node_to_value(IntrusiveListNode& node)
|
|
|
+{
|
|
|
+ return (T*)((char*)&node - ((char*)&(((T*)nullptr)->*member) - (char*)nullptr));
|
|
|
+}
|
|
|
+
|
|
|
+inline IntrusiveListNode::~IntrusiveListNode()
|
|
|
+{
|
|
|
+ if (m_storage)
|
|
|
+ remove();
|
|
|
+}
|
|
|
+
|
|
|
+inline void IntrusiveListNode::remove()
|
|
|
+{
|
|
|
+ ASSERT(m_storage);
|
|
|
+ if (m_storage->m_first == this)
|
|
|
+ m_storage->m_first = m_next;
|
|
|
+ if (m_storage->m_last == this)
|
|
|
+ m_storage->m_last = m_prev;
|
|
|
+ if (m_prev)
|
|
|
+ m_prev->m_next = m_next;
|
|
|
+ if (m_next)
|
|
|
+ m_next->m_prev = m_prev;
|
|
|
+ m_prev = nullptr;
|
|
|
+ m_next = nullptr;
|
|
|
+ m_storage = nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+inline bool IntrusiveListNode::is_in_list() const
|
|
|
+{
|
|
|
+ return m_storage != nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+using AK::IntrusiveList;
|
|
|
+using AK::IntrusiveListNode;
|