Skip to content

Commit

Permalink
AK: Combine SinglyLinkedList and SinglyLinkedListWithCount
Browse files Browse the repository at this point in the history
Using policy based design `SinglyLinkedList` and
`SinglyLinkedListWithCount` can be combined into one class which takes
a policy to determine how to keep track of the size of the list. The
default policy is to use list iteration to count the items in the list
each time. The `WithCount` form is a different policy which tracks the
size, but comes with the overhead of storing the count and
incrementing/decrementing on each modification.

This model is extensible to have other forms of counting by
implementing only a new policy instead of implementing a totally new
type.
  • Loading branch information
ldm5180 authored and AtkinsSJ committed Jan 2, 2023
1 parent 0105600 commit e0ab776
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 156 deletions.
3 changes: 2 additions & 1 deletion AK/Forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma once

#include <AK/DefaultDelete.h>
#include <AK/SinglyLinkedListSizePolicy.h>
#include <AK/Types.h>

namespace AK {
Expand Down Expand Up @@ -64,7 +65,7 @@ using Bytes = Span<u8>;
template<typename T, AK::MemoryOrder DefaultMemoryOrder>
class Atomic;

template<typename T>
template<typename T, typename TSizeCalculationPolicy = DefaultSizeCalculationPolicy>
class SinglyLinkedList;

template<typename T>
Expand Down
18 changes: 11 additions & 7 deletions AK/SinglyLinkedList.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class SinglyLinkedListIterator {
bool m_removed { false };
};

template<typename T>
template<typename T, typename TSizeCalculationPolicy>
class SinglyLinkedList {
private:
struct Node {
Expand Down Expand Up @@ -96,12 +96,9 @@ class SinglyLinkedList {

bool is_empty() const { return !head(); }

inline size_t size_slow() const
inline size_t size() const
{
size_t size = 0;
for (auto* node = m_head; node; node = node->next)
++size;
return size;
return m_size_policy.size(m_head);
}

void clear()
Expand All @@ -113,6 +110,7 @@ class SinglyLinkedList {
}
m_head = nullptr;
m_tail = nullptr;
m_size_policy.reset();
}

T& first()
Expand Down Expand Up @@ -144,6 +142,7 @@ class SinglyLinkedList {
if (m_tail == m_head)
m_tail = nullptr;
m_head = m_head->next;
m_size_policy.decrease_size(value);
delete prev_head;
return value;
}
Expand All @@ -154,6 +153,7 @@ class SinglyLinkedList {
auto* node = new (nothrow) Node(forward<U>(value));
if (!node)
return Error::from_errno(ENOMEM);
m_size_policy.increase_size(value);
if (!m_head) {
m_head = node;
m_tail = node;
Expand All @@ -170,6 +170,7 @@ class SinglyLinkedList {
auto* node = new (nothrow) Node(forward<U>(value));
if (!node)
return Error::from_errno(ENOMEM);
m_size_policy.increase_size(value);
if (!m_head) {
m_head = node;
m_tail = node;
Expand Down Expand Up @@ -237,6 +238,7 @@ class SinglyLinkedList {
auto* node = new (nothrow) Node(forward<U>(value));
if (!node)
return Error::from_errno(ENOMEM);
m_size_policy.increase_size(value);
node->next = iterator.m_node;
if (m_head == iterator.m_node)
m_head = node;
Expand All @@ -254,6 +256,7 @@ class SinglyLinkedList {
auto* node = new (nothrow) Node(forward<U>(value));
if (!node)
return Error::from_errno(ENOMEM);
m_size_policy.increase_size(value);
node->next = iterator.m_node->next;

iterator.m_node->next = node;
Expand Down Expand Up @@ -286,6 +289,7 @@ class SinglyLinkedList {
m_tail = iterator.m_prev;
if (iterator.m_prev)
iterator.m_prev->next = iterator.m_node->next;
m_size_policy.decrease_size(iterator.m_node->value);
delete iterator.m_node;
}

Expand All @@ -298,8 +302,8 @@ class SinglyLinkedList {

Node* m_head { nullptr };
Node* m_tail { nullptr };
TSizeCalculationPolicy m_size_policy {};
};

}

#if USING_AK_GLOBALLY
Expand Down
47 changes: 47 additions & 0 deletions AK/SinglyLinkedListSizePolicy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <AK/Types.h>

namespace AK {

struct DefaultSizeCalculationPolicy {
constexpr void increase_size(auto const&) { }

constexpr void decrease_size(auto const&) { }

constexpr void reset() { }

constexpr size_t size(auto const* head) const
{
size_t size = 0;
for (auto* node = head; node; node = node->next)
++size;
return size;
}
};

struct CountingSizeCalculationPolicy {
constexpr void increase_size(auto const&) { ++m_size; }

constexpr void decrease_size(auto const&) { --m_size; }

constexpr void reset() { m_size = 0; }

constexpr size_t size(auto const*) const { return m_size; }

private:
size_t m_size { 0 };
};

}

#ifdef USING_AK_GLOBALLY
using AK::CountingSizeCalculationPolicy;
using AK::DefaultSizeCalculationPolicy;
#endif
144 changes: 0 additions & 144 deletions AK/SinglyLinkedListWithCount.h

This file was deleted.

4 changes: 2 additions & 2 deletions Kernel/Net/IPv4Socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#pragma once

#include <AK/HashMap.h>
#include <AK/SinglyLinkedListWithCount.h>
#include <AK/SinglyLinkedList.h>
#include <Kernel/DoubleBuffer.h>
#include <Kernel/KBuffer.h>
#include <Kernel/Locking/MutexProtected.h>
Expand Down Expand Up @@ -116,7 +116,7 @@ class IPv4Socket : public Socket {
OwnPtr<KBuffer> data;
};

SinglyLinkedListWithCount<ReceivedPacket> m_receive_queue;
SinglyLinkedList<ReceivedPacket, CountingSizeCalculationPolicy> m_receive_queue;

OwnPtr<DoubleBuffer> m_receive_buffer;

Expand Down
Loading

0 comments on commit e0ab776

Please sign in to comment.