@@ -23,6 +23,8 @@ import kotlin.native.concurrent.*
23
23
internal abstract class EventLoop : CoroutineDispatcher () {
24
24
/* *
25
25
* Counts the number of nested `runBlocking` and [Dispatchers.Unconfined] that use this event loop.
26
+ * There are two 32-bit counters encoded in this 64-bit value, allowing to count [Dispatchers.Unconfined]
27
+ * separately from `runBlocking`; see [delta] and its uses.
26
28
*/
27
29
private var useCount = 0L
28
30
@@ -51,7 +53,8 @@ internal abstract class EventLoop : CoroutineDispatcher() {
51
53
* (no check for performance reasons, may be added in the future).
52
54
*/
53
55
public open fun processNextEvent (): Long {
54
- if (! processUnconfinedEvent()) return Long .MAX_VALUE
56
+ val task = popNextTask() ? : return Long .MAX_VALUE
57
+ task.run ()
55
58
return nextTime
56
59
}
57
60
@@ -64,11 +67,17 @@ internal abstract class EventLoop : CoroutineDispatcher() {
64
67
}
65
68
66
69
public fun processUnconfinedEvent (): Boolean {
67
- val queue = unconfinedQueue ? : return false
68
- val task = queue.removeFirstOrNull() ? : return false
70
+ val task = popUnconfinedTask() ? : return false
69
71
task.run ()
70
72
return true
71
73
}
74
+
75
+ public fun popUnconfinedTask (): DispatchedTask <* >? =
76
+ unconfinedQueue?.removeFirstOrNull()
77
+
78
+ protected open fun popNextTask (onlyUnconfined : Boolean = false): Runnable ? =
79
+ popUnconfinedTask()
80
+
72
81
/* *
73
82
* Returns `true` if the invoking `runBlocking(context) { ... }` that was passed this event loop in its context
74
83
* parameter should call [processNextEvent] for this event loop (otherwise, it will process thread-local one).
@@ -249,9 +258,15 @@ internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
249
258
}
250
259
}
251
260
252
- override fun processNextEvent (): Long {
261
+ override fun popNextTask (onlyUnconfined : Boolean ): Runnable ? {
262
+ val unconfined = popUnconfinedTask()
263
+ if (onlyUnconfined) {
264
+ return unconfined
265
+ }
253
266
// unconfined events take priority
254
- if (processUnconfinedEvent()) return nextTime
267
+ if (unconfined != null ) {
268
+ return unconfined
269
+ }
255
270
// queue all delayed tasks that are due to be executed
256
271
val delayed = _delayed .value
257
272
if (delayed != null && ! delayed.isEmpty) {
@@ -269,8 +284,7 @@ internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
269
284
}
270
285
}
271
286
// then process one event from queue
272
- dequeue()?.run ()
273
- return nextTime
287
+ return dequeue()
274
288
}
275
289
276
290
public final override fun dispatch (context : CoroutineContext , block : Runnable ) = enqueue(block)
0 commit comments