44 lines
721 B
Go

package localcache
import "sync"
type call[K comparable, V any] struct {
wg sync.WaitGroup
val V
err error
}
type SingleFlight[K comparable, V any] struct {
mu sync.Mutex
m map[K]*call[K, V]
}
func NewSingleFlight[K comparable, V any]() *SingleFlight[K, V] {
return &SingleFlight[K, V]{m: make(map[K]*call[K, V])}
}
func (r *SingleFlight[K, V]) Do(key K, fn func() (V, error)) (V, error) {
r.mu.Lock()
if r.m == nil {
r.m = make(map[K]*call[K, V])
}
if c, ok := r.m[key]; ok {
r.mu.Unlock()
c.wg.Wait()
return c.val, c.err
}
c := new(call[K, V])
c.wg.Add(1)
r.m[key] = c
r.mu.Unlock()
c.val, c.err = fn()
c.wg.Done()
r.mu.Lock()
delete(r.m, key)
r.mu.Unlock()
return c.val, c.err
}