mirror of
				https://github.com/Atmosphere-NX/Atmosphere-libs.git
				synced 2025-10-31 11:36:02 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			580 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			580 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) Atmosphère-NX
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify it
 | |
|  * under the terms and conditions of the GNU General Public License,
 | |
|  * version 2, as published by the Free Software Foundation.
 | |
|  *
 | |
|  * This program is distributed in the hope it will be useful, but WITHOUT
 | |
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | |
|  * more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| #include <vapours/common.hpp>
 | |
| #include <vapours/assert.hpp>
 | |
| #include <vapours/util/util_parent_of_member.hpp>
 | |
| #include <vapours/freebsd/tree.hpp>
 | |
| 
 | |
| namespace ams::util {
 | |
| 
 | |
|     AMS_PRAGMA_BEGIN_OPTIMIZE("-O3")
 | |
| 
 | |
|     namespace impl {
 | |
| 
 | |
|         class IntrusiveRedBlackTreeImpl;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     #pragma pack(push, 4)
 | |
|     struct IntrusiveRedBlackTreeNode {
 | |
|         NON_COPYABLE(IntrusiveRedBlackTreeNode);
 | |
|         public:
 | |
|             using RBEntry = freebsd::RBEntry<IntrusiveRedBlackTreeNode>;
 | |
|         private:
 | |
|             RBEntry m_entry;
 | |
|         public:
 | |
|             constexpr explicit ALWAYS_INLINE IntrusiveRedBlackTreeNode(util::ConstantInitializeTag) : m_entry(util::ConstantInitialize) { /* ... */ }
 | |
|             explicit ALWAYS_INLINE IntrusiveRedBlackTreeNode() { /* ... */ }
 | |
| 
 | |
|             [[nodiscard]] constexpr ALWAYS_INLINE RBEntry &GetRBEntry() { return m_entry; }
 | |
|             [[nodiscard]] constexpr ALWAYS_INLINE const RBEntry &GetRBEntry() const { return m_entry; }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE void SetRBEntry(const RBEntry &entry) { m_entry = entry; }
 | |
|     };
 | |
|     static_assert(sizeof(IntrusiveRedBlackTreeNode) == 3 * sizeof(void *) + std::max<size_t>(sizeof(freebsd::RBColor), 4));
 | |
|     #pragma pack(pop)
 | |
| 
 | |
|     template<class T, class Traits, class Comparator>
 | |
|     class IntrusiveRedBlackTree;
 | |
| 
 | |
|     namespace impl {
 | |
| 
 | |
|         class IntrusiveRedBlackTreeImpl {
 | |
|             NON_COPYABLE(IntrusiveRedBlackTreeImpl);
 | |
|             private:
 | |
|                 template<class, class, class>
 | |
|                 friend class ::ams::util::IntrusiveRedBlackTree;
 | |
|             private:
 | |
|                 using RootType = freebsd::RBHead<IntrusiveRedBlackTreeNode>;
 | |
|             private:
 | |
|                 RootType m_root;
 | |
|             public:
 | |
|                 template<bool Const>
 | |
|                 class Iterator;
 | |
| 
 | |
|                 using value_type      = IntrusiveRedBlackTreeNode;
 | |
|                 using size_type       = size_t;
 | |
|                 using difference_type = ptrdiff_t;
 | |
|                 using pointer         = value_type *;
 | |
|                 using const_pointer   = const value_type *;
 | |
|                 using reference       = value_type &;
 | |
|                 using const_reference = const value_type &;
 | |
|                 using iterator        = Iterator<false>;
 | |
|                 using const_iterator  = Iterator<true>;
 | |
| 
 | |
|                 template<bool Const>
 | |
|                 class Iterator {
 | |
|                     public:
 | |
|                         using iterator_category = std::bidirectional_iterator_tag;
 | |
|                         using value_type        = typename IntrusiveRedBlackTreeImpl::value_type;
 | |
|                         using difference_type   = typename IntrusiveRedBlackTreeImpl::difference_type;
 | |
|                         using pointer           = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_pointer,   IntrusiveRedBlackTreeImpl::pointer>::type;
 | |
|                         using reference         = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_reference, IntrusiveRedBlackTreeImpl::reference>::type;
 | |
|                     private:
 | |
|                         pointer m_node;
 | |
|                     public:
 | |
|                         constexpr explicit ALWAYS_INLINE Iterator(pointer n) : m_node(n) { /* ... */ }
 | |
| 
 | |
|                         constexpr ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
 | |
|                             return m_node == rhs.m_node;
 | |
|                         }
 | |
| 
 | |
|                         constexpr ALWAYS_INLINE pointer operator->() const {
 | |
|                             return m_node;
 | |
|                         }
 | |
| 
 | |
|                         constexpr ALWAYS_INLINE reference operator*() const {
 | |
|                             return *m_node;
 | |
|                         }
 | |
| 
 | |
|                         constexpr ALWAYS_INLINE Iterator &operator++() {
 | |
|                             m_node = GetNext(m_node);
 | |
|                             return *this;
 | |
|                         }
 | |
| 
 | |
|                         constexpr ALWAYS_INLINE Iterator &operator--() {
 | |
|                             m_node = GetPrev(m_node);
 | |
|                             return *this;
 | |
|                         }
 | |
| 
 | |
|                         constexpr ALWAYS_INLINE Iterator operator++(int) {
 | |
|                             const Iterator it{*this};
 | |
|                             ++(*this);
 | |
|                             return it;
 | |
|                         }
 | |
| 
 | |
|                         constexpr ALWAYS_INLINE Iterator operator--(int) {
 | |
|                             const Iterator it{*this};
 | |
|                             --(*this);
 | |
|                             return it;
 | |
|                         }
 | |
| 
 | |
|                         constexpr ALWAYS_INLINE operator Iterator<true>() const {
 | |
|                             return Iterator<true>(m_node);
 | |
|                         }
 | |
|                 };
 | |
|             private:
 | |
|                 constexpr ALWAYS_INLINE bool EmptyImpl() const {
 | |
|                     return m_root.IsEmpty();
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetMinImpl() const {
 | |
|                     return freebsd::RB_MIN(const_cast<RootType &>(m_root));
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetMaxImpl() const {
 | |
|                     return freebsd::RB_MAX(const_cast<RootType &>(m_root));
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) {
 | |
|                     return freebsd::RB_REMOVE(m_root, node);
 | |
|                 }
 | |
|             public:
 | |
|                 static constexpr IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) {
 | |
|                     return freebsd::RB_NEXT(node);
 | |
|                 }
 | |
| 
 | |
|                 static constexpr IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) {
 | |
|                     return freebsd::RB_PREV(node);
 | |
|                 }
 | |
| 
 | |
|                 static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNext(IntrusiveRedBlackTreeNode const *node) {
 | |
|                     return static_cast<const IntrusiveRedBlackTreeNode *>(GetNext(const_cast<IntrusiveRedBlackTreeNode *>(node)));
 | |
|                 }
 | |
| 
 | |
|                 static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetPrev(IntrusiveRedBlackTreeNode const *node) {
 | |
|                     return static_cast<const IntrusiveRedBlackTreeNode *>(GetPrev(const_cast<IntrusiveRedBlackTreeNode *>(node)));
 | |
|                 }
 | |
|             public:
 | |
|                 constexpr ALWAYS_INLINE IntrusiveRedBlackTreeImpl() = default;
 | |
| 
 | |
|                 /* Iterator accessors. */
 | |
|                 constexpr ALWAYS_INLINE iterator begin() {
 | |
|                     return iterator(this->GetMinImpl());
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE const_iterator begin() const {
 | |
|                     return const_iterator(this->GetMinImpl());
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE iterator end() {
 | |
|                     return iterator(static_cast<IntrusiveRedBlackTreeNode *>(nullptr));
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE const_iterator end() const {
 | |
|                     return const_iterator(static_cast<const IntrusiveRedBlackTreeNode *>(nullptr));
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE const_iterator cbegin() const {
 | |
|                     return this->begin();
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE const_iterator cend() const {
 | |
|                     return this->end();
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE iterator iterator_to(reference ref) {
 | |
|                     return iterator(std::addressof(ref));
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE const_iterator iterator_to(const_reference ref) const {
 | |
|                     return const_iterator(std::addressof(ref));
 | |
|                 }
 | |
| 
 | |
|                 /* Content management. */
 | |
|                 constexpr ALWAYS_INLINE bool empty() const {
 | |
|                     return this->EmptyImpl();
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE reference back() {
 | |
|                     return *this->GetMaxImpl();
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE const_reference back() const {
 | |
|                     return *this->GetMaxImpl();
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE reference front() {
 | |
|                     return *this->GetMinImpl();
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE const_reference front() const {
 | |
|                     return *this->GetMinImpl();
 | |
|                 }
 | |
| 
 | |
|                 constexpr ALWAYS_INLINE iterator erase(iterator it) {
 | |
|                     auto cur  = std::addressof(*it);
 | |
|                     auto next = GetNext(cur);
 | |
|                     this->RemoveImpl(cur);
 | |
|                     return iterator(next);
 | |
|                 }
 | |
|         };
 | |
| 
 | |
|     }
 | |
| 
 | |
|     template<typename T>
 | |
|     concept HasRedBlackKeyType = requires {
 | |
|         { std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>;
 | |
|     };
 | |
| 
 | |
|     namespace impl {
 | |
| 
 | |
|         template<typename T, typename Default>
 | |
|         consteval auto *GetRedBlackKeyType() {
 | |
|             if constexpr (HasRedBlackKeyType<T>) {
 | |
|                 return static_cast<typename T::RedBlackKeyType *>(nullptr);
 | |
|             } else {
 | |
|                 return static_cast<Default *>(nullptr);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     template<typename T, typename Default>
 | |
|     using RedBlackKeyType = typename std::remove_pointer<decltype(impl::GetRedBlackKeyType<T, Default>())>::type;
 | |
| 
 | |
|     template<class T, class Traits, class Comparator>
 | |
|     class IntrusiveRedBlackTree {
 | |
|         NON_COPYABLE(IntrusiveRedBlackTree);
 | |
|         public:
 | |
|             using ImplType = impl::IntrusiveRedBlackTreeImpl;
 | |
|         private:
 | |
|             ImplType m_impl;
 | |
|         public:
 | |
|             template<bool Const>
 | |
|             class Iterator;
 | |
| 
 | |
|             using value_type      = T;
 | |
|             using size_type       = size_t;
 | |
|             using difference_type = ptrdiff_t;
 | |
|             using pointer         = T *;
 | |
|             using const_pointer   = const T *;
 | |
|             using reference       = T &;
 | |
|             using const_reference = const T &;
 | |
|             using iterator        = Iterator<false>;
 | |
|             using const_iterator  = Iterator<true>;
 | |
| 
 | |
|             using key_type      = RedBlackKeyType<Comparator, value_type>;
 | |
|             using const_key_pointer   = const key_type *;
 | |
|             using const_key_reference = const key_type &;
 | |
| 
 | |
|             template<bool Const>
 | |
|             class Iterator {
 | |
|                 public:
 | |
|                     friend class IntrusiveRedBlackTree<T, Traits, Comparator>;
 | |
| 
 | |
|                     using ImplIterator = typename std::conditional<Const, ImplType::const_iterator, ImplType::iterator>::type;
 | |
| 
 | |
|                     using iterator_category = std::bidirectional_iterator_tag;
 | |
|                     using value_type        = typename IntrusiveRedBlackTree::value_type;
 | |
|                     using difference_type   = typename IntrusiveRedBlackTree::difference_type;
 | |
|                     using pointer           = typename std::conditional<Const, IntrusiveRedBlackTree::const_pointer,   IntrusiveRedBlackTree::pointer>::type;
 | |
|                     using reference         = typename std::conditional<Const, IntrusiveRedBlackTree::const_reference, IntrusiveRedBlackTree::reference>::type;
 | |
|                 private:
 | |
|                     ImplIterator m_impl;
 | |
|                 private:
 | |
|                     constexpr explicit ALWAYS_INLINE Iterator(ImplIterator it) : m_impl(it) { /* ... */ }
 | |
| 
 | |
|                     constexpr explicit ALWAYS_INLINE Iterator(typename ImplIterator::pointer p) : m_impl(p) { /* ... */ }
 | |
| 
 | |
|                     constexpr ALWAYS_INLINE ImplIterator GetImplIterator() const {
 | |
|                         return m_impl;
 | |
|                     }
 | |
|                 public:
 | |
|                     constexpr ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
 | |
|                         return m_impl == rhs.m_impl;
 | |
|                     }
 | |
| 
 | |
|                     constexpr ALWAYS_INLINE pointer operator->() const {
 | |
|                         return Traits::GetParent(std::addressof(*m_impl));
 | |
|                     }
 | |
| 
 | |
|                     constexpr ALWAYS_INLINE reference operator*() const {
 | |
|                         return *Traits::GetParent(std::addressof(*m_impl));
 | |
|                     }
 | |
| 
 | |
|                     constexpr ALWAYS_INLINE Iterator &operator++() {
 | |
|                         ++m_impl;
 | |
|                         return *this;
 | |
|                     }
 | |
| 
 | |
|                     constexpr ALWAYS_INLINE Iterator &operator--() {
 | |
|                         --m_impl;
 | |
|                         return *this;
 | |
|                     }
 | |
| 
 | |
|                     constexpr ALWAYS_INLINE Iterator operator++(int) {
 | |
|                         const Iterator it{*this};
 | |
|                         ++m_impl;
 | |
|                         return it;
 | |
|                     }
 | |
| 
 | |
|                     constexpr ALWAYS_INLINE Iterator operator--(int) {
 | |
|                         const Iterator it{*this};
 | |
|                         --m_impl;
 | |
|                         return it;
 | |
|                     }
 | |
| 
 | |
|                     constexpr ALWAYS_INLINE operator Iterator<true>() const {
 | |
|                         return Iterator<true>(m_impl);
 | |
|                     }
 | |
|             };
 | |
|         private:
 | |
|             static constexpr ALWAYS_INLINE int CompareImpl(const IntrusiveRedBlackTreeNode *lhs, const IntrusiveRedBlackTreeNode *rhs) {
 | |
|                 return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs));
 | |
|             }
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE int CompareKeyImpl(const_key_reference key, const IntrusiveRedBlackTreeNode *rhs) {
 | |
|                 return Comparator::Compare(key, *Traits::GetParent(rhs));
 | |
|             }
 | |
| 
 | |
|             /* Define accessors using RB_* functions. */
 | |
|             constexpr IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) {
 | |
|                 return freebsd::RB_INSERT(m_impl.m_root, node, CompareImpl);
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
 | |
|                 return freebsd::RB_FIND(const_cast<ImplType::RootType &>(m_impl.m_root), const_cast<IntrusiveRedBlackTreeNode *>(node), CompareImpl);
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
 | |
|                 return freebsd::RB_NFIND(const_cast<ImplType::RootType &>(m_impl.m_root), const_cast<IntrusiveRedBlackTreeNode *>(node), CompareImpl);
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindKeyImpl(const_key_reference key) const {
 | |
|                 return freebsd::RB_FIND_KEY(const_cast<ImplType::RootType &>(m_impl.m_root), key, CompareKeyImpl);
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *NFindKeyImpl(const_key_reference key) const {
 | |
|                 return freebsd::RB_NFIND_KEY(const_cast<ImplType::RootType &>(m_impl.m_root), key, CompareKeyImpl);
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindExistingImpl(IntrusiveRedBlackTreeNode const *node) const {
 | |
|                 return freebsd::RB_FIND_EXISTING(const_cast<ImplType::RootType &>(m_impl.m_root), const_cast<IntrusiveRedBlackTreeNode *>(node), CompareImpl);
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindExistingKeyImpl(const_key_reference key) const {
 | |
|                 return freebsd::RB_FIND_EXISTING_KEY(const_cast<ImplType::RootType &>(m_impl.m_root), key, CompareKeyImpl);
 | |
|             }
 | |
|         public:
 | |
|             constexpr ALWAYS_INLINE IntrusiveRedBlackTree() = default;
 | |
| 
 | |
|             /* Iterator accessors. */
 | |
|             constexpr ALWAYS_INLINE iterator begin() {
 | |
|                 return iterator(m_impl.begin());
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE const_iterator begin() const {
 | |
|                 return const_iterator(m_impl.begin());
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator end() {
 | |
|                 return iterator(m_impl.end());
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE const_iterator end() const {
 | |
|                 return const_iterator(m_impl.end());
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE const_iterator cbegin() const {
 | |
|                 return this->begin();
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE const_iterator cend() const {
 | |
|                 return this->end();
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator iterator_to(reference ref) {
 | |
|                 return iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE const_iterator iterator_to(const_reference ref) const {
 | |
|                 return const_iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
 | |
|             }
 | |
| 
 | |
|             /* Content management. */
 | |
|             constexpr ALWAYS_INLINE bool empty() const {
 | |
|                 return m_impl.empty();
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE reference back() {
 | |
|                 return *Traits::GetParent(std::addressof(m_impl.back()));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE const_reference back() const {
 | |
|                 return *Traits::GetParent(std::addressof(m_impl.back()));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE reference front() {
 | |
|                 return *Traits::GetParent(std::addressof(m_impl.front()));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE const_reference front() const {
 | |
|                 return *Traits::GetParent(std::addressof(m_impl.front()));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator erase(iterator it) {
 | |
|                 return iterator(m_impl.erase(it.GetImplIterator()));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator insert(reference ref) {
 | |
|                 ImplType::pointer node = Traits::GetNode(std::addressof(ref));
 | |
|                 this->InsertImpl(node);
 | |
|                 return iterator(node);
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator find(const_reference ref) const {
 | |
|                 return iterator(this->FindImpl(Traits::GetNode(std::addressof(ref))));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator nfind(const_reference ref) const {
 | |
|                 return iterator(this->NFindImpl(Traits::GetNode(std::addressof(ref))));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator find_key(const_key_reference ref) const {
 | |
|                 return iterator(this->FindKeyImpl(ref));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator nfind_key(const_key_reference ref) const {
 | |
|                 return iterator(this->NFindKeyImpl(ref));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator find_existing(const_reference ref) const {
 | |
|                 return iterator(this->FindExistingImpl(Traits::GetNode(std::addressof(ref))));
 | |
|             }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE iterator find_existing_key(const_key_reference ref) const {
 | |
|                 return iterator(this->FindExistingKeyImpl(ref));
 | |
|             }
 | |
|     };
 | |
| 
 | |
|     template<auto T, class Derived = util::impl::GetParentType<T>>
 | |
|     class IntrusiveRedBlackTreeMemberTraits;
 | |
| 
 | |
|     template<class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
 | |
|     class IntrusiveRedBlackTreeMemberTraits<Member, Derived> {
 | |
|         public:
 | |
|             template<class Comparator>
 | |
|             using TreeType     = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraits, Comparator>;
 | |
|             using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
 | |
|         private:
 | |
|             template<class, class, class>
 | |
|             friend class IntrusiveRedBlackTree;
 | |
| 
 | |
|             friend class impl::IntrusiveRedBlackTreeImpl;
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
 | |
|                 return std::addressof(parent->*Member);
 | |
|             }
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
 | |
|                 return std::addressof(parent->*Member);
 | |
|             }
 | |
| 
 | |
|             static ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
 | |
|                 return util::GetParentPointer<Member, Derived>(node);
 | |
|             }
 | |
| 
 | |
|             static ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
 | |
|                 return util::GetParentPointer<Member, Derived>(node);
 | |
|             }
 | |
|         private:
 | |
|             static_assert(util::IsAligned(util::impl::OffsetOf<Member, Derived>::value, alignof(void *)));
 | |
|     };
 | |
| 
 | |
|     template<auto T, class Derived = util::impl::GetParentType<T>>
 | |
|     class IntrusiveRedBlackTreeMemberTraitsDeferredAssert;
 | |
| 
 | |
|     template<class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
 | |
|     class IntrusiveRedBlackTreeMemberTraitsDeferredAssert<Member, Derived> {
 | |
|         public:
 | |
|             template<class Comparator>
 | |
|             using TreeType     = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>;
 | |
|             using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
 | |
| 
 | |
|             static constexpr bool IsValid() {
 | |
|                 return util::IsAligned(util::impl::OffsetOf<Member, Derived>::value, alignof(void *));
 | |
|             }
 | |
|         private:
 | |
|             template<class, class, class>
 | |
|             friend class IntrusiveRedBlackTree;
 | |
| 
 | |
|             friend class impl::IntrusiveRedBlackTreeImpl;
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
 | |
|                 return std::addressof(parent->*Member);
 | |
|             }
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
 | |
|                 return std::addressof(parent->*Member);
 | |
|             }
 | |
| 
 | |
|             static ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
 | |
|                 return util::GetParentPointer<Member, Derived>(node);
 | |
|             }
 | |
| 
 | |
|             static ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
 | |
|                 return util::GetParentPointer<Member, Derived>(node);
 | |
|             }
 | |
|     };
 | |
| 
 | |
|     template<class Derived>
 | |
|     class alignas(void *) IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
 | |
|         public:
 | |
|             using IntrusiveRedBlackTreeNode::IntrusiveRedBlackTreeNode;
 | |
| 
 | |
|             constexpr ALWAYS_INLINE Derived *GetPrev()             { return static_cast<      Derived *>(static_cast<      IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this))); }
 | |
|             constexpr ALWAYS_INLINE const Derived *GetPrev() const { return static_cast<const Derived *>(static_cast<const IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this))); }
 | |
| 
 | |
|             constexpr ALWAYS_INLINE Derived *GetNext()             { return static_cast<      Derived *>(static_cast<      IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetNext(this))); }
 | |
|             constexpr ALWAYS_INLINE const Derived *GetNext() const { return static_cast<const Derived *>(static_cast<const IntrusiveRedBlackTreeBaseNode *>(impl::IntrusiveRedBlackTreeImpl::GetNext(this))); }
 | |
|     };
 | |
| 
 | |
|     template<class Derived>
 | |
|     class IntrusiveRedBlackTreeBaseTraits {
 | |
|         public:
 | |
|             template<class Comparator>
 | |
|             using TreeType     = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeBaseTraits, Comparator>;
 | |
|             using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
 | |
|         private:
 | |
|             template<class, class, class>
 | |
|             friend class IntrusiveRedBlackTree;
 | |
| 
 | |
|             friend class impl::IntrusiveRedBlackTreeImpl;
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
 | |
|                 return static_cast<IntrusiveRedBlackTreeNode *>(static_cast<IntrusiveRedBlackTreeBaseNode<Derived> *>(parent));
 | |
|             }
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
 | |
|                 return static_cast<const IntrusiveRedBlackTreeNode *>(static_cast<const IntrusiveRedBlackTreeBaseNode<Derived> *>(parent));
 | |
|             }
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
 | |
|                 return static_cast<Derived *>(static_cast<IntrusiveRedBlackTreeBaseNode<Derived> *>(node));
 | |
|             }
 | |
| 
 | |
|             static constexpr ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
 | |
|                 return static_cast<const Derived *>(static_cast<const IntrusiveRedBlackTreeBaseNode<Derived> *>(node));
 | |
|             }
 | |
|     };
 | |
| 
 | |
|     AMS_PRAGMA_END_OPTIMIZE()
 | |
| 
 | |
| }
 |