Skip to content

Instantly share code, notes, and snippets.

@jokaye
Created May 9, 2019 07:38
Show Gist options
  • Select an option

  • Save jokaye/3ef2f64e343a27f023268895df2e8dea to your computer and use it in GitHub Desktop.

Select an option

Save jokaye/3ef2f64e343a27f023268895df2e8dea to your computer and use it in GitHub Desktop.
#singleflight
package main
import "sync"
type call struct {
wg sync.WaitGroup
val interface{}
err error
result []chan
dups int
}
type Group struct {
lock sync.Mutex
m map[string]*call
}
func (g *Group)Do (key string, fn func() (interface{}, error))(v interface{}, err error, shared bool){
g.lock.Lock()
if g.m == nil {
g.m = make(map[string]*call)
}
if c, ok := g.m[key];ok {
c.dups ++
g.lock.Unlock()
c.wg.Wait()
return c.val, c.err, true
}
c := new(call)
g.m[key] = c
c.wg.Add(1)
g.lock.Unlock()
g.doCall(c, key, fn)
return c.val, c.err, c.dups > 0
}
func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
c.val, c.err = fn()
c.wg.Done()
g.mu.Lock()
delete(g.m, key)
for _, ch := range c.chans {
ch <- Result{c.val, c.err, c.dups > 0}
}
g.mu.Unlock()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment