@@ -195,35 +195,41 @@ func (w *priorityqueue[T]) spin() {
195195 w .lockedLock .Lock ()
196196 defer w .lockedLock .Unlock ()
197197
198- w .queue .Ascend (func (item * item [T ]) bool {
199- if w .waiters .Load () == 0 { // no waiters, return as we can not hand anything out anyways
200- return false
201- }
198+ for continueLoop := true ; continueLoop ; {
199+ continueLoop = false
200+ w .queue .Ascend (func (item * item [T ]) bool {
201+ if w .waiters .Load () == 0 { // no waiters, return as we can not hand anything out anyways
202+ return false
203+ }
204+
205+ // No next element we can process
206+ if item .readyAt != nil && item .readyAt .After (w .now ()) {
207+ readyAt := item .readyAt .Sub (w .now ())
208+ if readyAt <= 0 { // Toctou race with the above check
209+ readyAt = 1
210+ }
211+ nextReady = w .tick (readyAt )
212+ return false
213+ }
202214
203- // No next element we can process
204- if item .readyAt != nil && item .readyAt .After (w .now ()) {
205- readyAt := item .readyAt .Sub (w .now ())
206- if readyAt <= 0 { // Toctou race with the above check
207- readyAt = 1
215+ // Item is locked, we can not hand it out
216+ if w .locked .Has (item .key ) {
217+ return true
208218 }
209- nextReady = w .tick (readyAt )
219+
220+ w .metrics .get (item .key )
221+ w .locked .Insert (item .key )
222+ w .waiters .Add (- 1 )
223+ delete (w .items , item .key )
224+ w .queue .Delete (item )
225+ w .get <- * item
226+
227+ // Return false because continuing with Ascend after deleting an item
228+ // can lead to panics within Ascend.
229+ continueLoop = true
210230 return false
211- }
212-
213- // Item is locked, we can not hand it out
214- if w .locked .Has (item .key ) {
215- return true
216- }
217-
218- w .metrics .get (item .key )
219- w .locked .Insert (item .key )
220- w .waiters .Add (- 1 )
221- delete (w .items , item .key )
222- w .queue .Delete (item )
223- w .get <- * item
224-
225- return true
226- })
231+ })
232+ }
227233 }()
228234 }
229235}
0 commit comments