singleflight.go 793 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package missinggo
  2. import "sync"
  3. type ongoing struct {
  4. // Waiters can proceed, someone finished the task.
  5. do sync.Mutex
  6. users int
  7. }
  8. type SingleFlight struct {
  9. mu sync.Mutex
  10. ongoing map[string]*ongoing
  11. }
  12. type Operation struct {
  13. sf *SingleFlight
  14. id string
  15. }
  16. func (op Operation) Unlock() {
  17. op.sf.Unlock(op.id)
  18. }
  19. func (me *SingleFlight) Lock(id string) Operation {
  20. me.mu.Lock()
  21. on, ok := me.ongoing[id]
  22. if !ok {
  23. on = new(ongoing)
  24. if me.ongoing == nil {
  25. me.ongoing = make(map[string]*ongoing)
  26. }
  27. me.ongoing[id] = on
  28. }
  29. on.users++
  30. me.mu.Unlock()
  31. on.do.Lock()
  32. return Operation{me, id}
  33. }
  34. func (me *SingleFlight) Unlock(id string) {
  35. me.mu.Lock()
  36. on := me.ongoing[id]
  37. on.do.Unlock()
  38. on.users--
  39. if on.users == 0 {
  40. delete(me.ongoing, id)
  41. }
  42. me.mu.Unlock()
  43. }