mirror of
https://github.com/writeas/web-core
synced 2018-07-20 11:55:21 +00:00
70 lines
1.2 KiB
Go
70 lines
1.2 KiB
Go
package memo
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type (
|
|
Memo struct {
|
|
f Func
|
|
mu sync.Mutex //guards cache
|
|
cache *entry
|
|
|
|
cacheDur time.Duration
|
|
lastCache time.Time
|
|
}
|
|
|
|
Func func() (interface{}, error)
|
|
)
|
|
|
|
type (
|
|
entry struct {
|
|
res result
|
|
ready chan struct{} // close when res is read
|
|
}
|
|
|
|
result struct {
|
|
value interface{}
|
|
err error
|
|
}
|
|
)
|
|
|
|
func New(f Func, cd time.Duration) *Memo {
|
|
return &Memo{
|
|
f: f,
|
|
cacheDur: cd,
|
|
}
|
|
}
|
|
|
|
// Invalidate resets the cache to nil if the memo's given cache duration has
|
|
// elapsed, and returns true if the cache was actually invalidated.
|
|
func (memo *Memo) Invalidate() bool {
|
|
defer memo.mu.Unlock()
|
|
memo.mu.Lock()
|
|
|
|
if memo.cache != nil && time.Now().Sub(memo.lastCache) > memo.cacheDur {
|
|
memo.cache = nil
|
|
memo.lastCache = time.Now()
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (memo *Memo) Get() (value interface{}, err error) {
|
|
memo.mu.Lock()
|
|
if memo.cache == nil {
|
|
memo.cache = &entry{ready: make(chan struct{})}
|
|
memo.mu.Unlock()
|
|
|
|
memo.cache.res.value, memo.cache.res.err = memo.f()
|
|
|
|
close(memo.cache.ready)
|
|
} else {
|
|
memo.mu.Unlock()
|
|
|
|
<-memo.cache.ready
|
|
}
|
|
return memo.cache.res.value, memo.cache.res.err
|
|
}
|