singleflight.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package singleflight provides a duplicate function call suppression
  5. // mechanism.
  6. package singleflight // import "golang.org/x/sync/singleflight"
  7. import "sync"
  8. // call is an in-flight or completed singleflight.Do call
  9. type call struct {
  10. wg sync.WaitGroup
  11. // These fields are written once before the WaitGroup is done
  12. // and are only read after the WaitGroup is done.
  13. val interface{}
  14. err error
  15. // forgotten indicates whether Forget was called with this call's key
  16. // while the call was still in flight.
  17. forgotten bool
  18. // These fields are read and written with the singleflight
  19. // mutex held before the WaitGroup is done, and are read but
  20. // not written after the WaitGroup is done.
  21. dups int
  22. chans []chan<- Result
  23. }
  24. // Group represents a class of work and forms a namespace in
  25. // which units of work can be executed with duplicate suppression.
  26. type Group struct {
  27. mu sync.Mutex // protects m
  28. m map[string]*call // lazily initialized
  29. }
  30. // Result holds the results of Do, so they can be passed
  31. // on a channel.
  32. type Result struct {
  33. Val interface{}
  34. Err error
  35. Shared bool
  36. }
  37. // Do executes and returns the results of the given function, making
  38. // sure that only one execution is in-flight for a given key at a
  39. // time. If a duplicate comes in, the duplicate caller waits for the
  40. // original to complete and receives the same results.
  41. // The return value shared indicates whether v was given to multiple callers.
  42. func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
  43. g.mu.Lock()
  44. if g.m == nil {
  45. g.m = make(map[string]*call)
  46. }
  47. if c, ok := g.m[key]; ok {
  48. c.dups++
  49. g.mu.Unlock()
  50. c.wg.Wait()
  51. return c.val, c.err, true
  52. }
  53. c := new(call)
  54. c.wg.Add(1)
  55. g.m[key] = c
  56. g.mu.Unlock()
  57. g.doCall(c, key, fn)
  58. return c.val, c.err, c.dups > 0
  59. }
  60. // DoChan is like Do but returns a channel that will receive the
  61. // results when they are ready.
  62. func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result {
  63. ch := make(chan Result, 1)
  64. g.mu.Lock()
  65. if g.m == nil {
  66. g.m = make(map[string]*call)
  67. }
  68. if c, ok := g.m[key]; ok {
  69. c.dups++
  70. c.chans = append(c.chans, ch)
  71. g.mu.Unlock()
  72. return ch
  73. }
  74. c := &call{chans: []chan<- Result{ch}}
  75. c.wg.Add(1)
  76. g.m[key] = c
  77. g.mu.Unlock()
  78. go g.doCall(c, key, fn)
  79. return ch
  80. }
  81. // doCall handles the single call for a key.
  82. func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
  83. c.val, c.err = fn()
  84. c.wg.Done()
  85. g.mu.Lock()
  86. if !c.forgotten {
  87. delete(g.m, key)
  88. }
  89. for _, ch := range c.chans {
  90. ch <- Result{c.val, c.err, c.dups > 0}
  91. }
  92. g.mu.Unlock()
  93. }
  94. // Forget tells the singleflight to forget about a key. Future calls
  95. // to Do for this key will call the function rather than waiting for
  96. // an earlier call to complete.
  97. func (g *Group) Forget(key string) {
  98. g.mu.Lock()
  99. if c, ok := g.m[key]; ok {
  100. c.forgotten = true
  101. }
  102. delete(g.m, key)
  103. g.mu.Unlock()
  104. }