From 063d9754d745f0a171c0577b7d0dedc8dd836eb4 Mon Sep 17 00:00:00 2001 From: Ferdinand Majerech Date: Mon, 4 Aug 2014 02:16:34 +0200 Subject: [PATCH] Queue now uses a freelist to minimize allocations. --- source/dyaml/queue.d | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/source/dyaml/queue.d b/source/dyaml/queue.d index 1cd4a25..8b2fd1b 100644 --- a/source/dyaml/queue.d +++ b/source/dyaml/queue.d @@ -45,6 +45,10 @@ struct Queue(T) Node* last_ = null; /// Cursor pointing to the current node in iteration. Node* cursor_ = null; + + /// The first element of a linked list of freed Nodes available for recycling. + Node* freeList_ = null; + /// Length of the queue. size_t length_ = 0; @@ -54,9 +58,15 @@ struct Queue(T) @disable int opCmp(ref Queue); /// Destroy the queue, deallocating all its elements. - @safe nothrow ~this() + @trusted nothrow ~this() { while(!empty) { pop(); } + while(freeList_ !is null) + { + auto toFree = freeList_; + freeList_ = toFree.next_; + free(toFree); + } cursor_ = last_ = first_ = null; length_ = 0; } @@ -90,9 +100,19 @@ struct Queue(T) /// Push new item to the queue. void push(T item) @trusted nothrow { - Node* newLast = allocate!Node(item, cast(Node*)null); + Node* newLast; + if(freeList_ !is null) + { + newLast = freeList_; + freeList_ = freeList_.next_; + *newLast = Node(item, null); + } + else + { + newLast = allocate!Node(item, cast(Node*)null); + } if(last_ !is null) { last_.next_ = newLast; } - if(first_ is null) { first_ = newLast; } + if(first_ is null) { first_ = newLast; } last_ = newLast; ++length_; } @@ -139,10 +159,13 @@ struct Queue(T) } body { - T result = peek(); - Node* temp = first_; - first_ = first_.next_; - free(temp); + T result = peek(); + Node* popped = first_; + first_ = first_.next_; + + Node* oldFree = freeList_; + freeList_ = popped; + freeList_.next_ = oldFree; if(--length_ == 0) { assert(first_ is null);