1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-11-23 04:12:02 +00:00

IntrusiveRedBlackTree: refactor to add ->GetPrev(), ->GetNext() to BaseNode inheritors

This commit is contained in:
Michael Scire 2020-08-03 11:32:12 -07:00 committed by SciresM
parent c3fa3bd5d6
commit 90fd771fce
2 changed files with 135 additions and 65 deletions

View file

@ -425,21 +425,35 @@ struct { \
/* Main rb operation. /* Main rb operation.
* Moves node close to the key of elm to top * Moves node close to the key of elm to top
*/ */
#define RB_GENERATE(name, type, field, cmp) \ #define RB_GENERATE_WITHOUT_COMPARE(name, type, field) \
RB_GENERATE_INTERNAL(name, type, field, cmp,) RB_GENERATE_WITHOUT_COMPARE_INTERNAL(name, type, field,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \ #define RB_GENERATE_WITHOUT_COMPARE_STATIC(name, type, field) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static) RB_GENERATE_WITHOUT_COMPARE_INTERNAL(name, type, field, __unused static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ #define RB_GENERATE_WITHOUT_COMPARE_INTERNAL(name, type, field, attr) \
RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
RB_GENERATE_REMOVE_COLOR(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_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_NEXT(name, type, field, attr) \
RB_GENERATE_PREV(name, type, field, attr) \ RB_GENERATE_PREV(name, type, field, attr) \
RB_GENERATE_MINMAX(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) \ #define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
attr void \ attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \

View file

@ -29,17 +29,21 @@ namespace ams::util {
template<class, class, class> template<class, class, class>
friend class IntrusiveRedBlackTree; friend class IntrusiveRedBlackTree;
template<class, class>
friend class IntrusiveRedBlackTreeImpl;
public: public:
constexpr IntrusiveRedBlackTreeNode() : entry() { /* ... */} constexpr IntrusiveRedBlackTreeNode() : entry() { /* ... */}
}; };
static_assert(std::is_literal_type<IntrusiveRedBlackTreeNode>::value); static_assert(std::is_literal_type<IntrusiveRedBlackTreeNode>::value);
template<class T, class Traits, class Comparator> template<class T, class Traits>
class IntrusiveRedBlackTree { class IntrusiveRedBlackTreeImpl {
NON_COPYABLE(IntrusiveRedBlackTree); NON_COPYABLE(IntrusiveRedBlackTreeImpl);
private: protected:
RB_HEAD(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode); RB_HEAD(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode);
using RootType = IntrusiveRedBlackTreeRoot;
protected:
IntrusiveRedBlackTreeRoot root; IntrusiveRedBlackTreeRoot root;
public: public:
template<bool Const> template<bool Const>
@ -59,10 +63,10 @@ namespace ams::util {
class Iterator { class Iterator {
public: public:
using iterator_category = std::bidirectional_iterator_tag; using iterator_category = std::bidirectional_iterator_tag;
using value_type = typename IntrusiveRedBlackTree::value_type; using value_type = typename IntrusiveRedBlackTreeImpl::value_type;
using difference_type = typename IntrusiveRedBlackTree::difference_type; using difference_type = typename IntrusiveRedBlackTreeImpl::difference_type;
using pointer = typename std::conditional<Const, IntrusiveRedBlackTree::const_pointer, IntrusiveRedBlackTree::pointer>::type; using pointer = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_pointer, IntrusiveRedBlackTreeImpl::pointer>::type;
using reference = typename std::conditional<Const, IntrusiveRedBlackTree::const_reference, IntrusiveRedBlackTree::reference>::type; using reference = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_reference, IntrusiveRedBlackTreeImpl::reference>::type;
private: private:
pointer node; pointer node;
public: public:
@ -110,30 +114,10 @@ namespace ams::util {
return Iterator<true>(this->node); return Iterator<true>(this->node);
} }
}; };
protected:
/* Generate static implementations for non-comparison operations for IntrusiveRedBlackTreeRoot. */
RB_GENERATE_WITHOUT_COMPARE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry);
private: 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<const IntrusiveRedBlackTreeNode *>(GetNext(const_cast<IntrusiveRedBlackTreeNode *>(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<const IntrusiveRedBlackTreeNode *>(GetPrev(const_cast<IntrusiveRedBlackTreeNode *>(node)));
}
/* Define accessors using RB_* functions. */ /* Define accessors using RB_* functions. */
constexpr ALWAYS_INLINE void InitializeImpl() { constexpr ALWAYS_INLINE void InitializeImpl() {
RB_INIT(&this->root); RB_INIT(&this->root);
@ -151,24 +135,27 @@ namespace ams::util {
return RB_MAX(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root)); return RB_MAX(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
} }
IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) {
return RB_INSERT(IntrusiveRedBlackTreeRoot, &this->root, node);
}
IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) { IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) {
return RB_REMOVE(IntrusiveRedBlackTreeRoot, &this->root, node); return RB_REMOVE(IntrusiveRedBlackTreeRoot, &this->root, node);
} }
IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
return RB_FIND(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root), const_cast<IntrusiveRedBlackTreeNode *>(node));
}
IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
return RB_NFIND(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root), const_cast<IntrusiveRedBlackTreeNode *>(node));
}
public: 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<const IntrusiveRedBlackTreeNode *>(GetNext(const_cast<IntrusiveRedBlackTreeNode *>(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<const IntrusiveRedBlackTreeNode *>(GetPrev(const_cast<IntrusiveRedBlackTreeNode *>(node)));
}
public:
constexpr ALWAYS_INLINE IntrusiveRedBlackTreeImpl() : root() {
this->InitializeImpl(); this->InitializeImpl();
} }
@ -226,17 +213,58 @@ namespace ams::util {
return *Traits::GetParent(this->GetMinImpl()); return *Traits::GetParent(this->GetMinImpl());
} }
iterator insert(reference ref) {
this->InsertImpl(Traits::GetNode(&ref));
return iterator(&ref);
}
iterator erase(iterator it) { iterator erase(iterator it) {
auto cur = Traits::GetNode(&*it); auto cur = Traits::GetNode(&*it);
auto next = Traits::GetParent(GetNext(cur)); auto next = Traits::GetParent(GetNext(cur));
this->RemoveImpl(cur); this->RemoveImpl(cur);
return iterator(next); return iterator(next);
} }
};
template<class T, class Traits, class Comparator>
class IntrusiveRedBlackTree : public IntrusiveRedBlackTreeImpl<T, Traits> {
NON_COPYABLE(IntrusiveRedBlackTree);
public:
using ImplType = IntrusiveRedBlackTreeImpl<T, Traits>;
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<IntrusiveRedBlackTreeRootWithCompare *>(&this->root), node);
}
IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
return RB_FIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
}
IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
return RB_NFIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->root)), const_cast<IntrusiveRedBlackTreeNode *>(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 { iterator find(const_reference ref) const {
return iterator(Traits::GetParent(this->FindImpl(Traits::GetNode(&ref)))); return iterator(Traits::GetParent(this->FindImpl(Traits::GetNode(&ref))));
@ -254,10 +282,13 @@ namespace ams::util {
class IntrusiveRedBlackTreeMemberTraits<Member, Derived> { class IntrusiveRedBlackTreeMemberTraits<Member, Derived> {
public: public:
template<class Comparator> template<class Comparator>
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraits, Comparator>; using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraits, Comparator>;
using TreeTypeImpl = IntrusiveRedBlackTreeImpl<Derived, IntrusiveRedBlackTreeMemberTraits>;
private: private:
template<class, class, class> template<class, class, class>
friend class IntrusiveRedBlackTree; friend class IntrusiveRedBlackTree;
template<class, class>
friend class IntrusiveRedBlackTreeImpl;
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) { static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
return std::addressof(parent->*Member); return std::addressof(parent->*Member);
@ -286,7 +317,8 @@ namespace ams::util {
class IntrusiveRedBlackTreeMemberTraitsDeferredAssert<Member, Derived> { class IntrusiveRedBlackTreeMemberTraitsDeferredAssert<Member, Derived> {
public: public:
template<class Comparator> template<class Comparator>
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>; using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>;
using TreeTypeImpl = IntrusiveRedBlackTreeImpl<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert>;
static constexpr bool IsValid() { static constexpr bool IsValid() {
TYPED_STORAGE(Derived) DerivedStorage = {}; TYPED_STORAGE(Derived) DerivedStorage = {};
@ -295,6 +327,8 @@ namespace ams::util {
private: private:
template<class, class, class> template<class, class, class>
friend class IntrusiveRedBlackTree; friend class IntrusiveRedBlackTree;
template<class, class>
friend class IntrusiveRedBlackTreeImpl;
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) { static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
return std::addressof(parent->*Member); return std::addressof(parent->*Member);
@ -314,16 +348,26 @@ namespace ams::util {
}; };
template<class Derived> template<class Derived>
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 Derived> template<class Derived>
class IntrusiveRedBlackTreeBaseTraits { class IntrusiveRedBlackTreeBaseTraits {
public: public:
template<class Comparator> template<class Comparator>
using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeBaseTraits, Comparator>; using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeBaseTraits, Comparator>;
using TreeTypeImpl = IntrusiveRedBlackTreeImpl<Derived, IntrusiveRedBlackTreeBaseTraits>;
private: private:
template<class, class, class> template<class, class, class>
friend class IntrusiveRedBlackTree; friend class IntrusiveRedBlackTree;
template<class, class>
friend class IntrusiveRedBlackTreeImpl;
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) { static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
return static_cast<IntrusiveRedBlackTreeNode *>(parent); return static_cast<IntrusiveRedBlackTreeNode *>(parent);
@ -342,4 +386,16 @@ namespace ams::util {
} }
}; };
} template<class Derived>
constexpr Derived *IntrusiveRedBlackTreeBaseNode<Derived>::GetPrev() { using TreeType = typename IntrusiveRedBlackTreeBaseTraits<Derived>::TreeTypeImpl; return static_cast<Derived *>(TreeType::GetPrev(static_cast<Derived *>(this))); }
template<class Derived>
constexpr const Derived *IntrusiveRedBlackTreeBaseNode<Derived>::GetPrev() const { using TreeType = typename IntrusiveRedBlackTreeBaseTraits<Derived>::TreeTypeImpl; return static_cast<const Derived *>(TreeType::GetPrev(static_cast<const Derived *>(this))); }
template<class Derived>
constexpr Derived *IntrusiveRedBlackTreeBaseNode<Derived>::GetNext() { using TreeType = typename IntrusiveRedBlackTreeBaseTraits<Derived>::TreeTypeImpl; return static_cast<Derived *>(TreeType::GetNext(static_cast<Derived *>(this))); }
template<class Derived>
constexpr const Derived *IntrusiveRedBlackTreeBaseNode<Derived>::GetNext() const { using TreeType = typename IntrusiveRedBlackTreeBaseTraits<Derived>::TreeTypeImpl; return static_cast<const Derived *>(TreeType::GetNext(static_cast<const Derived *>(this))); }
}