AK+Kernel: Reduce the number of template parameters of IntrusiveRBTree

This makes the user-facing type only take the node member pointer, and
lets the compiler figure out the other needed types from that.
This commit is contained in:
Ali Mohammad Pur 2021-09-09 15:27:19 +04:30 committed by Idan Horowitz
parent 5a0cdb15b0
commit 14c8373eb0
Notes: sideshowbarker 2024-07-18 04:20:26 +09:00
3 changed files with 35 additions and 18 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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)
{