From 3ff0a3aa4b616fc448ffa7ed0b093879fe04d3ee Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 22 May 2021 16:17:32 +0200 Subject: [PATCH] AK: Avoid allocations for the Queue class Previously the Queue class used a SinglyLinkedList to manage its queue segments. This changes the Queue class to use the IntrusiveList class instead which saves us one allocation per segment. --- AK/Queue.h | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/AK/Queue.h b/AK/Queue.h index 5bfa454dd03..d52026f107f 100644 --- a/AK/Queue.h +++ b/AK/Queue.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -16,7 +17,11 @@ template class Queue { public: Queue() = default; - ~Queue() = default; + + ~Queue() + { + clear(); + } size_t size() const { return m_size; } bool is_empty() const { return m_size == 0; } @@ -24,18 +29,20 @@ public: template void enqueue(U&& value) { - if (m_segments.is_empty() || m_segments.last()->size() >= segment_size) - m_segments.append(make>()); - m_segments.last()->append(forward(value)); + if (m_segments.is_empty() || m_segments.last()->data.size() >= segment_size) { + auto segment = new QueueSegment; + m_segments.append(*segment); + } + m_segments.last()->data.append(forward(value)); ++m_size; } T dequeue() { VERIFY(!is_empty()); - auto value = move((*m_segments.first())[m_index_into_first++]); + auto value = move(m_segments.first()->data[m_index_into_first++]); if (m_index_into_first == segment_size) { - m_segments.take_first(); + delete m_segments.take_first(); m_index_into_first = 0; } --m_size; @@ -45,18 +52,24 @@ public: const T& head() const { VERIFY(!is_empty()); - return (*m_segments.first())[m_index_into_first]; + return m_segments.first()->data[m_index_into_first]; } void clear() { - m_segments.clear(); + while (auto* segment = m_segments.take_first()) + delete segment; m_index_into_first = 0; m_size = 0; } private: - SinglyLinkedList>> m_segments; + struct QueueSegment { + Vector data; + IntrusiveListNode node; + }; + + IntrusiveList, &QueueSegment::node> m_segments; size_t m_index_into_first { 0 }; size_t m_size { 0 }; };