open-nomad/client/stats/ring.go

68 lines
1.4 KiB
Go
Raw Normal View History

2016-05-09 13:35:53 +00:00
package stats
import (
"fmt"
2016-05-20 09:10:50 +00:00
"sync"
2016-05-09 13:35:53 +00:00
)
var (
2016-05-09 16:53:00 +00:00
// The default size of the ring buffer
2016-05-09 13:35:53 +00:00
defaultCap = 60
)
2016-05-09 16:53:00 +00:00
// RingBuff is a data structure which is a circular list based on slices
2016-05-09 13:35:53 +00:00
type RingBuff struct {
head int
buff []interface{}
2016-05-20 09:10:50 +00:00
lock sync.RWMutex
2016-05-09 13:35:53 +00:00
}
2016-05-09 16:53:00 +00:00
// NewRingBuff creates a new ring buffer of the specified size
2016-05-09 13:35:53 +00:00
func NewRingBuff(capacity int) (*RingBuff, error) {
if capacity < 1 {
return nil, fmt.Errorf("can not create a ring buffer with capacity: %v", capacity)
}
return &RingBuff{buff: make([]interface{}, 0, capacity), head: -1}, nil
2016-05-09 13:35:53 +00:00
}
2016-05-09 16:53:00 +00:00
// Enqueue queues a new value in the ring buffer. This operation would
// over-write an older value if the list has reached it's capacity
2016-05-09 13:35:53 +00:00
func (r *RingBuff) Enqueue(value interface{}) {
2016-05-20 09:10:50 +00:00
r.lock.Lock()
defer r.lock.Unlock()
if len(r.buff) < cap(r.buff) {
r.buff = append(r.buff, struct{}{})
}
2016-05-09 13:35:53 +00:00
r.head += 1
if r.head == cap(r.buff) {
2016-05-09 13:35:53 +00:00
r.head = 0
}
r.buff[r.head] = value
}
2016-05-09 16:53:00 +00:00
// Peek returns the last value enqueued in the ring buffer
2016-05-09 13:35:53 +00:00
func (r *RingBuff) Peek() interface{} {
2016-05-20 09:10:50 +00:00
r.lock.RLock()
defer r.lock.RUnlock()
if r.head == -1 {
return nil
}
2016-05-09 13:35:53 +00:00
return r.buff[r.head]
}
2016-05-09 16:53:00 +00:00
// Values returns all the values in the buffer.
2016-05-09 13:35:53 +00:00
func (r *RingBuff) Values() []interface{} {
2016-05-20 09:10:50 +00:00
r.lock.RLock()
defer r.lock.RUnlock()
2016-05-09 13:35:53 +00:00
if r.head == len(r.buff)-1 {
vals := make([]interface{}, len(r.buff))
copy(vals, r.buff)
return vals
}
slice1 := r.buff[r.head+1:]
slice2 := r.buff[:r.head+1]
return append(slice1, slice2...)
}