diff --git a/memo/memo.go b/memo/memo.go new file mode 100644 index 0000000..8592b17 --- /dev/null +++ b/memo/memo.go @@ -0,0 +1,56 @@ +package memo + +import ( + "sync" +) + +type ( + Memo struct { + f Func + mu sync.Mutex //guards cache + cache *entry + } + + 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) *Memo { + return &Memo{ + f: f, + } +} + +func (memo *Memo) Invalidate() { + memo.mu.Lock() + memo.cache = nil + memo.mu.Unlock() +} + +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 +}