@@ -256,21 +256,7 @@ internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
256
256
// unconfined events take priority
257
257
if (processUnconfinedEvent()) return 0
258
258
// queue all delayed tasks that are due to be executed
259
- val delayed = _delayed .value
260
- if (delayed != null && ! delayed.isEmpty) {
261
- val now = nanoTime()
262
- while (true ) {
263
- // make sure that moving from delayed to queue removes from delayed only after it is added to queue
264
- // to make sure that 'isEmpty' and `nextTime` that check both of them
265
- // do not transiently report that both delayed and queue are empty during move
266
- delayed.removeFirstIf {
267
- if (it.timeToExecute(now)) {
268
- enqueueImpl(it)
269
- } else
270
- false
271
- } ? : break // quit loop when nothing more to remove or enqueueImpl returns false on "isComplete"
272
- }
273
- }
259
+ enqueueDelayedTasks()
274
260
// then process one event from queue
275
261
val task = dequeue()
276
262
if (task != null ) {
@@ -283,6 +269,8 @@ internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
283
269
final override fun dispatch (context : CoroutineContext , block : Runnable ) = enqueue(block)
284
270
285
271
open fun enqueue (task : Runnable ) {
272
+ // are there some delayed tasks that should execute before this one? If so, move them to the queue first.
273
+ enqueueDelayedTasks()
286
274
if (enqueueImpl(task)) {
287
275
// todo: we should unpark only when this delayed task became first in the queue
288
276
unpark()
@@ -336,6 +324,25 @@ internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
336
324
}
337
325
}
338
326
327
+ /* * Move all delayed tasks that are due to the main queue. */
328
+ private fun enqueueDelayedTasks () {
329
+ val delayed = _delayed .value
330
+ if (delayed != null && ! delayed.isEmpty) {
331
+ val now = nanoTime()
332
+ while (true ) {
333
+ // make sure that moving from delayed to queue removes from delayed only after it is added to queue
334
+ // to make sure that 'isEmpty' and `nextTime` that check both of them
335
+ // do not transiently report that both delayed and queue are empty during move
336
+ delayed.removeFirstIf {
337
+ if (it.timeToExecute(now)) {
338
+ enqueueImpl(it)
339
+ } else
340
+ false
341
+ } ? : break // quit loop when nothing more to remove or enqueueImpl returns false on "isComplete"
342
+ }
343
+ }
344
+ }
345
+
339
346
private fun closeQueue () {
340
347
assert { isCompleted }
341
348
_queue .loop { queue ->
0 commit comments