mirror of https://github.com/poanetwork/gecko.git
75 lines
1.5 KiB
Go
75 lines
1.5 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package timer
|
|
|
|
import (
|
|
"container/list"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// TimedMeter is a meter that discards old events
|
|
type TimedMeter struct {
|
|
lock sync.Mutex
|
|
// Amount of time to keep a tick
|
|
Duration time.Duration
|
|
// TODO: Currently this list has an entry for each tick... This isn't really
|
|
// sustainable at high tick numbers. We should be batching ticks with
|
|
// similar times into the same bucket.
|
|
tickList *list.List
|
|
}
|
|
|
|
// Tick implements the Meter interface
|
|
func (tm *TimedMeter) Tick() {
|
|
tm.lock.Lock()
|
|
defer tm.lock.Unlock()
|
|
|
|
tm.tick()
|
|
}
|
|
|
|
// Ticks implements the Meter interface
|
|
func (tm *TimedMeter) Ticks() int {
|
|
tm.lock.Lock()
|
|
defer tm.lock.Unlock()
|
|
|
|
return tm.ticks()
|
|
}
|
|
|
|
func (tm *TimedMeter) init() {
|
|
if tm.tickList == nil {
|
|
tm.tickList = list.New()
|
|
}
|
|
}
|
|
|
|
func (tm *TimedMeter) tick() {
|
|
tm.init()
|
|
tm.tickList.PushBack(time.Now())
|
|
}
|
|
|
|
func (tm *TimedMeter) ticks() int {
|
|
tm.init()
|
|
|
|
timeBound := time.Now().Add(-tm.Duration)
|
|
// removeExpiredHead returns false once there is nothing left to remove
|
|
for tm.removeExpiredHead(timeBound) {
|
|
}
|
|
return tm.tickList.Len()
|
|
}
|
|
|
|
// Returns true if the head was removed, false otherwise
|
|
func (tm *TimedMeter) removeExpiredHead(t time.Time) bool {
|
|
if tm.tickList.Len() == 0 {
|
|
return false
|
|
}
|
|
|
|
head := tm.tickList.Front()
|
|
headTime := head.Value.(time.Time)
|
|
|
|
if headTime.Before(t) {
|
|
tm.tickList.Remove(head)
|
|
return true
|
|
}
|
|
return false
|
|
}
|