diff --git a/AK/IntrusiveRedBlackTree.h b/AK/IntrusiveRedBlackTree.h index 6190f6b27a5..56424ec8465 100644 --- a/AK/IntrusiveRedBlackTree.h +++ b/AK/IntrusiveRedBlackTree.h @@ -9,17 +9,24 @@ #include <AK/IntrusiveDetails.h> #include <AK/RedBlackTree.h> -namespace AK { +namespace AK::Detail { -namespace Detail { template<Integral K, typename V, typename Container = RawPtr<V>> class IntrusiveRedBlackTreeNode; -} + +struct ExtractIntrusiveRedBlackTreeTypes { + template<typename K, typename V, typename Container, typename T> + static K key(IntrusiveRedBlackTreeNode<K, V, Container> T::*x); + template<typename K, typename V, typename Container, typename T> + static V value(IntrusiveRedBlackTreeNode<K, V, Container> T::*x); + template<typename K, typename V, typename Container, typename T> + static Container container(IntrusiveRedBlackTreeNode<K, V, Container> T::*x); +}; template<Integral K, typename V, typename Container = RawPtr<V>> -using IntrusiveRedBlackTreeNode = Detail::IntrusiveRedBlackTreeNode<K, V, typename Detail::SubstituteIntrusiveContainerType<V, Container>::Type>; +using SubstitutedIntrusiveRedBlackTreeNode = IntrusiveRedBlackTreeNode<K, V, typename Detail::SubstituteIntrusiveContainerType<V, Container>::Type>; -template<Integral K, typename V, typename Container, IntrusiveRedBlackTreeNode<K, V, Container> V::*member> +template<Integral K, typename V, typename Container, SubstitutedIntrusiveRedBlackTreeNode<K, V, Container> V::*member> class IntrusiveRedBlackTree : public BaseRedBlackTree<K> { public: @@ -30,7 +37,7 @@ public: } using BaseTree = BaseRedBlackTree<K>; - using TreeNode = IntrusiveRedBlackTreeNode<K, V, Container>; + using TreeNode = SubstitutedIntrusiveRedBlackTreeNode<K, V, Container>; Container find(K key) { @@ -161,8 +168,6 @@ private: } }; -namespace Detail { - template<Integral K, typename V, typename Container> class IntrusiveRedBlackTreeNode : public BaseRedBlackTree<K>::Node { public: @@ -185,20 +190,18 @@ public: #ifndef __clang__ private: - template<Integral TK, typename TV, typename TContainer, IntrusiveRedBlackTreeNode<TK, TV, TContainer> TV::*member> - friend class ::AK::IntrusiveRedBlackTree; + template<Integral TK, typename TV, typename TContainer, SubstitutedIntrusiveRedBlackTreeNode<TK, TV, TContainer> TV::*member> + friend class ::AK::Detail::IntrusiveRedBlackTree; #endif bool m_in_tree { false }; [[no_unique_address]] SelfReferenceIfNeeded<Container, IsRaw> m_self; }; -} - // Specialise IntrusiveRedBlackTree for NonnullRefPtr // By default, red black trees cannot contain null entries anyway, so switch to RefPtr // and just make the user-facing functions deref the pointers. -template<Integral K, typename V, IntrusiveRedBlackTreeNode<K, V, NonnullRefPtr<V>> V::*member> +template<Integral K, typename V, SubstitutedIntrusiveRedBlackTreeNode<K, V, NonnullRefPtr<V>> V::*member> class IntrusiveRedBlackTree<K, V, NonnullRefPtr<V>, member> : public IntrusiveRedBlackTree<K, V, RefPtr<V>, member> { public: [[nodiscard]] NonnullRefPtr<V> find(K key) const { return IntrusiveRedBlackTree<K, V, RefPtr<V>, member>::find(key).release_nonnull(); } @@ -207,5 +210,19 @@ public: } +namespace AK { + +template<Integral K, typename V, typename Container = RawPtr<K>> +using IntrusiveRedBlackTreeNode = Detail::SubstitutedIntrusiveRedBlackTreeNode<K, V, Container>; + +template<auto member> +using IntrusiveRedBlackTree = Detail::IntrusiveRedBlackTree< + decltype(Detail::ExtractIntrusiveRedBlackTreeTypes::key(member)), + decltype(Detail::ExtractIntrusiveRedBlackTreeTypes::value(member)), + decltype(Detail::ExtractIntrusiveRedBlackTreeTypes::container(member)), + member>; + +} + using AK::IntrusiveRedBlackTree; using AK::IntrusiveRedBlackTreeNode; diff --git a/Kernel/Memory/PageDirectory.cpp b/Kernel/Memory/PageDirectory.cpp index 133bfc91651..e277e634547 100644 --- a/Kernel/Memory/PageDirectory.cpp +++ b/Kernel/Memory/PageDirectory.cpp @@ -17,9 +17,9 @@ extern u8 end_of_kernel_image[]; namespace Kernel::Memory { -static Singleton<IntrusiveRedBlackTree<FlatPtr, PageDirectory, RawPtr<PageDirectory>, &PageDirectory::m_tree_node>> s_cr3_map; +static Singleton<IntrusiveRedBlackTree<&PageDirectory::m_tree_node>> s_cr3_map; -static IntrusiveRedBlackTree<FlatPtr, PageDirectory, RawPtr<PageDirectory>, &PageDirectory::m_tree_node>& cr3_map() +static IntrusiveRedBlackTree<&PageDirectory::m_tree_node>& cr3_map() { VERIFY_INTERRUPTS_DISABLED(); return *s_cr3_map; diff --git a/Tests/AK/TestIntrusiveRedBlackTree.cpp b/Tests/AK/TestIntrusiveRedBlackTree.cpp index a27e8abb186..6492c577704 100644 --- a/Tests/AK/TestIntrusiveRedBlackTree.cpp +++ b/Tests/AK/TestIntrusiveRedBlackTree.cpp @@ -20,7 +20,7 @@ public: IntrusiveRedBlackTreeNode<int, IntrusiveTest, RawPtr<IntrusiveTest>> m_tree_node; int m_some_value; }; -using IntrusiveRBTree = IntrusiveRedBlackTree<int, IntrusiveTest, RawPtr<IntrusiveTest>, &IntrusiveTest::m_tree_node>; +using IntrusiveRBTree = IntrusiveRedBlackTree<&IntrusiveTest::m_tree_node>; TEST_CASE(construct) { @@ -123,7 +123,7 @@ public: IntrusiveRedBlackTreeNode<int, IntrusiveRefPtrTest, RefPtr<IntrusiveRefPtrTest>> m_tree_node; }; -using IntrusiveRefPtrRBTree = IntrusiveRedBlackTree<int, IntrusiveRefPtrTest, RefPtr<IntrusiveRefPtrTest>, &IntrusiveRefPtrTest::m_tree_node>; +using IntrusiveRefPtrRBTree = IntrusiveRedBlackTree<&IntrusiveRefPtrTest::m_tree_node>; TEST_CASE(intrusive_ref_ptr_no_ref_leaks) { @@ -173,7 +173,7 @@ public: IntrusiveRedBlackTreeNode<int, IntrusiveNonnullRefPtrTest, NonnullRefPtr<IntrusiveNonnullRefPtrTest>> m_tree_node; }; -using IntrusiveNonnullRefPtrRBTree = IntrusiveRedBlackTree<int, IntrusiveNonnullRefPtrTest, NonnullRefPtr<IntrusiveNonnullRefPtrTest>, &IntrusiveNonnullRefPtrTest::m_tree_node>; +using IntrusiveNonnullRefPtrRBTree = IntrusiveRedBlackTree<&IntrusiveNonnullRefPtrTest::m_tree_node>; TEST_CASE(intrusive_nonnull_ref_ptr_intrusive) {