AK: Set IntrusiveRBTree Node key on insertion instead of construction

This makes the API look much nicer.
This commit is contained in:
Idan Horowitz 2021-09-08 03:07:34 +03:00
parent 1db9250766
commit cb9720baab
3 changed files with 33 additions and 37 deletions

View file

@ -48,10 +48,11 @@ public:
return node_to_value(*node); return node_to_value(*node);
} }
void insert(V& value) void insert(K key, V& value)
{ {
auto& node = value.*member; auto& node = value.*member;
VERIFY(!node.m_in_tree); VERIFY(!node.m_in_tree);
node.key = key;
BaseTree::insert(&node); BaseTree::insert(&node);
if constexpr (!TreeNode::IsRaw) if constexpr (!TreeNode::IsRaw)
node.m_self.reference = &value; // Note: Self-reference ensures that the object will keep a ref to itself when the Container is a smart pointer. node.m_self.reference = &value; // Note: Self-reference ensures that the object will keep a ref to itself when the Container is a smart pointer.
@ -165,11 +166,6 @@ namespace Detail {
template<Integral K, typename V, typename Container> template<Integral K, typename V, typename Container>
class IntrusiveRedBlackTreeNode : public BaseRedBlackTree<K>::Node { class IntrusiveRedBlackTreeNode : public BaseRedBlackTree<K>::Node {
public: public:
IntrusiveRedBlackTreeNode(K key)
: BaseRedBlackTree<K>::Node(key)
{
}
~IntrusiveRedBlackTreeNode() ~IntrusiveRedBlackTreeNode()
{ {
VERIFY(!is_in_tree()); VERIFY(!is_in_tree());

View file

@ -38,6 +38,9 @@ public:
: key(key) : key(key)
{ {
} }
Node()
{
}
virtual ~Node() {}; virtual ~Node() {};
}; };

View file

@ -12,9 +12,8 @@
class IntrusiveTest { class IntrusiveTest {
public: public:
IntrusiveTest(int key, int value) IntrusiveTest(int value)
: m_tree_node(key) : m_some_value(value)
, m_some_value(value)
{ {
} }
@ -33,12 +32,12 @@ TEST_CASE(construct)
TEST_CASE(ints) TEST_CASE(ints)
{ {
IntrusiveRBTree test; IntrusiveRBTree test;
IntrusiveTest first { 1, 10 }; IntrusiveTest first { 10 };
test.insert(first); test.insert(1, first);
IntrusiveTest second { 3, 20 }; IntrusiveTest second { 20 };
test.insert(second); test.insert(3, second);
IntrusiveTest third { 2, 30 }; IntrusiveTest third { 30 };
test.insert(third); test.insert(2, third);
EXPECT_EQ(test.size(), 3u); EXPECT_EQ(test.size(), 3u);
EXPECT_EQ(test.find(3)->m_some_value, 20); EXPECT_EQ(test.find(3)->m_some_value, 20);
EXPECT_EQ(test.find(2)->m_some_value, 30); EXPECT_EQ(test.find(2)->m_some_value, 30);
@ -53,12 +52,12 @@ TEST_CASE(ints)
TEST_CASE(largest_smaller_than) TEST_CASE(largest_smaller_than)
{ {
IntrusiveRBTree test; IntrusiveRBTree test;
IntrusiveTest first { 1, 10 }; IntrusiveTest first { 10 };
test.insert(first); test.insert(1, first);
IntrusiveTest second { 11, 20 }; IntrusiveTest second { 20 };
test.insert(second); test.insert(11, second);
IntrusiveTest third { 21, 30 }; IntrusiveTest third { 30 };
test.insert(third); test.insert(21, third);
EXPECT_EQ(test.size(), 3u); EXPECT_EQ(test.size(), 3u);
EXPECT_EQ(test.find_largest_not_above(3)->m_some_value, 10); EXPECT_EQ(test.find_largest_not_above(3)->m_some_value, 10);
EXPECT_EQ(test.find_largest_not_above(17)->m_some_value, 20); EXPECT_EQ(test.find_largest_not_above(17)->m_some_value, 20);
@ -86,8 +85,8 @@ TEST_CASE(key_ordered_iteration)
// insert random keys // insert random keys
for (size_t i = 0; i < amount; i++) { for (size_t i = 0; i < amount; i++) {
auto entry = make<IntrusiveTest>(keys[i], keys[i]); auto entry = make<IntrusiveTest>(keys[i]);
test.insert(*entry); test.insert(keys[i], *entry);
m_entries.append(move(entry)); m_entries.append(move(entry));
} }
@ -108,8 +107,8 @@ TEST_CASE(clear)
IntrusiveRBTree test; IntrusiveRBTree test;
NonnullOwnPtrVector<IntrusiveTest> m_entries; NonnullOwnPtrVector<IntrusiveTest> m_entries;
for (size_t i = 0; i < 1000; i++) { for (size_t i = 0; i < 1000; i++) {
auto entry = make<IntrusiveTest>(i, i); auto entry = make<IntrusiveTest>(i);
test.insert(*entry); test.insert(i, *entry);
m_entries.append(move(entry)); m_entries.append(move(entry));
} }
test.clear(); test.clear();
@ -118,8 +117,7 @@ TEST_CASE(clear)
class IntrusiveRefPtrTest : public RefCounted<IntrusiveRefPtrTest> { class IntrusiveRefPtrTest : public RefCounted<IntrusiveRefPtrTest> {
public: public:
IntrusiveRefPtrTest(int key) IntrusiveRefPtrTest()
: m_tree_node(key)
{ {
} }
@ -129,11 +127,11 @@ using IntrusiveRefPtrRBTree = IntrusiveRedBlackTree<int, IntrusiveRefPtrTest, Re
TEST_CASE(intrusive_ref_ptr_no_ref_leaks) TEST_CASE(intrusive_ref_ptr_no_ref_leaks)
{ {
auto item = adopt_ref(*new IntrusiveRefPtrTest(0)); auto item = adopt_ref(*new IntrusiveRefPtrTest());
EXPECT_EQ(1u, item->ref_count()); EXPECT_EQ(1u, item->ref_count());
IntrusiveRefPtrRBTree ref_tree; IntrusiveRefPtrRBTree ref_tree;
ref_tree.insert(*item); ref_tree.insert(0, *item);
EXPECT_EQ(2u, item->ref_count()); EXPECT_EQ(2u, item->ref_count());
ref_tree.remove(0); ref_tree.remove(0);
@ -142,11 +140,11 @@ TEST_CASE(intrusive_ref_ptr_no_ref_leaks)
TEST_CASE(intrusive_ref_ptr_clear) TEST_CASE(intrusive_ref_ptr_clear)
{ {
auto item = adopt_ref(*new IntrusiveRefPtrTest(0)); auto item = adopt_ref(*new IntrusiveRefPtrTest());
EXPECT_EQ(1u, item->ref_count()); EXPECT_EQ(1u, item->ref_count());
IntrusiveRefPtrRBTree ref_tree; IntrusiveRefPtrRBTree ref_tree;
ref_tree.insert(*item); ref_tree.insert(0, *item);
EXPECT_EQ(2u, item->ref_count()); EXPECT_EQ(2u, item->ref_count());
ref_tree.clear(); ref_tree.clear();
@ -155,12 +153,12 @@ TEST_CASE(intrusive_ref_ptr_clear)
TEST_CASE(intrusive_ref_ptr_destructor) TEST_CASE(intrusive_ref_ptr_destructor)
{ {
auto item = adopt_ref(*new IntrusiveRefPtrTest(0)); auto item = adopt_ref(*new IntrusiveRefPtrTest());
EXPECT_EQ(1u, item->ref_count()); EXPECT_EQ(1u, item->ref_count());
{ {
IntrusiveRefPtrRBTree ref_tree; IntrusiveRefPtrRBTree ref_tree;
ref_tree.insert(*item); ref_tree.insert(0, *item);
EXPECT_EQ(2u, item->ref_count()); EXPECT_EQ(2u, item->ref_count());
} }
@ -169,8 +167,7 @@ TEST_CASE(intrusive_ref_ptr_destructor)
class IntrusiveNonnullRefPtrTest : public RefCounted<IntrusiveNonnullRefPtrTest> { class IntrusiveNonnullRefPtrTest : public RefCounted<IntrusiveNonnullRefPtrTest> {
public: public:
IntrusiveNonnullRefPtrTest(int key) IntrusiveNonnullRefPtrTest()
: m_tree_node(key)
{ {
} }
@ -180,11 +177,11 @@ using IntrusiveNonnullRefPtrRBTree = IntrusiveRedBlackTree<int, IntrusiveNonnull
TEST_CASE(intrusive_nonnull_ref_ptr_intrusive) TEST_CASE(intrusive_nonnull_ref_ptr_intrusive)
{ {
auto item = adopt_ref(*new IntrusiveNonnullRefPtrTest(0)); auto item = adopt_ref(*new IntrusiveNonnullRefPtrTest());
EXPECT_EQ(1u, item->ref_count()); EXPECT_EQ(1u, item->ref_count());
IntrusiveNonnullRefPtrRBTree nonnull_ref_tree; IntrusiveNonnullRefPtrRBTree nonnull_ref_tree;
nonnull_ref_tree.insert(*item); nonnull_ref_tree.insert(0, *item);
EXPECT_EQ(2u, item->ref_count()); EXPECT_EQ(2u, item->ref_count());
EXPECT(!nonnull_ref_tree.is_empty()); EXPECT(!nonnull_ref_tree.is_empty());