50 lines
741 B
Go
50 lines
741 B
Go
package missinggo
|
|
|
|
import "sync"
|
|
|
|
type ongoing struct {
|
|
do sync.Mutex
|
|
users int
|
|
}
|
|
|
|
type SingleFlight struct {
|
|
mu sync.Mutex
|
|
ongoing map[string]*ongoing
|
|
}
|
|
|
|
type Operation struct {
|
|
sf *SingleFlight
|
|
id string
|
|
}
|
|
|
|
func (op Operation) Unlock() {
|
|
op.sf.Unlock(op.id)
|
|
}
|
|
|
|
func (me *SingleFlight) Lock(id string) Operation {
|
|
me.mu.Lock()
|
|
on, ok := me.ongoing[id]
|
|
if !ok {
|
|
on = new(ongoing)
|
|
if me.ongoing == nil {
|
|
me.ongoing = make(map[string]*ongoing)
|
|
}
|
|
me.ongoing[id] = on
|
|
}
|
|
on.users++
|
|
me.mu.Unlock()
|
|
on.do.Lock()
|
|
return Operation{me, id}
|
|
}
|
|
|
|
func (me *SingleFlight) Unlock(id string) {
|
|
me.mu.Lock()
|
|
on := me.ongoing[id]
|
|
on.do.Unlock()
|
|
on.users--
|
|
if on.users == 0 {
|
|
delete(me.ongoing, id)
|
|
}
|
|
me.mu.Unlock()
|
|
}
|