diff --git a/libraries/libvapours/include/freebsd/sys/tree.h b/libraries/libvapours/include/freebsd/sys/tree.h index fecde6913..d18ee1821 100644 --- a/libraries/libvapours/include/freebsd/sys/tree.h +++ b/libraries/libvapours/include/freebsd/sys/tree.h @@ -425,21 +425,35 @@ struct { \ /* Main rb operation. * Moves node close to the key of elm to top */ -#define RB_GENERATE(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp,) -#define RB_GENERATE_STATIC(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static) -#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ - RB_GENERATE_INSERT_COLOR(name, type, field, attr) \ +#define RB_GENERATE_WITHOUT_COMPARE(name, type, field) \ + RB_GENERATE_WITHOUT_COMPARE_INTERNAL(name, type, field,) +#define RB_GENERATE_WITHOUT_COMPARE_STATIC(name, type, field) \ + RB_GENERATE_WITHOUT_COMPARE_INTERNAL(name, type, field, __unused static) +#define RB_GENERATE_WITHOUT_COMPARE_INTERNAL(name, type, field, attr) \ RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \ - RB_GENERATE_INSERT(name, type, field, cmp, attr) \ RB_GENERATE_REMOVE(name, type, field, attr) \ - RB_GENERATE_FIND(name, type, field, cmp, attr) \ - RB_GENERATE_NFIND(name, type, field, cmp, attr) \ RB_GENERATE_NEXT(name, type, field, attr) \ RB_GENERATE_PREV(name, type, field, attr) \ RB_GENERATE_MINMAX(name, type, field, attr) +#define RB_GENERATE_WITH_COMPARE(name, type, field, cmp) \ + RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_WITH_COMPARE_STATIC(name, type, field, cmp) \ + RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp, attr) \ + RB_GENERATE_INSERT_COLOR(name, type, field, attr) \ + RB_GENERATE_INSERT(name, type, field, cmp, attr) \ + RB_GENERATE_FIND(name, type, field, cmp, attr) \ + RB_GENERATE_NFIND(name, type, field, cmp, attr) + +#define RB_GENERATE_ALL(name, type, field, cmp) \ + RB_GENERATE_ALL_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_ALL_STATIC(name, type, field, cmp) \ + RB_GENERATE_ALL_INTERNAL(name, type, field, cmp, __unused static) +#define RB_GENERATE_ALL_INTERNAL(name, type, field, cmp, attr) \ + RB_GENERATE_WITHOUT_COMPARE_INTERNAL(name, type, field, attr) \ + RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp, attr) + #define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \ attr void \ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ diff --git a/libraries/libvapours/include/vapours/util/util_intrusive_red_black_tree.hpp b/libraries/libvapours/include/vapours/util/util_intrusive_red_black_tree.hpp index d7910f5b8..7c114e7cb 100644 --- a/libraries/libvapours/include/vapours/util/util_intrusive_red_black_tree.hpp +++ b/libraries/libvapours/include/vapours/util/util_intrusive_red_black_tree.hpp @@ -29,17 +29,21 @@ namespace ams::util { template friend class IntrusiveRedBlackTree; + + template + friend class IntrusiveRedBlackTreeImpl; public: constexpr IntrusiveRedBlackTreeNode() : entry() { /* ... */} }; static_assert(std::is_literal_type::value); - template - class IntrusiveRedBlackTree { - NON_COPYABLE(IntrusiveRedBlackTree); - private: + template + class IntrusiveRedBlackTreeImpl { + NON_COPYABLE(IntrusiveRedBlackTreeImpl); + protected: RB_HEAD(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode); - + using RootType = IntrusiveRedBlackTreeRoot; + protected: IntrusiveRedBlackTreeRoot root; public: template @@ -59,10 +63,10 @@ namespace ams::util { class Iterator { public: 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::type; - using reference = typename std::conditional::type; + using value_type = typename IntrusiveRedBlackTreeImpl::value_type; + using difference_type = typename IntrusiveRedBlackTreeImpl::difference_type; + using pointer = typename std::conditional::type; + using reference = typename std::conditional::type; private: pointer node; public: @@ -110,30 +114,10 @@ namespace ams::util { return Iterator(this->node); } }; + protected: + /* Generate static implementations for non-comparison operations for IntrusiveRedBlackTreeRoot. */ + RB_GENERATE_WITHOUT_COMPARE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry); private: - static int CompareImpl(const IntrusiveRedBlackTreeNode *lhs, const IntrusiveRedBlackTreeNode *rhs) { - return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs)); - } - - /* Generate static implementations for IntrusiveRedBlackTreeRoot. */ - RB_GENERATE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry, CompareImpl); - - static constexpr inline IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) { - return RB_NEXT(IntrusiveRedBlackTreeRoot, nullptr, node); - } - - static constexpr inline IntrusiveRedBlackTreeNode const *GetNext(IntrusiveRedBlackTreeNode const *node) { - return const_cast(GetNext(const_cast(node))); - } - - static constexpr inline IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) { - return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node); - } - - static constexpr inline IntrusiveRedBlackTreeNode const *GetPrev(IntrusiveRedBlackTreeNode const *node) { - return const_cast(GetPrev(const_cast(node))); - } - /* Define accessors using RB_* functions. */ constexpr ALWAYS_INLINE void InitializeImpl() { RB_INIT(&this->root); @@ -151,24 +135,27 @@ namespace ams::util { return RB_MAX(IntrusiveRedBlackTreeRoot, const_cast(&this->root)); } - IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) { - return RB_INSERT(IntrusiveRedBlackTreeRoot, &this->root, node); - } - IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) { return RB_REMOVE(IntrusiveRedBlackTreeRoot, &this->root, node); } - - IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const { - return RB_FIND(IntrusiveRedBlackTreeRoot, const_cast(&this->root), const_cast(node)); - } - - IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const { - return RB_NFIND(IntrusiveRedBlackTreeRoot, const_cast(&this->root), const_cast(node)); - } - public: - constexpr ALWAYS_INLINE IntrusiveRedBlackTree() : root() { + static constexpr inline IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) { + return RB_NEXT(IntrusiveRedBlackTreeRoot, nullptr, node); + } + + static constexpr inline IntrusiveRedBlackTreeNode const *GetNext(IntrusiveRedBlackTreeNode const *node) { + return const_cast(GetNext(const_cast(node))); + } + + static constexpr inline IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) { + return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node); + } + + static constexpr inline IntrusiveRedBlackTreeNode const *GetPrev(IntrusiveRedBlackTreeNode const *node) { + return const_cast(GetPrev(const_cast(node))); + } + public: + constexpr ALWAYS_INLINE IntrusiveRedBlackTreeImpl() : root() { this->InitializeImpl(); } @@ -226,17 +213,58 @@ namespace ams::util { return *Traits::GetParent(this->GetMinImpl()); } - iterator insert(reference ref) { - this->InsertImpl(Traits::GetNode(&ref)); - return iterator(&ref); - } - iterator erase(iterator it) { auto cur = Traits::GetNode(&*it); auto next = Traits::GetParent(GetNext(cur)); this->RemoveImpl(cur); return iterator(next); } + }; + + template + class IntrusiveRedBlackTree : public IntrusiveRedBlackTreeImpl { + NON_COPYABLE(IntrusiveRedBlackTree); + public: + using ImplType = IntrusiveRedBlackTreeImpl; + + struct IntrusiveRedBlackTreeRootWithCompare : ImplType::IntrusiveRedBlackTreeRoot{}; + + using value_type = ImplType::value_type; + using size_type = ImplType::size_type; + using difference_type = ImplType::difference_type; + using pointer = ImplType::pointer; + using const_pointer = ImplType::const_pointer; + using reference = ImplType::reference; + using const_reference = ImplType::const_reference; + using iterator = ImplType::iterator; + using const_iterator = ImplType::const_iterator; + protected: + /* Generate static implementations for comparison operations for IntrusiveRedBlackTreeRoot. */ + RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode, entry, CompareImpl); + private: + static int CompareImpl(const IntrusiveRedBlackTreeNode *lhs, const IntrusiveRedBlackTreeNode *rhs) { + return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs)); + } + + /* Define accessors using RB_* functions. */ + IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) { + return RB_INSERT(IntrusiveRedBlackTreeRootWithCompare, static_cast(&this->root), node); + } + + IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const { + return RB_FIND(IntrusiveRedBlackTreeRootWithCompare, const_cast(static_cast(&this->root)), const_cast(node)); + } + + IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const { + return RB_NFIND(IntrusiveRedBlackTreeRootWithCompare, const_cast(static_cast(&this->root)), const_cast(node)); + } + public: + constexpr ALWAYS_INLINE IntrusiveRedBlackTree() : ImplType() { /* ... */ } + + iterator insert(reference ref) { + this->InsertImpl(Traits::GetNode(&ref)); + return iterator(&ref); + } iterator find(const_reference ref) const { return iterator(Traits::GetParent(this->FindImpl(Traits::GetNode(&ref)))); @@ -254,10 +282,13 @@ namespace ams::util { class IntrusiveRedBlackTreeMemberTraits { public: template - using TreeType = IntrusiveRedBlackTree; + using TreeType = IntrusiveRedBlackTree; + using TreeTypeImpl = IntrusiveRedBlackTreeImpl; private: template friend class IntrusiveRedBlackTree; + template + friend class IntrusiveRedBlackTreeImpl; static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) { return std::addressof(parent->*Member); @@ -286,7 +317,8 @@ namespace ams::util { class IntrusiveRedBlackTreeMemberTraitsDeferredAssert { public: template - using TreeType = IntrusiveRedBlackTree; + using TreeType = IntrusiveRedBlackTree; + using TreeTypeImpl = IntrusiveRedBlackTreeImpl; static constexpr bool IsValid() { TYPED_STORAGE(Derived) DerivedStorage = {}; @@ -295,6 +327,8 @@ namespace ams::util { private: template friend class IntrusiveRedBlackTree; + template + friend class IntrusiveRedBlackTreeImpl; static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) { return std::addressof(parent->*Member); @@ -314,16 +348,26 @@ namespace ams::util { }; template - class IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode{}; + class IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode { + public: + constexpr ALWAYS_INLINE Derived *GetPrev(); + constexpr ALWAYS_INLINE const Derived *GetPrev() const; + + constexpr ALWAYS_INLINE Derived *GetNext(); + constexpr ALWAYS_INLINE const Derived *GetNext() const; + }; template class IntrusiveRedBlackTreeBaseTraits { public: template - using TreeType = IntrusiveRedBlackTree; + using TreeType = IntrusiveRedBlackTree; + using TreeTypeImpl = IntrusiveRedBlackTreeImpl; private: template friend class IntrusiveRedBlackTree; + template + friend class IntrusiveRedBlackTreeImpl; static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) { return static_cast(parent); @@ -342,4 +386,16 @@ namespace ams::util { } }; -} \ No newline at end of file + template + constexpr Derived *IntrusiveRedBlackTreeBaseNode::GetPrev() { using TreeType = typename IntrusiveRedBlackTreeBaseTraits::TreeTypeImpl; return static_cast(TreeType::GetPrev(static_cast(this))); } + + template + constexpr const Derived *IntrusiveRedBlackTreeBaseNode::GetPrev() const { using TreeType = typename IntrusiveRedBlackTreeBaseTraits::TreeTypeImpl; return static_cast(TreeType::GetPrev(static_cast(this))); } + + template + constexpr Derived *IntrusiveRedBlackTreeBaseNode::GetNext() { using TreeType = typename IntrusiveRedBlackTreeBaseTraits::TreeTypeImpl; return static_cast(TreeType::GetNext(static_cast(this))); } + + template + constexpr const Derived *IntrusiveRedBlackTreeBaseNode::GetNext() const { using TreeType = typename IntrusiveRedBlackTreeBaseTraits::TreeTypeImpl; return static_cast(TreeType::GetNext(static_cast(this))); } + +}