293dd2e848
* Add vendor dir so builds dont require dep * Pin specific version go-eth version
99 lines
2.7 KiB
Go
Executable File
99 lines
2.7 KiB
Go
Executable File
// CookieJar - A contestant's algorithm toolbox
|
|
// Copyright (c) 2013 Peter Szilagyi. All rights reserved.
|
|
//
|
|
// CookieJar is dual licensed: use of this source code is governed by a BSD
|
|
// license that can be found in the LICENSE file. Alternatively, the CookieJar
|
|
// toolbox may be used in accordance with the terms and conditions contained
|
|
// in a signed written agreement between you and the author(s).
|
|
|
|
// Package queue implements a FIFO (first in first out) data structure supporting
|
|
// arbitrary types (even a mixture).
|
|
//
|
|
// Internally it uses a dynamically growing circular slice of blocks, resulting
|
|
// in faster resizes than a simple dynamic array/slice would allow.
|
|
package queue
|
|
|
|
// The size of a block of data
|
|
const blockSize = 4096
|
|
|
|
// First in, first out data structure.
|
|
type Queue struct {
|
|
tailIdx int
|
|
headIdx int
|
|
tailOff int
|
|
headOff int
|
|
|
|
blocks [][]interface{}
|
|
head []interface{}
|
|
tail []interface{}
|
|
}
|
|
|
|
// Creates a new, empty queue.
|
|
func New() *Queue {
|
|
result := new(Queue)
|
|
result.blocks = [][]interface{}{make([]interface{}, blockSize)}
|
|
result.head = result.blocks[0]
|
|
result.tail = result.blocks[0]
|
|
return result
|
|
}
|
|
|
|
// Pushes a new element into the queue, expanding it if necessary.
|
|
func (q *Queue) Push(data interface{}) {
|
|
q.tail[q.tailOff] = data
|
|
q.tailOff++
|
|
if q.tailOff == blockSize {
|
|
q.tailOff = 0
|
|
q.tailIdx = (q.tailIdx + 1) % len(q.blocks)
|
|
|
|
// If we wrapped over to the end, insert a new block and update indices
|
|
if q.tailIdx == q.headIdx {
|
|
buffer := make([][]interface{}, len(q.blocks)+1)
|
|
copy(buffer[:q.tailIdx], q.blocks[:q.tailIdx])
|
|
buffer[q.tailIdx] = make([]interface{}, blockSize)
|
|
copy(buffer[q.tailIdx+1:], q.blocks[q.tailIdx:])
|
|
q.blocks = buffer
|
|
q.headIdx++
|
|
q.head = q.blocks[q.headIdx]
|
|
}
|
|
q.tail = q.blocks[q.tailIdx]
|
|
}
|
|
}
|
|
|
|
// Pops out an element from the queue. Note, no bounds checking are done.
|
|
func (q *Queue) Pop() (res interface{}) {
|
|
res, q.head[q.headOff] = q.head[q.headOff], nil
|
|
q.headOff++
|
|
if q.headOff == blockSize {
|
|
q.headOff = 0
|
|
q.headIdx = (q.headIdx + 1) % len(q.blocks)
|
|
q.head = q.blocks[q.headIdx]
|
|
}
|
|
return
|
|
}
|
|
|
|
// Returns the first element in the queue. Note, no bounds checking are done.
|
|
func (q *Queue) Front() interface{} {
|
|
return q.head[q.headOff]
|
|
}
|
|
|
|
// Checks whether the queue is empty.
|
|
func (q *Queue) Empty() bool {
|
|
return q.headIdx == q.tailIdx && q.headOff == q.tailOff
|
|
}
|
|
|
|
// Returns the number of elements in the queue.
|
|
func (q *Queue) Size() int {
|
|
if q.tailIdx > q.headIdx {
|
|
return (q.tailIdx-q.headIdx)*blockSize - q.headOff + q.tailOff
|
|
} else if q.tailIdx < q.headIdx {
|
|
return (len(q.blocks)-q.headIdx+q.tailIdx)*blockSize - q.headOff + q.tailOff
|
|
} else {
|
|
return q.tailOff - q.headOff
|
|
}
|
|
}
|
|
|
|
// Clears out the contents of the queue.
|
|
func (q *Queue) Reset() {
|
|
*q = *New()
|
|
}
|