MCPcopy
hub / github.com/grafana/tempo / Wait

Method Wait

modules/frontend/queue/queue.go:242–286  ·  view source on GitHub ↗

Wait does c.cond.Wait() but will also return if the context provided is done. All the documentation of sync.Cond.Wait() applies, but it's especially important to remember that the mutex of the cond should be held while Wait() is called (and mutex will be held once it returns)

(ctx context.Context)

Source from the content-addressed store, hash-verified

240// All the documentation of sync.Cond.Wait() applies, but it's especially important to remember that the mutex of
241// the cond should be held while Wait() is called (and mutex will be held once it returns)
242func (c contextCond) Wait(ctx context.Context) {
243 // "condWait" goroutine does q.cond.Wait() and signals through condWait channel.
244 condWait := make(chan struct{})
245 go func() {
246 if c.testHookBeforeWaiting != nil {
247 c.testHookBeforeWaiting()
248 }
249 c.Cond.Wait()
250 close(condWait)
251 }()
252
253 // "waiting" goroutine: signals that the condWait goroutine has started waiting.
254 // Notice that a closed waiting channel implies that the goroutine above has started waiting
255 // (because it has unlocked the mutex), but the other way is not true:
256 // - condWait it may have unlocked and is waiting, but someone else locked the mutex faster than us:
257 // in this case that caller will eventually unlock, and we'll be able to enter here.
258 // - condWait called Wait(), unlocked, received a broadcast and locked again faster than we were able to lock here:
259 // in this case condWait channel will be closed, and this goroutine will be waiting until we unlock.
260 waiting := make(chan struct{})
261 go func() {
262 c.L.Lock()
263 close(waiting)
264 c.L.Unlock()
265 }()
266
267 select {
268 case <-condWait:
269 // We don't know whether the waiting goroutine is done or not, but we don't care:
270 // it will be done once nobody is fighting for the mutex anymore.
271 case <-ctx.Done():
272 // In order to avoid leaking the condWait goroutine, we can send a broadcast.
273 // Before sending the broadcast we need to make sure that condWait goroutine is already waiting (or has already waited).
274 select {
275 case <-condWait:
276 // No need to broadcast as q.cond.Wait() has returned already.
277 return
278 case <-waiting:
279 // q.cond.Wait() might be still waiting (or maybe not!), so we'll poke it just in case.
280 c.Broadcast()
281 }
282
283 // Make sure we are not waiting anymore, we need to do that before returning as the caller will need to unlock the mutex.
284 <-condWait
285 }
286}

Callers 1

TestContextCondFunction · 0.95

Calls 2

WaitMethod · 0.65
DoneMethod · 0.65

Tested by 1

TestContextCondFunction · 0.76