diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/intrusive_red_black_tree.h | 391 | ||||
-rw-r--r-- | src/common/tree.h | 625 |
2 files changed, 551 insertions, 465 deletions
diff --git a/src/common/intrusive_red_black_tree.h b/src/common/intrusive_red_black_tree.h index 3173cc449..b296b639e 100644 --- a/src/common/intrusive_red_black_tree.h +++ b/src/common/intrusive_red_black_tree.h @@ -4,6 +4,8 @@ #pragma once +#include "common/alignment.h" +#include "common/common_funcs.h" #include "common/parent_of_member.h" #include "common/tree.h" @@ -15,32 +17,33 @@ class IntrusiveRedBlackTreeImpl; } +#pragma pack(push, 4) struct IntrusiveRedBlackTreeNode { + YUZU_NON_COPYABLE(IntrusiveRedBlackTreeNode); + public: - using EntryType = RBEntry<IntrusiveRedBlackTreeNode>; + using RBEntry = freebsd::RBEntry<IntrusiveRedBlackTreeNode>; - constexpr IntrusiveRedBlackTreeNode() = default; +private: + RBEntry m_entry; - void SetEntry(const EntryType& new_entry) { - entry = new_entry; - } +public: + explicit IntrusiveRedBlackTreeNode() = default; - [[nodiscard]] EntryType& GetEntry() { - return entry; + [[nodiscard]] constexpr RBEntry& GetRBEntry() { + return m_entry; } - - [[nodiscard]] const EntryType& GetEntry() const { - return entry; + [[nodiscard]] constexpr const RBEntry& GetRBEntry() const { + return m_entry; } -private: - EntryType entry{}; - - friend class impl::IntrusiveRedBlackTreeImpl; - - template <class, class, class> - friend class IntrusiveRedBlackTree; + constexpr 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; @@ -48,12 +51,17 @@ class IntrusiveRedBlackTree; namespace impl { class IntrusiveRedBlackTreeImpl { + YUZU_NON_COPYABLE(IntrusiveRedBlackTreeImpl); + private: template <class, class, class> friend class ::Common::IntrusiveRedBlackTree; - using RootType = RBHead<IntrusiveRedBlackTreeNode>; - RootType root; +private: + using RootType = freebsd::RBHead<IntrusiveRedBlackTreeNode>; + +private: + RootType m_root; public: template <bool Const> @@ -81,149 +89,150 @@ public: IntrusiveRedBlackTreeImpl::reference>; private: - pointer node; + pointer m_node; public: - explicit Iterator(pointer n) : node(n) {} + constexpr explicit Iterator(pointer n) : m_node(n) {} - bool operator==(const Iterator& rhs) const { - return this->node == rhs.node; + constexpr bool operator==(const Iterator& rhs) const { + return m_node == rhs.m_node; } - bool operator!=(const Iterator& rhs) const { + constexpr bool operator!=(const Iterator& rhs) const { return !(*this == rhs); } - pointer operator->() const { - return this->node; + constexpr pointer operator->() const { + return m_node; } - reference operator*() const { - return *this->node; + constexpr reference operator*() const { + return *m_node; } - Iterator& operator++() { - this->node = GetNext(this->node); + constexpr Iterator& operator++() { + m_node = GetNext(m_node); return *this; } - Iterator& operator--() { - this->node = GetPrev(this->node); + constexpr Iterator& operator--() { + m_node = GetPrev(m_node); return *this; } - Iterator operator++(int) { + constexpr Iterator operator++(int) { const Iterator it{*this}; ++(*this); return it; } - Iterator operator--(int) { + constexpr Iterator operator--(int) { const Iterator it{*this}; --(*this); return it; } - operator Iterator<true>() const { - return Iterator<true>(this->node); + constexpr operator Iterator<true>() const { + return Iterator<true>(m_node); } }; private: - // Define accessors using RB_* functions. - bool EmptyImpl() const { - return root.IsEmpty(); + constexpr bool EmptyImpl() const { + return m_root.IsEmpty(); } - IntrusiveRedBlackTreeNode* GetMinImpl() const { - return RB_MIN(const_cast<RootType*>(&root)); + constexpr IntrusiveRedBlackTreeNode* GetMinImpl() const { + return freebsd::RB_MIN(const_cast<RootType&>(m_root)); } - IntrusiveRedBlackTreeNode* GetMaxImpl() const { - return RB_MAX(const_cast<RootType*>(&root)); + constexpr IntrusiveRedBlackTreeNode* GetMaxImpl() const { + return freebsd::RB_MAX(const_cast<RootType&>(m_root)); } - IntrusiveRedBlackTreeNode* RemoveImpl(IntrusiveRedBlackTreeNode* node) { - return RB_REMOVE(&root, node); + constexpr IntrusiveRedBlackTreeNode* RemoveImpl(IntrusiveRedBlackTreeNode* node) { + return freebsd::RB_REMOVE(m_root, node); } public: - static IntrusiveRedBlackTreeNode* GetNext(IntrusiveRedBlackTreeNode* node) { - return RB_NEXT(node); + static constexpr IntrusiveRedBlackTreeNode* GetNext(IntrusiveRedBlackTreeNode* node) { + return freebsd::RB_NEXT(node); } - static IntrusiveRedBlackTreeNode* GetPrev(IntrusiveRedBlackTreeNode* node) { - return RB_PREV(node); + static constexpr IntrusiveRedBlackTreeNode* GetPrev(IntrusiveRedBlackTreeNode* node) { + return freebsd::RB_PREV(node); } - static const IntrusiveRedBlackTreeNode* GetNext(const IntrusiveRedBlackTreeNode* node) { + static constexpr IntrusiveRedBlackTreeNode const* GetNext( + IntrusiveRedBlackTreeNode const* node) { return static_cast<const IntrusiveRedBlackTreeNode*>( GetNext(const_cast<IntrusiveRedBlackTreeNode*>(node))); } - static const IntrusiveRedBlackTreeNode* GetPrev(const IntrusiveRedBlackTreeNode* node) { + static constexpr IntrusiveRedBlackTreeNode const* GetPrev( + IntrusiveRedBlackTreeNode const* node) { return static_cast<const IntrusiveRedBlackTreeNode*>( GetPrev(const_cast<IntrusiveRedBlackTreeNode*>(node))); } public: - constexpr IntrusiveRedBlackTreeImpl() {} + constexpr IntrusiveRedBlackTreeImpl() = default; // Iterator accessors. - iterator begin() { + constexpr iterator begin() { return iterator(this->GetMinImpl()); } - const_iterator begin() const { + constexpr const_iterator begin() const { return const_iterator(this->GetMinImpl()); } - iterator end() { + constexpr iterator end() { return iterator(static_cast<IntrusiveRedBlackTreeNode*>(nullptr)); } - const_iterator end() const { + constexpr const_iterator end() const { return const_iterator(static_cast<const IntrusiveRedBlackTreeNode*>(nullptr)); } - const_iterator cbegin() const { + constexpr const_iterator cbegin() const { return this->begin(); } - const_iterator cend() const { + constexpr const_iterator cend() const { return this->end(); } - iterator iterator_to(reference ref) { - return iterator(&ref); + constexpr iterator iterator_to(reference ref) { + return iterator(std::addressof(ref)); } - const_iterator iterator_to(const_reference ref) const { - return const_iterator(&ref); + constexpr const_iterator iterator_to(const_reference ref) const { + return const_iterator(std::addressof(ref)); } // Content management. - bool empty() const { + constexpr bool empty() const { return this->EmptyImpl(); } - reference back() { + constexpr reference back() { return *this->GetMaxImpl(); } - const_reference back() const { + constexpr const_reference back() const { return *this->GetMaxImpl(); } - reference front() { + constexpr reference front() { return *this->GetMinImpl(); } - const_reference front() const { + constexpr const_reference front() const { return *this->GetMinImpl(); } - iterator erase(iterator it) { + constexpr iterator erase(iterator it) { auto cur = std::addressof(*it); auto next = GetNext(cur); this->RemoveImpl(cur); @@ -234,16 +243,16 @@ public: } // namespace impl template <typename T> -concept HasLightCompareType = requires { - { std::is_same<typename T::LightCompareType, void>::value } -> std::convertible_to<bool>; +concept HasRedBlackKeyType = requires { + { std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>; }; namespace impl { template <typename T, typename Default> - consteval auto* GetLightCompareType() { - if constexpr (HasLightCompareType<T>) { - return static_cast<typename T::LightCompareType*>(nullptr); + consteval auto* GetRedBlackKeyType() { + if constexpr (HasRedBlackKeyType<T>) { + return static_cast<typename T::RedBlackKeyType*>(nullptr); } else { return static_cast<Default*>(nullptr); } @@ -252,16 +261,17 @@ namespace impl { } // namespace impl template <typename T, typename Default> -using LightCompareType = std::remove_pointer_t<decltype(impl::GetLightCompareType<T, Default>())>; +using RedBlackKeyType = std::remove_pointer_t<decltype(impl::GetRedBlackKeyType<T, Default>())>; template <class T, class Traits, class Comparator> class IntrusiveRedBlackTree { + YUZU_NON_COPYABLE(IntrusiveRedBlackTree); public: using ImplType = impl::IntrusiveRedBlackTreeImpl; private: - ImplType impl{}; + ImplType m_impl; public: template <bool Const> @@ -277,9 +287,9 @@ public: using iterator = Iterator<false>; using const_iterator = Iterator<true>; - using light_value_type = LightCompareType<Comparator, value_type>; - using const_light_pointer = const light_value_type*; - using const_light_reference = const light_value_type&; + 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 { @@ -298,183 +308,201 @@ public: IntrusiveRedBlackTree::reference>; private: - ImplIterator iterator; + ImplIterator m_impl; private: - explicit Iterator(ImplIterator it) : iterator(it) {} + constexpr explicit Iterator(ImplIterator it) : m_impl(it) {} - explicit Iterator(typename std::conditional<Const, ImplType::const_iterator, - ImplType::iterator>::type::pointer ptr) - : iterator(ptr) {} + constexpr explicit Iterator(typename ImplIterator::pointer p) : m_impl(p) {} - ImplIterator GetImplIterator() const { - return this->iterator; + constexpr ImplIterator GetImplIterator() const { + return m_impl; } public: - bool operator==(const Iterator& rhs) const { - return this->iterator == rhs.iterator; + constexpr bool operator==(const Iterator& rhs) const { + return m_impl == rhs.m_impl; } - bool operator!=(const Iterator& rhs) const { + constexpr bool operator!=(const Iterator& rhs) const { return !(*this == rhs); } - pointer operator->() const { - return Traits::GetParent(std::addressof(*this->iterator)); + constexpr pointer operator->() const { + return Traits::GetParent(std::addressof(*m_impl)); } - reference operator*() const { - return *Traits::GetParent(std::addressof(*this->iterator)); + constexpr reference operator*() const { + return *Traits::GetParent(std::addressof(*m_impl)); } - Iterator& operator++() { - ++this->iterator; + constexpr Iterator& operator++() { + ++m_impl; return *this; } - Iterator& operator--() { - --this->iterator; + constexpr Iterator& operator--() { + --m_impl; return *this; } - Iterator operator++(int) { + constexpr Iterator operator++(int) { const Iterator it{*this}; - ++this->iterator; + ++m_impl; return it; } - Iterator operator--(int) { + constexpr Iterator operator--(int) { const Iterator it{*this}; - --this->iterator; + --m_impl; return it; } - operator Iterator<true>() const { - return Iterator<true>(this->iterator); + constexpr operator Iterator<true>() const { + return Iterator<true>(m_impl); } }; private: - static int CompareImpl(const IntrusiveRedBlackTreeNode* lhs, - const IntrusiveRedBlackTreeNode* rhs) { + static constexpr int CompareImpl(const IntrusiveRedBlackTreeNode* lhs, + const IntrusiveRedBlackTreeNode* rhs) { return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs)); } - static int LightCompareImpl(const void* elm, const IntrusiveRedBlackTreeNode* rhs) { - return Comparator::Compare(*static_cast<const_light_pointer>(elm), *Traits::GetParent(rhs)); + static constexpr int CompareKeyImpl(const_key_reference key, + const IntrusiveRedBlackTreeNode* rhs) { + return Comparator::Compare(key, *Traits::GetParent(rhs)); } // Define accessors using RB_* functions. - IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) { - return RB_INSERT(&impl.root, node, CompareImpl); + constexpr IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) { + return freebsd::RB_INSERT(m_impl.m_root, node, CompareImpl); } - IntrusiveRedBlackTreeNode* FindImpl(const IntrusiveRedBlackTreeNode* node) const { - return RB_FIND(const_cast<ImplType::RootType*>(&impl.root), - const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl); + constexpr IntrusiveRedBlackTreeNode* FindImpl(IntrusiveRedBlackTreeNode const* node) const { + return freebsd::RB_FIND(const_cast<ImplType::RootType&>(m_impl.m_root), + const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl); } - IntrusiveRedBlackTreeNode* NFindImpl(const IntrusiveRedBlackTreeNode* node) const { - return RB_NFIND(const_cast<ImplType::RootType*>(&impl.root), - const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl); + constexpr IntrusiveRedBlackTreeNode* NFindImpl(IntrusiveRedBlackTreeNode const* node) const { + return freebsd::RB_NFIND(const_cast<ImplType::RootType&>(m_impl.m_root), + const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl); } - IntrusiveRedBlackTreeNode* FindLightImpl(const_light_pointer lelm) const { - return RB_FIND_LIGHT(const_cast<ImplType::RootType*>(&impl.root), - static_cast<const void*>(lelm), LightCompareImpl); + constexpr IntrusiveRedBlackTreeNode* FindKeyImpl(const_key_reference key) const { + return freebsd::RB_FIND_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key, + CompareKeyImpl); } - IntrusiveRedBlackTreeNode* NFindLightImpl(const_light_pointer lelm) const { - return RB_NFIND_LIGHT(const_cast<ImplType::RootType*>(&impl.root), - static_cast<const void*>(lelm), LightCompareImpl); + constexpr IntrusiveRedBlackTreeNode* NFindKeyImpl(const_key_reference key) const { + return freebsd::RB_NFIND_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key, + CompareKeyImpl); + } + + constexpr 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 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 IntrusiveRedBlackTree() = default; // Iterator accessors. - iterator begin() { - return iterator(this->impl.begin()); + constexpr iterator begin() { + return iterator(m_impl.begin()); } - const_iterator begin() const { - return const_iterator(this->impl.begin()); + constexpr const_iterator begin() const { + return const_iterator(m_impl.begin()); } - iterator end() { - return iterator(this->impl.end()); + constexpr iterator end() { + return iterator(m_impl.end()); } - const_iterator end() const { - return const_iterator(this->impl.end()); + constexpr const_iterator end() const { + return const_iterator(m_impl.end()); } - const_iterator cbegin() const { + constexpr const_iterator cbegin() const { return this->begin(); } - const_iterator cend() const { + constexpr const_iterator cend() const { return this->end(); } - iterator iterator_to(reference ref) { - return iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref)))); + constexpr iterator iterator_to(reference ref) { + return iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref)))); } - const_iterator iterator_to(const_reference ref) const { - return const_iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref)))); + constexpr const_iterator iterator_to(const_reference ref) const { + return const_iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref)))); } // Content management. - bool empty() const { - return this->impl.empty(); + constexpr bool empty() const { + return m_impl.empty(); } - reference back() { - return *Traits::GetParent(std::addressof(this->impl.back())); + constexpr reference back() { + return *Traits::GetParent(std::addressof(m_impl.back())); } - const_reference back() const { - return *Traits::GetParent(std::addressof(this->impl.back())); + constexpr const_reference back() const { + return *Traits::GetParent(std::addressof(m_impl.back())); } - reference front() { - return *Traits::GetParent(std::addressof(this->impl.front())); + constexpr reference front() { + return *Traits::GetParent(std::addressof(m_impl.front())); } - const_reference front() const { - return *Traits::GetParent(std::addressof(this->impl.front())); + constexpr const_reference front() const { + return *Traits::GetParent(std::addressof(m_impl.front())); } - iterator erase(iterator it) { - return iterator(this->impl.erase(it.GetImplIterator())); + constexpr iterator erase(iterator it) { + return iterator(m_impl.erase(it.GetImplIterator())); } - iterator insert(reference ref) { + constexpr iterator insert(reference ref) { ImplType::pointer node = Traits::GetNode(std::addressof(ref)); this->InsertImpl(node); return iterator(node); } - iterator find(const_reference ref) const { + constexpr iterator find(const_reference ref) const { return iterator(this->FindImpl(Traits::GetNode(std::addressof(ref)))); } - iterator nfind(const_reference ref) const { + constexpr iterator nfind(const_reference ref) const { return iterator(this->NFindImpl(Traits::GetNode(std::addressof(ref)))); } - iterator find_light(const_light_reference ref) const { - return iterator(this->FindLightImpl(std::addressof(ref))); + constexpr iterator find_key(const_key_reference ref) const { + return iterator(this->FindKeyImpl(ref)); + } + + constexpr iterator nfind_key(const_key_reference ref) const { + return iterator(this->NFindKeyImpl(ref)); + } + + constexpr iterator find_existing(const_reference ref) const { + return iterator(this->FindExistingImpl(Traits::GetNode(std::addressof(ref)))); } - iterator nfind_light(const_light_reference ref) const { - return iterator(this->NFindLightImpl(std::addressof(ref))); + constexpr iterator find_existing_key(const_key_reference ref) const { + return iterator(this->FindExistingKeyImpl(ref)); } }; -template <auto T, class Derived = impl::GetParentType<T>> +template <auto T, class Derived = Common::impl::GetParentType<T>> class IntrusiveRedBlackTreeMemberTraits; template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived> @@ -498,19 +526,16 @@ private: return std::addressof(parent->*Member); } - static constexpr Derived* GetParent(IntrusiveRedBlackTreeNode* node) { - return GetParentPointer<Member, Derived>(node); + static Derived* GetParent(IntrusiveRedBlackTreeNode* node) { + return Common::GetParentPointer<Member, Derived>(node); } - static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) { - return GetParentPointer<Member, Derived>(node); + static Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) { + return Common::GetParentPointer<Member, Derived>(node); } - -private: - static constexpr TypedStorage<Derived> DerivedStorage = {}; }; -template <auto T, class Derived = impl::GetParentType<T>> +template <auto T, class Derived = Common::impl::GetParentType<T>> class IntrusiveRedBlackTreeMemberTraitsDeferredAssert; template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived> @@ -521,11 +546,6 @@ public: IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>; using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl; - static constexpr bool IsValid() { - TypedStorage<Derived> DerivedStorage = {}; - return GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage); - } - private: template <class, class, class> friend class IntrusiveRedBlackTree; @@ -540,30 +560,36 @@ private: return std::addressof(parent->*Member); } - static constexpr Derived* GetParent(IntrusiveRedBlackTreeNode* node) { - return GetParentPointer<Member, Derived>(node); + static Derived* GetParent(IntrusiveRedBlackTreeNode* node) { + return Common::GetParentPointer<Member, Derived>(node); } - static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) { - return GetParentPointer<Member, Derived>(node); + static Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) { + return Common::GetParentPointer<Member, Derived>(node); } }; template <class Derived> -class IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode { +class alignas(void*) IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode { public: + using IntrusiveRedBlackTreeNode::IntrusiveRedBlackTreeNode; + constexpr Derived* GetPrev() { - return static_cast<Derived*>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this)); + return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode*>( + impl::IntrusiveRedBlackTreeImpl::GetPrev(this))); } constexpr const Derived* GetPrev() const { - return static_cast<const Derived*>(impl::IntrusiveRedBlackTreeImpl::GetPrev(this)); + return static_cast<const Derived*>(static_cast<const IntrusiveRedBlackTreeBaseNode*>( + impl::IntrusiveRedBlackTreeImpl::GetPrev(this))); } constexpr Derived* GetNext() { - return static_cast<Derived*>(impl::IntrusiveRedBlackTreeImpl::GetNext(this)); + return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode*>( + impl::IntrusiveRedBlackTreeImpl::GetNext(this))); } constexpr const Derived* GetNext() const { - return static_cast<const Derived*>(impl::IntrusiveRedBlackTreeImpl::GetNext(this)); + return static_cast<const Derived*>(static_cast<const IntrusiveRedBlackTreeBaseNode*>( + impl::IntrusiveRedBlackTreeImpl::GetNext(this))); } }; @@ -581,19 +607,22 @@ private: friend class impl::IntrusiveRedBlackTreeImpl; static constexpr IntrusiveRedBlackTreeNode* GetNode(Derived* parent) { - return static_cast<IntrusiveRedBlackTreeNode*>(parent); + return static_cast<IntrusiveRedBlackTreeNode*>( + static_cast<IntrusiveRedBlackTreeBaseNode<Derived>*>(parent)); } static constexpr IntrusiveRedBlackTreeNode const* GetNode(Derived const* parent) { - return static_cast<const IntrusiveRedBlackTreeNode*>(parent); + return static_cast<const IntrusiveRedBlackTreeNode*>( + static_cast<const IntrusiveRedBlackTreeBaseNode<Derived>*>(parent)); } static constexpr Derived* GetParent(IntrusiveRedBlackTreeNode* node) { - return static_cast<Derived*>(node); + return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode<Derived>*>(node)); } - static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) { - return static_cast<const Derived*>(node); + static constexpr Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) { + return static_cast<const Derived*>( + static_cast<const IntrusiveRedBlackTreeBaseNode<Derived>*>(node)); } }; diff --git a/src/common/tree.h b/src/common/tree.h index 18faa4a48..28370e343 100644 --- a/src/common/tree.h +++ b/src/common/tree.h @@ -43,294 +43,265 @@ * The maximum height of a red-black tree is 2lg (n+1). */ -#include "common/assert.h" +namespace Common::freebsd { -namespace Common { +enum class RBColor { + RB_BLACK = 0, + RB_RED = 1, +}; + +#pragma pack(push, 4) template <typename T> -class RBHead { +class RBEntry { public: - [[nodiscard]] T* Root() { - return rbh_root; - } + constexpr RBEntry() = default; - [[nodiscard]] const T* Root() const { - return rbh_root; + [[nodiscard]] constexpr T* Left() { + return m_rbe_left; } - - void SetRoot(T* root) { - rbh_root = root; + [[nodiscard]] constexpr const T* Left() const { + return m_rbe_left; } - [[nodiscard]] bool IsEmpty() const { - return Root() == nullptr; + constexpr void SetLeft(T* e) { + m_rbe_left = e; } -private: - T* rbh_root = nullptr; -}; - -enum class EntryColor { - Black, - Red, -}; - -template <typename T> -class RBEntry { -public: - [[nodiscard]] T* Left() { - return rbe_left; + [[nodiscard]] constexpr T* Right() { + return m_rbe_right; } - - [[nodiscard]] const T* Left() const { - return rbe_left; + [[nodiscard]] constexpr const T* Right() const { + return m_rbe_right; } - void SetLeft(T* left) { - rbe_left = left; + constexpr void SetRight(T* e) { + m_rbe_right = e; } - [[nodiscard]] T* Right() { - return rbe_right; + [[nodiscard]] constexpr T* Parent() { + return m_rbe_parent; } - - [[nodiscard]] const T* Right() const { - return rbe_right; + [[nodiscard]] constexpr const T* Parent() const { + return m_rbe_parent; } - void SetRight(T* right) { - rbe_right = right; + constexpr void SetParent(T* e) { + m_rbe_parent = e; } - [[nodiscard]] T* Parent() { - return rbe_parent; + [[nodiscard]] constexpr bool IsBlack() const { + return m_rbe_color == RBColor::RB_BLACK; } - - [[nodiscard]] const T* Parent() const { - return rbe_parent; + [[nodiscard]] constexpr bool IsRed() const { + return m_rbe_color == RBColor::RB_RED; } - - void SetParent(T* parent) { - rbe_parent = parent; + [[nodiscard]] constexpr RBColor Color() const { + return m_rbe_color; } - [[nodiscard]] bool IsBlack() const { - return rbe_color == EntryColor::Black; + constexpr void SetColor(RBColor c) { + m_rbe_color = c; } - [[nodiscard]] bool IsRed() const { - return rbe_color == EntryColor::Red; - } +private: + T* m_rbe_left{}; + T* m_rbe_right{}; + T* m_rbe_parent{}; + RBColor m_rbe_color{RBColor::RB_BLACK}; +}; +#pragma pack(pop) - [[nodiscard]] EntryColor Color() const { - return rbe_color; - } +template <typename T> +struct CheckRBEntry { + static constexpr bool value = false; +}; +template <typename T> +struct CheckRBEntry<RBEntry<T>> { + static constexpr bool value = true; +}; - void SetColor(EntryColor color) { - rbe_color = color; - } +template <typename T> +concept IsRBEntry = CheckRBEntry<T>::value; +template <typename T> +concept HasRBEntry = requires(T& t, const T& ct) { + { t.GetRBEntry() } -> std::same_as<RBEntry<T>&>; + { ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>; +}; + +template <typename T> +requires HasRBEntry<T> +class RBHead { private: - T* rbe_left = nullptr; - T* rbe_right = nullptr; - T* rbe_parent = nullptr; - EntryColor rbe_color{}; + T* m_rbh_root = nullptr; + +public: + [[nodiscard]] constexpr T* Root() { + return m_rbh_root; + } + [[nodiscard]] constexpr const T* Root() const { + return m_rbh_root; + } + constexpr void SetRoot(T* root) { + m_rbh_root = root; + } + + [[nodiscard]] constexpr bool IsEmpty() const { + return this->Root() == nullptr; + } }; -template <typename Node> -[[nodiscard]] RBEntry<Node>& RB_ENTRY(Node* node) { - return node->GetEntry(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr RBEntry<T>& RB_ENTRY(T* t) { + return t->GetRBEntry(); } - -template <typename Node> -[[nodiscard]] const RBEntry<Node>& RB_ENTRY(const Node* node) { - return node->GetEntry(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr const RBEntry<T>& RB_ENTRY(const T* t) { + return t->GetRBEntry(); } -template <typename Node> -[[nodiscard]] Node* RB_PARENT(Node* node) { - return RB_ENTRY(node).Parent(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr T* RB_LEFT(T* t) { + return RB_ENTRY(t).Left(); } - -template <typename Node> -[[nodiscard]] const Node* RB_PARENT(const Node* node) { - return RB_ENTRY(node).Parent(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr const T* RB_LEFT(const T* t) { + return RB_ENTRY(t).Left(); } -template <typename Node> -void RB_SET_PARENT(Node* node, Node* parent) { - return RB_ENTRY(node).SetParent(parent); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr T* RB_RIGHT(T* t) { + return RB_ENTRY(t).Right(); } - -template <typename Node> -[[nodiscard]] Node* RB_LEFT(Node* node) { - return RB_ENTRY(node).Left(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr const T* RB_RIGHT(const T* t) { + return RB_ENTRY(t).Right(); } -template <typename Node> -[[nodiscard]] const Node* RB_LEFT(const Node* node) { - return RB_ENTRY(node).Left(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr T* RB_PARENT(T* t) { + return RB_ENTRY(t).Parent(); } - -template <typename Node> -void RB_SET_LEFT(Node* node, Node* left) { - return RB_ENTRY(node).SetLeft(left); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr const T* RB_PARENT(const T* t) { + return RB_ENTRY(t).Parent(); } -template <typename Node> -[[nodiscard]] Node* RB_RIGHT(Node* node) { - return RB_ENTRY(node).Right(); +template <typename T> +requires HasRBEntry<T> +constexpr void RB_SET_LEFT(T* t, T* e) { + RB_ENTRY(t).SetLeft(e); } - -template <typename Node> -[[nodiscard]] const Node* RB_RIGHT(const Node* node) { - return RB_ENTRY(node).Right(); +template <typename T> +requires HasRBEntry<T> +constexpr void RB_SET_RIGHT(T* t, T* e) { + RB_ENTRY(t).SetRight(e); } - -template <typename Node> -void RB_SET_RIGHT(Node* node, Node* right) { - return RB_ENTRY(node).SetRight(right); +template <typename T> +requires HasRBEntry<T> +constexpr void RB_SET_PARENT(T* t, T* e) { + RB_ENTRY(t).SetParent(e); } -template <typename Node> -[[nodiscard]] bool RB_IS_BLACK(const Node* node) { - return RB_ENTRY(node).IsBlack(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr bool RB_IS_BLACK(const T* t) { + return RB_ENTRY(t).IsBlack(); } - -template <typename Node> -[[nodiscard]] bool RB_IS_RED(const Node* node) { - return RB_ENTRY(node).IsRed(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr bool RB_IS_RED(const T* t) { + return RB_ENTRY(t).IsRed(); } -template <typename Node> -[[nodiscard]] EntryColor RB_COLOR(const Node* node) { - return RB_ENTRY(node).Color(); +template <typename T> +requires HasRBEntry<T> +[[nodiscard]] constexpr RBColor RB_COLOR(const T* t) { + return RB_ENTRY(t).Color(); } -template <typename Node> -void RB_SET_COLOR(Node* node, EntryColor color) { - return RB_ENTRY(node).SetColor(color); +template <typename T> +requires HasRBEntry<T> +constexpr void RB_SET_COLOR(T* t, RBColor c) { + RB_ENTRY(t).SetColor(c); } -template <typename Node> -void RB_SET(Node* node, Node* parent) { - auto& entry = RB_ENTRY(node); - entry.SetParent(parent); - entry.SetLeft(nullptr); - entry.SetRight(nullptr); - entry.SetColor(EntryColor::Red); +template <typename T> +requires HasRBEntry<T> +constexpr void RB_SET(T* elm, T* parent) { + auto& rb_entry = RB_ENTRY(elm); + rb_entry.SetParent(parent); + rb_entry.SetLeft(nullptr); + rb_entry.SetRight(nullptr); + rb_entry.SetColor(RBColor::RB_RED); } -template <typename Node> -void RB_SET_BLACKRED(Node* black, Node* red) { - RB_SET_COLOR(black, EntryColor::Black); - RB_SET_COLOR(red, EntryColor::Red); +template <typename T> +requires HasRBEntry<T> +constexpr void RB_SET_BLACKRED(T* black, T* red) { + RB_SET_COLOR(black, RBColor::RB_BLACK); + RB_SET_COLOR(red, RBColor::RB_RED); } -template <typename Node> -void RB_ROTATE_LEFT(RBHead<Node>* head, Node* elm, Node*& tmp) { +template <typename T> +requires HasRBEntry<T> +constexpr void RB_ROTATE_LEFT(RBHead<T>& head, T* elm, T*& tmp) { tmp = RB_RIGHT(elm); - RB_SET_RIGHT(elm, RB_LEFT(tmp)); - if (RB_RIGHT(elm) != nullptr) { + if (RB_SET_RIGHT(elm, RB_LEFT(tmp)); RB_RIGHT(elm) != nullptr) { RB_SET_PARENT(RB_LEFT(tmp), elm); } - RB_SET_PARENT(tmp, RB_PARENT(elm)); - if (RB_PARENT(tmp) != nullptr) { + if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) { if (elm == RB_LEFT(RB_PARENT(elm))) { RB_SET_LEFT(RB_PARENT(elm), tmp); } else { RB_SET_RIGHT(RB_PARENT(elm), tmp); } } else { - head->SetRoot(tmp); + head.SetRoot(tmp); } RB_SET_LEFT(tmp, elm); RB_SET_PARENT(elm, tmp); } -template <typename Node> -void RB_ROTATE_RIGHT(RBHead<Node>* head, Node* elm, Node*& tmp) { +template <typename T> +requires HasRBEntry<T> +constexpr void RB_ROTATE_RIGHT(RBHead<T>& head, T* elm, T*& tmp) { tmp = RB_LEFT(elm); - RB_SET_LEFT(elm, RB_RIGHT(tmp)); - if (RB_LEFT(elm) != nullptr) { + if (RB_SET_LEFT(elm, RB_RIGHT(tmp)); RB_LEFT(elm) != nullptr) { RB_SET_PARENT(RB_RIGHT(tmp), elm); } - RB_SET_PARENT(tmp, RB_PARENT(elm)); - if (RB_PARENT(tmp) != nullptr) { + if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) { if (elm == RB_LEFT(RB_PARENT(elm))) { RB_SET_LEFT(RB_PARENT(elm), tmp); } else { RB_SET_RIGHT(RB_PARENT(elm), tmp); } } else { - head->SetRoot(tmp); + head.SetRoot(tmp); } RB_SET_RIGHT(tmp, elm); RB_SET_PARENT(elm, tmp); } -template <typename Node> -void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) { - Node* parent = nullptr; - Node* tmp = nullptr; - - while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) { - Node* gparent = RB_PARENT(parent); - if (parent == RB_LEFT(gparent)) { - tmp = RB_RIGHT(gparent); - if (tmp && RB_IS_RED(tmp)) { - RB_SET_COLOR(tmp, EntryColor::Black); - RB_SET_BLACKRED(parent, gparent); - elm = gparent; - continue; - } - - if (RB_RIGHT(parent) == elm) { - RB_ROTATE_LEFT(head, parent, tmp); - tmp = parent; - parent = elm; - elm = tmp; - } - - RB_SET_BLACKRED(parent, gparent); - RB_ROTATE_RIGHT(head, gparent, tmp); - } else { - tmp = RB_LEFT(gparent); - if (tmp && RB_IS_RED(tmp)) { - RB_SET_COLOR(tmp, EntryColor::Black); - RB_SET_BLACKRED(parent, gparent); - elm = gparent; - continue; - } - - if (RB_LEFT(parent) == elm) { - RB_ROTATE_RIGHT(head, parent, tmp); - tmp = parent; - parent = elm; - elm = tmp; - } - - RB_SET_BLACKRED(parent, gparent); - RB_ROTATE_LEFT(head, gparent, tmp); - } - } - - RB_SET_COLOR(head->Root(), EntryColor::Black); -} - -template <typename Node> -void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { - Node* tmp; - while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root() && parent != nullptr) { +template <typename T> +requires HasRBEntry<T> +constexpr void RB_REMOVE_COLOR(RBHead<T>& head, T* parent, T* elm) { + T* tmp; + while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head.Root()) { if (RB_LEFT(parent) == elm) { tmp = RB_RIGHT(parent); - if (!tmp) { - ASSERT_MSG(false, "tmp is invalid!"); - break; - } if (RB_IS_RED(tmp)) { RB_SET_BLACKRED(tmp, parent); RB_ROTATE_LEFT(head, parent, tmp); @@ -339,29 +310,29 @@ void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { - RB_SET_COLOR(tmp, EntryColor::Red); + RB_SET_COLOR(tmp, RBColor::RB_RED); elm = parent; parent = RB_PARENT(elm); } else { if (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp))) { - Node* oleft; + T* oleft; if ((oleft = RB_LEFT(tmp)) != nullptr) { - RB_SET_COLOR(oleft, EntryColor::Black); + RB_SET_COLOR(oleft, RBColor::RB_BLACK); } - RB_SET_COLOR(tmp, EntryColor::Red); + RB_SET_COLOR(tmp, RBColor::RB_RED); RB_ROTATE_RIGHT(head, tmp, oleft); tmp = RB_RIGHT(parent); } RB_SET_COLOR(tmp, RB_COLOR(parent)); - RB_SET_COLOR(parent, EntryColor::Black); + RB_SET_COLOR(parent, RBColor::RB_BLACK); if (RB_RIGHT(tmp)) { - RB_SET_COLOR(RB_RIGHT(tmp), EntryColor::Black); + RB_SET_COLOR(RB_RIGHT(tmp), RBColor::RB_BLACK); } RB_ROTATE_LEFT(head, parent, tmp); - elm = head->Root(); + elm = head.Root(); break; } } else { @@ -372,68 +343,56 @@ void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { tmp = RB_LEFT(parent); } - if (!tmp) { - ASSERT_MSG(false, "tmp is invalid!"); - break; - } - if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { - RB_SET_COLOR(tmp, EntryColor::Red); + RB_SET_COLOR(tmp, RBColor::RB_RED); elm = parent; parent = RB_PARENT(elm); } else { if (RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) { - Node* oright; + T* oright; if ((oright = RB_RIGHT(tmp)) != nullptr) { - RB_SET_COLOR(oright, EntryColor::Black); + RB_SET_COLOR(oright, RBColor::RB_BLACK); } - RB_SET_COLOR(tmp, EntryColor::Red); + RB_SET_COLOR(tmp, RBColor::RB_RED); RB_ROTATE_LEFT(head, tmp, oright); tmp = RB_LEFT(parent); } RB_SET_COLOR(tmp, RB_COLOR(parent)); - RB_SET_COLOR(parent, EntryColor::Black); + RB_SET_COLOR(parent, RBColor::RB_BLACK); if (RB_LEFT(tmp)) { - RB_SET_COLOR(RB_LEFT(tmp), EntryColor::Black); + RB_SET_COLOR(RB_LEFT(tmp), RBColor::RB_BLACK); } RB_ROTATE_RIGHT(head, parent, tmp); - elm = head->Root(); + elm = head.Root(); break; } } } if (elm) { - RB_SET_COLOR(elm, EntryColor::Black); + RB_SET_COLOR(elm, RBColor::RB_BLACK); } } -template <typename Node> -Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { - Node* child = nullptr; - Node* parent = nullptr; - Node* old = elm; - EntryColor color{}; - - const auto finalize = [&] { - if (color == EntryColor::Black) { - RB_REMOVE_COLOR(head, parent, child); - } - - return old; - }; +template <typename T> +requires HasRBEntry<T> +constexpr T* RB_REMOVE(RBHead<T>& head, T* elm) { + T* child = nullptr; + T* parent = nullptr; + T* old = elm; + RBColor color = RBColor::RB_BLACK; if (RB_LEFT(elm) == nullptr) { child = RB_RIGHT(elm); } else if (RB_RIGHT(elm) == nullptr) { child = RB_LEFT(elm); } else { - Node* left; + T* left; elm = RB_RIGHT(elm); while ((left = RB_LEFT(elm)) != nullptr) { elm = left; @@ -446,6 +405,7 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { if (child) { RB_SET_PARENT(child, parent); } + if (parent) { if (RB_LEFT(parent) == elm) { RB_SET_LEFT(parent, child); @@ -453,14 +413,14 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { RB_SET_RIGHT(parent, child); } } else { - head->SetRoot(child); + head.SetRoot(child); } if (RB_PARENT(elm) == old) { parent = elm; } - elm->SetEntry(old->GetEntry()); + elm->SetRBEntry(old->GetRBEntry()); if (RB_PARENT(old)) { if (RB_LEFT(RB_PARENT(old)) == old) { @@ -469,17 +429,24 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { RB_SET_RIGHT(RB_PARENT(old), elm); } } else { - head->SetRoot(elm); + head.SetRoot(elm); } + RB_SET_PARENT(RB_LEFT(old), elm); + if (RB_RIGHT(old)) { RB_SET_PARENT(RB_RIGHT(old), elm); } + if (parent) { left = parent; } - return finalize(); + if (color == RBColor::RB_BLACK) { + RB_REMOVE_COLOR(head, parent, child); + } + + return old; } parent = RB_PARENT(elm); @@ -495,17 +462,69 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { RB_SET_RIGHT(parent, child); } } else { - head->SetRoot(child); + head.SetRoot(child); + } + + if (color == RBColor::RB_BLACK) { + RB_REMOVE_COLOR(head, parent, child); + } + + return old; +} + +template <typename T> +requires HasRBEntry<T> +constexpr void RB_INSERT_COLOR(RBHead<T>& head, T* elm) { + T *parent = nullptr, *tmp = nullptr; + while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) { + T* gparent = RB_PARENT(parent); + if (parent == RB_LEFT(gparent)) { + tmp = RB_RIGHT(gparent); + if (tmp && RB_IS_RED(tmp)) { + RB_SET_COLOR(tmp, RBColor::RB_BLACK); + RB_SET_BLACKRED(parent, gparent); + elm = gparent; + continue; + } + + if (RB_RIGHT(parent) == elm) { + RB_ROTATE_LEFT(head, parent, tmp); + tmp = parent; + parent = elm; + elm = tmp; + } + + RB_SET_BLACKRED(parent, gparent); + RB_ROTATE_RIGHT(head, gparent, tmp); + } else { + tmp = RB_LEFT(gparent); + if (tmp && RB_IS_RED(tmp)) { + RB_SET_COLOR(tmp, RBColor::RB_BLACK); + RB_SET_BLACKRED(parent, gparent); + elm = gparent; + continue; + } + + if (RB_LEFT(parent) == elm) { + RB_ROTATE_RIGHT(head, parent, tmp); + tmp = parent; + parent = elm; + elm = tmp; + } + + RB_SET_BLACKRED(parent, gparent); + RB_ROTATE_LEFT(head, gparent, tmp); + } } - return finalize(); + RB_SET_COLOR(head.Root(), RBColor::RB_BLACK); } -// Inserts a node into the RB tree -template <typename Node, typename CompareFunction> -Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) { - Node* parent = nullptr; - Node* tmp = head->Root(); +template <typename T, typename Compare> +requires HasRBEntry<T> +constexpr T* RB_INSERT(RBHead<T>& head, T* elm, Compare cmp) { + T* parent = nullptr; + T* tmp = head.Root(); int comp = 0; while (tmp) { @@ -529,17 +548,17 @@ Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) { RB_SET_RIGHT(parent, elm); } } else { - head->SetRoot(elm); + head.SetRoot(elm); } RB_INSERT_COLOR(head, elm); return nullptr; } -// Finds the node with the same key as elm -template <typename Node, typename CompareFunction> -Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { - Node* tmp = head->Root(); +template <typename T, typename Compare> +requires HasRBEntry<T> +constexpr T* RB_FIND(RBHead<T>& head, T* elm, Compare cmp) { + T* tmp = head.Root(); while (tmp) { const int comp = cmp(elm, tmp); @@ -555,11 +574,11 @@ Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { return nullptr; } -// Finds the first node greater than or equal to the search key -template <typename Node, typename CompareFunction> -Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { - Node* tmp = head->Root(); - Node* res = nullptr; +template <typename T, typename Compare> +requires HasRBEntry<T> +constexpr T* RB_NFIND(RBHead<T>& head, T* elm, Compare cmp) { + T* tmp = head.Root(); + T* res = nullptr; while (tmp) { const int comp = cmp(elm, tmp); @@ -576,13 +595,13 @@ Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { return res; } -// Finds the node with the same key as lelm -template <typename Node, typename CompareFunction> -Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) { - Node* tmp = head->Root(); +template <typename T, typename U, typename Compare> +requires HasRBEntry<T> +constexpr T* RB_FIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { + T* tmp = head.Root(); while (tmp) { - const int comp = lcmp(lelm, tmp); + const int comp = cmp(key, tmp); if (comp < 0) { tmp = RB_LEFT(tmp); } else if (comp > 0) { @@ -595,14 +614,14 @@ Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) return nullptr; } -// Finds the first node greater than or equal to the search key -template <typename Node, typename CompareFunction> -Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) { - Node* tmp = head->Root(); - Node* res = nullptr; +template <typename T, typename U, typename Compare> +requires HasRBEntry<T> +constexpr T* RB_NFIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { + T* tmp = head.Root(); + T* res = nullptr; while (tmp) { - const int comp = lcmp(lelm, tmp); + const int comp = cmp(key, tmp); if (comp < 0) { res = tmp; tmp = RB_LEFT(tmp); @@ -616,8 +635,43 @@ Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) return res; } -template <typename Node> -Node* RB_NEXT(Node* elm) { +template <typename T, typename Compare> +requires HasRBEntry<T> +constexpr T* RB_FIND_EXISTING(RBHead<T>& head, T* elm, Compare cmp) { + T* tmp = head.Root(); + + while (true) { + const int comp = cmp(elm, tmp); + if (comp < 0) { + tmp = RB_LEFT(tmp); + } else if (comp > 0) { + tmp = RB_RIGHT(tmp); + } else { + return tmp; + } + } +} + +template <typename T, typename U, typename Compare> +requires HasRBEntry<T> +constexpr T* RB_FIND_EXISTING_KEY(RBHead<T>& head, const U& key, Compare cmp) { + T* tmp = head.Root(); + + while (true) { + const int comp = cmp(key, tmp); + if (comp < 0) { + tmp = RB_LEFT(tmp); + } else if (comp > 0) { + tmp = RB_RIGHT(tmp); + } else { + return tmp; + } + } +} + +template <typename T> +requires HasRBEntry<T> +constexpr T* RB_NEXT(T* elm) { if (RB_RIGHT(elm)) { elm = RB_RIGHT(elm); while (RB_LEFT(elm)) { @@ -636,8 +690,9 @@ Node* RB_NEXT(Node* elm) { return elm; } -template <typename Node> -Node* RB_PREV(Node* elm) { +template <typename T> +requires HasRBEntry<T> +constexpr T* RB_PREV(T* elm) { if (RB_LEFT(elm)) { elm = RB_LEFT(elm); while (RB_RIGHT(elm)) { @@ -656,30 +711,32 @@ Node* RB_PREV(Node* elm) { return elm; } -template <typename Node> -Node* RB_MINMAX(RBHead<Node>* head, bool is_min) { - Node* tmp = head->Root(); - Node* parent = nullptr; +template <typename T> +requires HasRBEntry<T> +constexpr T* RB_MIN(RBHead<T>& head) { + T* tmp = head.Root(); + T* parent = nullptr; while (tmp) { parent = tmp; - if (is_min) { - tmp = RB_LEFT(tmp); - } else { - tmp = RB_RIGHT(tmp); - } + tmp = RB_LEFT(tmp); } return parent; } -template <typename Node> -Node* RB_MIN(RBHead<Node>* head) { - return RB_MINMAX(head, true); -} +template <typename T> +requires HasRBEntry<T> +constexpr T* RB_MAX(RBHead<T>& head) { + T* tmp = head.Root(); + T* parent = nullptr; -template <typename Node> -Node* RB_MAX(RBHead<Node>* head) { - return RB_MINMAX(head, false); + while (tmp) { + parent = tmp; + tmp = RB_RIGHT(tmp); + } + + return parent; } -} // namespace Common + +} // namespace Common::freebsd |