Do executes and returns the results of the given function, making sure that only one execution is in-flight for a given key at a time. If a duplicate comes in, the duplicate caller waits for the original to complete and receives the same results. The return value shared indicates whether v was given
(key K, fn func() (V, error))
| 92 | // |
| 93 | //nolint:revive |
| 94 | func (g *Group[K, V]) Do(key K, fn func() (V, error)) (v V, err error, shared bool) { |
| 95 | g.mu.Lock() |
| 96 | if g.m == nil { |
| 97 | g.m = make(map[K]*call[V]) |
| 98 | } |
| 99 | if c, ok := g.m[key]; ok { |
| 100 | c.dups++ |
| 101 | g.mu.Unlock() |
| 102 | c.wg.Wait() |
| 103 | |
| 104 | if e, ok := c.err.(*panicError); ok { |
| 105 | panic(e) |
| 106 | } else if c.err == errGoexit { |
| 107 | runtime.Goexit() |
| 108 | } |
| 109 | return c.val, c.err, true |
| 110 | } |
| 111 | c := new(call[V]) |
| 112 | c.wg.Add(1) |
| 113 | g.m[key] = c |
| 114 | g.mu.Unlock() |
| 115 | |
| 116 | g.doCall(c, key, fn) |
| 117 | return c.val, c.err, c.dups > 0 |
| 118 | } |
| 119 | |
| 120 | // DoChan is like Do but returns a channel that will receive the |
| 121 | // results when they are ready. |