Commit efd601d7 authored by xujianhai666's avatar xujianhai666

add full error

parent 6d88c0f0
...@@ -29,19 +29,21 @@ const ( ...@@ -29,19 +29,21 @@ const (
) )
var ( var (
ErrEmpty = errors.New("") ErrEmpty = errors.New("quue is empty")
ErrFull = errors.New("queue is full")
) )
// Queue represents a single instance of the queue data structure. // Queue represents a single instance of the queue data structure.
type Queue struct { type Queue struct {
buf []interface{} buf []interface{}
head, tail, count int head, tail, count, cap int
lock sync.Mutex lock sync.Mutex
} }
// New constructs and returns a new Queue. // New constructs and returns a new Queue.
func NewQueue() *Queue { func NewQueue(cap int) *Queue {
return &Queue{ return &Queue{
cap: cap,
buf: make([]interface{}, defaultQueueLen), buf: make([]interface{}, defaultQueueLen),
} }
} }
...@@ -56,7 +58,11 @@ func (q *Queue) Length() int { ...@@ -56,7 +58,11 @@ func (q *Queue) Length() int {
// resizes the queue to fit exactly twice its current contents // resizes the queue to fit exactly twice its current contents
// this can result in shrinking if the queue is less than half-full // this can result in shrinking if the queue is less than half-full
func (q *Queue) resize() { func (q *Queue) resize() {
newBuf := make([]interface{}, q.count<<1) newSize := q.count << 1
if newSize > q.cap {
newSize = q.cap
}
newBuf := make([]interface{}, newSize)
if q.tail > q.head { if q.tail > q.head {
copy(newBuf, q.buf[q.head:q.tail]) copy(newBuf, q.buf[q.head:q.tail])
...@@ -71,9 +77,13 @@ func (q *Queue) resize() { ...@@ -71,9 +77,13 @@ func (q *Queue) resize() {
} }
// Add puts an element on the end of the queue. // Add puts an element on the end of the queue.
func (q *Queue) Add(elem interface{}) { func (q *Queue) Add(elem interface{}) error {
q.lock.Lock() q.lock.Lock()
defer q.lock.Unlock() defer q.lock.Unlock()
if q.count >= q.cap {
return ErrFull
}
if q.count == len(q.buf) { if q.count == len(q.buf) {
q.resize() q.resize()
} }
...@@ -81,6 +91,7 @@ func (q *Queue) Add(elem interface{}) { ...@@ -81,6 +91,7 @@ func (q *Queue) Add(elem interface{}) {
q.buf[q.tail] = elem q.buf[q.tail] = elem
q.tail = (q.tail + 1) & (len(q.buf) - 1) q.tail = (q.tail + 1) & (len(q.buf) - 1)
q.count++ q.count++
return nil
} }
// Peek returns the element at the head of the queue. return ErrEmpty // Peek returns the element at the head of the queue. return ErrEmpty
......
...@@ -26,7 +26,7 @@ import ( ...@@ -26,7 +26,7 @@ import (
) )
func TestQueueSimple(t *testing.T) { func TestQueueSimple(t *testing.T) {
q := NewQueue() q := NewQueue(defaultQueueLen)
for i := 0; i < defaultQueueLen; i++ { for i := 0; i < defaultQueueLen; i++ {
q.Add(i) q.Add(i)
...@@ -40,7 +40,7 @@ func TestQueueSimple(t *testing.T) { ...@@ -40,7 +40,7 @@ func TestQueueSimple(t *testing.T) {
} }
func TestQueueWrapping(t *testing.T) { func TestQueueWrapping(t *testing.T) {
q := NewQueue() q := NewQueue(defaultQueueLen)
for i := 0; i < defaultQueueLen; i++ { for i := 0; i < defaultQueueLen; i++ {
q.Add(i) q.Add(i)
...@@ -57,8 +57,18 @@ func TestQueueWrapping(t *testing.T) { ...@@ -57,8 +57,18 @@ func TestQueueWrapping(t *testing.T) {
} }
} }
func TestQueueFull(t *testing.T) {
q := NewQueue(defaultQueueLen)
for i := 0; i < defaultQueueLen; i++ {
err := q.Add(i)
assert.Nil(t, err)
}
err := q.Add(defaultQueueLen)
assert.Equal(t, ErrFull, err)
}
func TestQueueLength(t *testing.T) { func TestQueueLength(t *testing.T) {
q := NewQueue() q := NewQueue(1000)
assert.Equal(t, 0, q.Length(), "empty queue length should be 0") assert.Equal(t, 0, q.Length(), "empty queue length should be 0")
...@@ -72,8 +82,8 @@ func TestQueueLength(t *testing.T) { ...@@ -72,8 +82,8 @@ func TestQueueLength(t *testing.T) {
} }
} }
func TestQueuePeekOutOfRangePanics(t *testing.T) { func TestQueuePeekOutOfRangeErr(t *testing.T) {
q := NewQueue() q := NewQueue(defaultQueueLen)
_, err := q.Peek() _, err := q.Peek()
assert.Equal(t, ErrEmpty, err) assert.Equal(t, ErrEmpty, err)
...@@ -86,8 +96,8 @@ func TestQueuePeekOutOfRangePanics(t *testing.T) { ...@@ -86,8 +96,8 @@ func TestQueuePeekOutOfRangePanics(t *testing.T) {
assert.Equal(t, ErrEmpty, err) assert.Equal(t, ErrEmpty, err)
} }
func TestQueueRemoveOutOfRangePanics(t *testing.T) { func TestQueueRemoveOutOfRangeErr(t *testing.T) {
q := NewQueue() q := NewQueue(defaultQueueLen)
_, err := q.Remove() _, err := q.Remove()
assert.Equal(t, ErrEmpty, err) assert.Equal(t, ErrEmpty, err)
...@@ -106,7 +116,7 @@ func TestQueueRemoveOutOfRangePanics(t *testing.T) { ...@@ -106,7 +116,7 @@ func TestQueueRemoveOutOfRangePanics(t *testing.T) {
// enough, but if you have less than that available and start swapping, then all bets are off. // enough, but if you have less than that available and start swapping, then all bets are off.
func BenchmarkQueueSerial(b *testing.B) { func BenchmarkQueueSerial(b *testing.B) {
q := NewQueue() q := NewQueue(defaultQueueLen)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
q.Add(nil) q.Add(nil)
} }
...@@ -117,7 +127,7 @@ func BenchmarkQueueSerial(b *testing.B) { ...@@ -117,7 +127,7 @@ func BenchmarkQueueSerial(b *testing.B) {
} }
func BenchmarkQueueTickTock(b *testing.B) { func BenchmarkQueueTickTock(b *testing.B) {
q := NewQueue() q := NewQueue(defaultQueueLen)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
q.Add(nil) q.Add(nil)
q.Peek() q.Peek()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment