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