@@ -155,6 +155,11 @@ public suspend fun <T> run(context: CoroutineContext, block: suspend () -> T): T
155
155
* in this blocked thread until the completion of this coroutine.
156
156
* See [CoroutineDispatcher] for the other implementations that are provided by `kotlinx.coroutines`.
157
157
*
158
+ * When [CoroutineDispatcher] is explicitly specified in the [context], then the new coroutine runs in the context of
159
+ * the specified dispatcher while the current thread is blocked. If the specified dispatcher implements [EventLoop]
160
+ * interface and this `runBlocking` invocation is performed from inside of the this event loop's thread, then
161
+ * this event loop is processed using its [processNextEvent][EventLoop.processNextEvent] method until coroutine completes.
162
+ *
158
163
* If this blocked thread is interrupted (see [Thread.interrupt]), then the coroutine job is cancelled and
159
164
* this `runBlocking` invocation throws [InterruptedException].
160
165
*
@@ -166,9 +171,13 @@ public suspend fun <T> run(context: CoroutineContext, block: suspend () -> T): T
166
171
@Throws(InterruptedException ::class )
167
172
public fun <T > runBlocking (context : CoroutineContext = EmptyCoroutineContext , block : suspend CoroutineScope .() -> T ): T {
168
173
val currentThread = Thread .currentThread()
169
- val eventLoop = if (context[ContinuationInterceptor ] == null ) BlockingEventLoop (currentThread) else null
170
- val newContext = newCoroutineContext(context + (eventLoop ? : EmptyCoroutineContext ))
171
- val coroutine = BlockingCoroutine <T >(newContext, currentThread, privateEventLoop = eventLoop != null )
174
+ val contextInterceptor = context[ContinuationInterceptor ]
175
+ val privateEventLoop = contextInterceptor == null // create private event loop if no dispatcher is specified
176
+ val eventLoop = if (privateEventLoop) BlockingEventLoop (currentThread) else contextInterceptor as ? EventLoop
177
+ val newContext = newCoroutineContext(
178
+ if (privateEventLoop) context + (eventLoop as ContinuationInterceptor ) else context
179
+ )
180
+ val coroutine = BlockingCoroutine <T >(newContext, currentThread, eventLoop, privateEventLoop)
172
181
coroutine.start(CoroutineStart .DEFAULT , coroutine, block)
173
182
return coroutine.joinBlocking()
174
183
}
@@ -210,10 +219,9 @@ private class RunCompletion<in T>(
210
219
private class BlockingCoroutine <T >(
211
220
parentContext : CoroutineContext ,
212
221
private val blockedThread : Thread ,
222
+ private val eventLoop : EventLoop ? ,
213
223
private val privateEventLoop : Boolean
214
224
) : AbstractCoroutine<T>(parentContext, true ) {
215
- private val eventLoop: EventLoop ? = parentContext[ContinuationInterceptor ] as ? EventLoop
216
-
217
225
init {
218
226
if (privateEventLoop) require(eventLoop is BlockingEventLoop )
219
227
}
0 commit comments