Browse Source

Updated copyright and commentary, now uses copy() builtin.

Peter H. Froehlich 8 years ago
parent
commit
5652cbe391
1 changed files with 16 additions and 12 deletions
  1. 16 12
      queue/queue.go

+ 16 - 12
queue/queue.go

@@ -1,4 +1,4 @@
-// Copyright (c) 2013, Peter H. Froehlich. All rights reserved.
+// Copyright (c) 2013-2017, Peter H. Froehlich. All rights reserved.
 // Use of this source code is governed by a BSD-style license
 // that can be found in the LICENSE file.
 
@@ -6,9 +6,9 @@
 // top of a slice/array. All operations are constant time except
 // for PushFront and PushBack which are amortized constant time.
 //
-// We are about 60%-90% faster than container/list would be at
-// the price of potentially wasting some memory because we grow
-// our slice by amortized doubling.
+// We are about 15%-45% faster than container/list at the price
+// of potentially wasting some memory because we grow by doubling.
+// We seem to even beat Go's channels by a small margin.
 package queue
 
 import "fmt"
@@ -55,7 +55,7 @@ func (q *Queue) Init() *Queue {
 // Personally I think it's a little wasteful because every single
 // PushFront/PushBack is going to pay the overhead of calling this.
 // But that's the price for making zero values useful immediately,
-// something Go apparently likes a lot.
+// something Go folks apparently like a lot.
 func (q *Queue) lazyInit() {
 	if q.rep == nil {
 		q.Init()
@@ -79,13 +79,17 @@ func (q *Queue) full() bool {
 
 // grow doubles the size of queue q's underlying slice/array.
 func (q *Queue) grow() {
-	big := make([]interface{}, q.length*2)
-	j := q.front
-	for i := 0; i < q.length; i++ {
-		big[i] = q.rep[j]
-		j = q.inc(j)
-	}
-	q.rep = big
+	bigger := make([]interface{}, q.length*2)
+	// Kudos to Rodrigo Moraes, see https://gist.github.com/moraes/2141121
+	copy(bigger, q.rep[q.front:])
+	copy(bigger[q.length-q.front:], q.rep[:q.front])
+	// The above replaced the "obvious" for loop and is a bit tricky.
+	// First note that q.front == q.back if we're full; if that wasn't
+	// true, things would be more complicated. Second recall that for
+	// a slice [lo:hi] the lo bound is inclusive whereas the hi bound
+	// is exclusive. If that doesn't convince you that the above works
+	// maybe drawing out some pictures for a concrete example will?
+	q.rep = bigger
 	q.front = 0
 	q.back = q.length
 }