@@ -75,6 +75,7 @@ private object DefaultDelayImpl : EventLoopImplBase(), Runnable {
75
75
try {
76
76
ThreadLocalEventLoop .setEventLoop(DelegatingUnconfinedEventLoop )
77
77
registerTimeLoopThread()
78
+ unTrackTask(this ) /* * see the comment in [startThreadOrObtainSleepingThread] */
78
79
try {
79
80
while (true ) {
80
81
Thread .interrupted() // just reset interruption flag
@@ -107,6 +108,17 @@ private object DefaultDelayImpl : EventLoopImplBase(), Runnable {
107
108
This means that whatever thread is going to be running by the end of this function,
108
109
it's going to notice the tasks it's supposed to run.
109
110
We can return `null` unconditionally. */
111
+ /* * If this function is called from a thread that's already registered as a time loop thread,
112
+ because a time loop thread is not parked right now, the time source will not advance time *currently*,
113
+ but it may do that as soon as the thread calling this is parked, which may happen earlier than the default
114
+ delay thread has a chance to run.
115
+ Because of that, we notify the time source that something is actually happening right now.
116
+ This would work automatically if instead of [scheduleBackgroundIoTask] we used [CoroutineDispatcher.dispatch] on
117
+ [Dispatchers.IO], but then, none of the delays would be skipped, as the whole time a [DefaultDelay] thread runs
118
+ would be considered as a task.
119
+ Therefore, we register a task right now and mark it as completed as soon as a [DefaultDelay] time loop gets
120
+ registered. */
121
+ trackTask(this )
110
122
scheduleBackgroundIoTask(this )
111
123
return null
112
124
}
0 commit comments