Skip to content

Commit 5f2b0c7

Browse files
committed
Revert decomposition of process to dequeue and task.run
Also adds the performance optimization. See the discussion on the PR.
1 parent 021cca3 commit 5f2b0c7

File tree

2 files changed

+14
-33
lines changed

2 files changed

+14
-33
lines changed

kotlinx-coroutines-core/common/src/EventLoop.common.kt

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ import kotlin.native.concurrent.*
2323
internal abstract class EventLoop : CoroutineDispatcher() {
2424
/**
2525
* 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.
2826
*/
2927
private var useCount = 0L
3028

@@ -53,9 +51,8 @@ internal abstract class EventLoop : CoroutineDispatcher() {
5351
* (no check for performance reasons, may be added in the future).
5452
*/
5553
public open fun processNextEvent(): Long {
56-
val task = dequeueNextTask() ?: return Long.MAX_VALUE
57-
task.run()
58-
return nextTime
54+
if (!processUnconfinedEvent()) return Long.MAX_VALUE
55+
return 0
5956
}
6057

6158
protected open val isEmpty: Boolean get() = isUnconfinedQueueEmpty
@@ -67,20 +64,11 @@ internal abstract class EventLoop : CoroutineDispatcher() {
6764
}
6865

6966
public fun processUnconfinedEvent(): Boolean {
70-
val task = dequeueUnconfinedTask() ?: return false
67+
val queue = unconfinedQueue ?: return false
68+
val task = queue.removeFirstOrNull() ?: return false
7169
task.run()
7270
return true
7371
}
74-
75-
protected fun dequeueUnconfinedTask(): DispatchedTask<*>? =
76-
unconfinedQueue?.removeFirstOrNull()
77-
78-
/**
79-
* Get the next event in this event loop, if there is one.
80-
*/
81-
protected open fun dequeueNextTask(): Runnable? =
82-
dequeueUnconfinedTask()
83-
8472
/**
8573
* Returns `true` if the invoking `runBlocking(context) { ... }` that was passed this event loop in its context
8674
* parameter should call [processNextEvent] for this event loop (otherwise, it will process thread-local one).
@@ -261,12 +249,9 @@ internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
261249
}
262250
}
263251

264-
protected override fun dequeueNextTask(): Runnable? {
265-
val unconfined = dequeueUnconfinedTask()
252+
override fun processNextEvent(): Long {
266253
// unconfined events take priority
267-
if (unconfined != null) {
268-
return unconfined
269-
}
254+
if (processUnconfinedEvent()) return 0
270255
// queue all delayed tasks that are due to be executed
271256
val delayed = _delayed.value
272257
if (delayed != null && !delayed.isEmpty) {
@@ -284,11 +269,11 @@ internal abstract class EventLoopImplBase: EventLoopImplPlatform(), Delay {
284269
}
285270
}
286271
// then process one event from queue
287-
return dequeue()
288-
}
289-
290-
override fun processNextEvent(): Long {
291-
dequeueNextTask()?.run()
272+
val task = dequeue()
273+
if (task != null) {
274+
task.run()
275+
return 0
276+
}
292277
return nextTime
293278
}
294279

kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,16 @@ internal actual object DefaultExecutor : EventLoopImplBase(), Runnable {
6565
if (!notifyStartup()) return
6666
while (true) {
6767
Thread.interrupted() // just reset interruption flag
68-
val nextTask = dequeueNextTask()
69-
if (nextTask != null) {
70-
shutdownNanos = Long.MAX_VALUE
71-
nextTask.run()
72-
}
73-
var parkNanos = nextTime
68+
var parkNanos = processNextEvent()
7469
if (parkNanos == Long.MAX_VALUE) {
7570
// nothing to do, initialize shutdown timeout
7671
val now = nanoTime()
7772
if (shutdownNanos == Long.MAX_VALUE) shutdownNanos = now + KEEP_ALIVE_NANOS
7873
val tillShutdown = shutdownNanos - now
7974
if (tillShutdown <= 0) return // shut thread down
8075
parkNanos = parkNanos.coerceAtMost(tillShutdown)
81-
}
76+
} else
77+
shutdownNanos = Long.MAX_VALUE
8278
if (parkNanos > 0) {
8379
// check if shutdown was requested and bail out in this case
8480
if (isShutdownRequested) return

0 commit comments

Comments
 (0)