doCall handles the single call for a key.
(c *call[V], key K, fn func() (V, error))
| 145 | |
| 146 | // doCall handles the single call for a key. |
| 147 | func (g *Group[K, V]) doCall(c *call[V], key K, fn func() (V, error)) { |
| 148 | normalReturn := false |
| 149 | recovered := false |
| 150 | |
| 151 | // use double-defer to distinguish panic from runtime.Goexit, |
| 152 | // more details see https://golang.org/cl/134395 |
| 153 | defer func() { |
| 154 | // the given function invoked runtime.Goexit |
| 155 | if !normalReturn && !recovered { |
| 156 | c.err = errGoexit |
| 157 | } |
| 158 | |
| 159 | g.mu.Lock() |
| 160 | defer g.mu.Unlock() |
| 161 | c.wg.Done() |
| 162 | if g.m[key] == c { |
| 163 | delete(g.m, key) |
| 164 | } |
| 165 | |
| 166 | if e, ok := c.err.(*panicError); ok { |
| 167 | // In order to prevent the waiting channels from being blocked forever, |
| 168 | // needs to ensure that this panic cannot be recovered. |
| 169 | if len(c.chans) > 0 { |
| 170 | go panic(e) |
| 171 | select {} // Keep this goroutine around so that it will appear in the crash dump. |
| 172 | } else { |
| 173 | panic(e) |
| 174 | } |
| 175 | } else if c.err == errGoexit { |
| 176 | // Already in the process of goexit, no need to call again |
| 177 | } else { |
| 178 | // Normal return |
| 179 | for _, ch := range c.chans { |
| 180 | ch <- Result[V]{c.val, c.err, c.dups > 0} |
| 181 | } |
| 182 | } |
| 183 | }() |
| 184 | |
| 185 | func() { |
| 186 | defer func() { |
| 187 | if !normalReturn { |
| 188 | // Ideally, we would wait to take a stack trace until we've determined |
| 189 | // whether this is a panic or a runtime.Goexit. |
| 190 | // |
| 191 | // Unfortunately, the only way we can distinguish the two is to see |
| 192 | // whether the recover stopped the goroutine from terminating, and by |
| 193 | // the time we know that, the part of the stack trace relevant to the |
| 194 | // panic has been discarded. |
| 195 | if r := recover(); r != nil { |
| 196 | c.err = newPanicError(r) |
| 197 | } |
| 198 | } |
| 199 | }() |
| 200 | |
| 201 | c.val, c.err = fn() |
| 202 | normalReturn = true |
| 203 | }() |
| 204 |
no test coverage detected