status-go/vendor/github.com/libp2p/go-libp2p-pubsub/timecache/first_seen_cache.go

72 lines
1.2 KiB
Go

package timecache
import (
"container/list"
"sync"
"time"
)
// FirstSeenCache is a thread-safe copy of https://github.com/whyrusleeping/timecache.
type FirstSeenCache struct {
q *list.List
m map[string]time.Time
span time.Duration
guard *sync.RWMutex
}
func newFirstSeenCache(span time.Duration) TimeCache {
return &FirstSeenCache{
q: list.New(),
m: make(map[string]time.Time),
span: span,
guard: new(sync.RWMutex),
}
}
func (tc FirstSeenCache) Add(s string) {
tc.guard.Lock()
defer tc.guard.Unlock()
_, ok := tc.m[s]
if ok {
panic("putting the same entry twice not supported")
}
// TODO(#515): Do GC in the background
tc.sweep()
tc.m[s] = time.Now()
tc.q.PushFront(s)
}
func (tc FirstSeenCache) sweep() {
for {
back := tc.q.Back()
if back == nil {
return
}
v := back.Value.(string)
t, ok := tc.m[v]
if !ok {
panic("inconsistent cache state")
}
if time.Since(t) > tc.span {
tc.q.Remove(back)
delete(tc.m, v)
} else {
return
}
}
}
func (tc FirstSeenCache) Has(s string) bool {
tc.guard.RLock()
defer tc.guard.RUnlock()
ts, ok := tc.m[s]
// Only consider the entry found if it was present in the cache AND hadn't already expired.
return ok && time.Since(ts) <= tc.span
}