Skip to content

Commit

Permalink
AK+Tests: Add IntrusiveList<T,...>::insert_before(..) method
Browse files Browse the repository at this point in the history
The insert_before method on AK::InlineLinkedList is used, so in order to
achieve feature parity, we need to implement it for AK::IntrusiveList as
well.
  • Loading branch information
bgianfo authored and awesomekling committed Jun 16, 2021
1 parent 4586668 commit b7f8343
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
23 changes: 23 additions & 0 deletions AK/IntrusiveList.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class IntrusiveList {
[[nodiscard]] size_t size_slow() const;
void append(T& n);
void prepend(T& n);
void insert_before(T&, T&);
void remove(T& n);
[[nodiscard]] bool contains(const T&) const;
[[nodiscard]] Container first() const;
Expand Down Expand Up @@ -264,6 +265,28 @@ inline void IntrusiveList<T, Container, member>::prepend(T& n)
m_storage.m_last = &nnode;
}

template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline void IntrusiveList<T, Container, member>::insert_before(T& bn, T& n)
{
remove(n);

auto& new_node = n.*member;
auto& before_node = bn.*member;
new_node.m_storage = &m_storage;
new_node.m_next = &before_node;
new_node.m_prev = before_node.m_prev;
if (before_node.m_prev)
before_node.m_prev->m_next = &new_node;
before_node.m_prev = &new_node;

if (m_storage.m_first == &before_node) {
m_storage.m_first = &new_node;
}

if constexpr (!RemoveReference<decltype(new_node)>::IsRaw)
new_node.m_self.reference = &n;
}

template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline void IntrusiveList<T, Container, member>::remove(T& n)
{
Expand Down
26 changes: 26 additions & 0 deletions Tests/AK/TestIntrusiveList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,32 @@ TEST_CASE(insert)
delete list.take_last();
}

TEST_CASE(insert_before)
{
IntrusiveTestList list;
auto two = new IntrusiveTestItem();
list.append(*two);
auto zero = new IntrusiveTestItem();
list.append(*zero);
auto one = new IntrusiveTestItem();
list.insert_before(*zero, *one);

EXPECT_EQ(list.first(), two);
EXPECT_EQ(list.last(), zero);
EXPECT(list.contains(*zero));
EXPECT(list.contains(*one));
EXPECT(list.contains(*two));

EXPECT(zero->m_list_node.is_in_list());
EXPECT(one->m_list_node.is_in_list());
EXPECT(two->m_list_node.is_in_list());
EXPECT_EQ(list.size_slow(), 3u);

while (auto elem = list.take_first()) {
delete elem;
}
}

TEST_CASE(enumeration)
{
constexpr size_t expected_size = 10;
Expand Down

0 comments on commit b7f8343

Please sign in to comment.