From 2ff0cd88227bfeec9da4f8701ff6433716638929 Mon Sep 17 00:00:00 2001 From: Andrew Gillis Date: Wed, 15 May 2019 00:17:53 -0400 Subject: [PATCH 1/2] New func to specify minimum capacity A larger minimum capacity can be specified to avoid buffer resizing in cases where the size frequently grows and shrinks across a wide range. Add module support --- .travis.yml | 2 +- deque.go | 27 +++++++++++++++++++++------ deque_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + 4 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 go.mod diff --git a/.travis.yml b/.travis.yml index 9608f4c..bef0db7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: go go: - - "1.8" - "1.9" - "1.10" - "1.11" + - "1.12" - "tip" before_script: diff --git a/deque.go b/deque.go index d9d9863..8e31fbd 100644 --- a/deque.go +++ b/deque.go @@ -6,10 +6,22 @@ const minCapacity = 16 // Deque represents a single instance of the deque data structure. type Deque struct { - buf []interface{} - head int - tail int - count int + buf []interface{} + head int + tail int + count int + minCap int +} + +// New creates a new Deque that has a minimum capacity of 2^minCapacityExp. If +// the value of the minimum capacity is less than or equal to the minimum +// allowed, then New returns the same as new(Deque). +func New(minCapacityExp uint) *Deque { + q := new(Deque) + if 1< minCapacity { + q.minCap = 1 << minCapacityExp + } + return q } // Len returns the number of elements currently stored in the queue. @@ -191,7 +203,10 @@ func (q *Deque) next(i int) int { // growIfFull resizes up if the buffer is full. func (q *Deque) growIfFull() { if len(q.buf) == 0 { - q.buf = make([]interface{}, minCapacity) + if q.minCap == 0 { + q.minCap = minCapacity + } + q.buf = make([]interface{}, q.minCap) return } if q.count == len(q.buf) { @@ -201,7 +216,7 @@ func (q *Deque) growIfFull() { // shrinkIfExcess resize down if the buffer 1/4 full. func (q *Deque) shrinkIfExcess() { - if len(q.buf) > minCapacity && (q.count<<2) == len(q.buf) { + if len(q.buf) > q.minCap && (q.count<<2) == len(q.buf) { q.resize() } } diff --git a/deque_test.go b/deque_test.go index da96a7c..9861497 100644 --- a/deque_test.go +++ b/deque_test.go @@ -480,6 +480,25 @@ func TestRemoveOutOfRangePanics(t *testing.T) { }) } +func TestNew(t *testing.T) { + exp := uint(8) + q := New(8) + q.PushBack("A") + if q.minCap != 1< Date: Wed, 15 May 2019 04:19:52 -0400 Subject: [PATCH 2/2] set minimum capacity at anytime --- deque.go | 26 +++++++++++++++----------- deque_test.go | 12 +++++++++--- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/deque.go b/deque.go index 8e31fbd..bca4ea1 100644 --- a/deque.go +++ b/deque.go @@ -13,17 +13,6 @@ type Deque struct { minCap int } -// New creates a new Deque that has a minimum capacity of 2^minCapacityExp. If -// the value of the minimum capacity is less than or equal to the minimum -// allowed, then New returns the same as new(Deque). -func New(minCapacityExp uint) *Deque { - q := new(Deque) - if 1< minCapacity { - q.minCap = 1 << minCapacityExp - } - return q -} - // Len returns the number of elements currently stored in the queue. func (q *Deque) Len() int { return q.count @@ -190,6 +179,21 @@ func (q *Deque) Rotate(n int) { } } +// SetMinCapacity sets a minimum capacity of 2^minCapacityExp. If the value of +// the minimum capacity is less than or equal to the minimum allowed, then +// capacity is set to the minimum allowed. This may be called at anytime to +// set a new minimum capacity. +// +// Setting a larger minimum capacity may be used to prevent resizing when the +// number of stored items changes frequently across a wide range. +func (q *Deque) SetMinCapacity(minCapacityExp uint) { + if 1< minCapacity { + q.minCap = 1 << minCapacityExp + } else { + q.minCap = minCapacity + } +} + // prev returns the previous buffer position wrapping around buffer. func (q *Deque) prev(i int) int { return (i - 1) & (len(q.buf) - 1) // bitwise modulus diff --git a/deque_test.go b/deque_test.go index 9861497..f26b0d3 100644 --- a/deque_test.go +++ b/deque_test.go @@ -480,9 +480,10 @@ func TestRemoveOutOfRangePanics(t *testing.T) { }) } -func TestNew(t *testing.T) { +func TestSetMinCapacity(t *testing.T) { + var q Deque exp := uint(8) - q := New(8) + q.SetMinCapacity(exp) q.PushBack("A") if q.minCap != 1<