common/CountPerSecond.go (37 lines of code) (raw):
package common
import (
"sync/atomic"
"time"
)
func NewCountPerSecond() CountPerSecond {
cps := countPerSecond{}
cps.Reset()
return &cps
}
// CountPerSecond ...
type CountPerSecond interface {
// Add atomically adds delta to *addr and returns the new value.
// To subtract a signed positive constant value c, do Add(^uint64(c-1)).
Add(delta uint64) uint64 // Pass 0 to get the current count value
LatestRate() float64
Reset()
}
type countPerSecond struct {
start int64 // Unix time allowing atomic update: Seconds since 1/1/1970
count uint64
nocopy NoCopy
}
func (cps *countPerSecond) Add(delta uint64) uint64 {
cps.nocopy.Check()
return atomic.AddUint64(&cps.count, delta)
}
func (cps *countPerSecond) LatestRate() float64 {
cps.nocopy.Check()
dur := time.Since(time.Unix(cps.start, 0))
if dur <= 0 {
dur = 1
}
return float64(atomic.LoadUint64(&cps.count)) / dur.Seconds()
}
func (cps *countPerSecond) Reset() {
cps.nocopy.Check()
atomic.StoreInt64(&cps.start, time.Now().Unix())
atomic.StoreUint64(&cps.count, 0)
}