@@ -6,23 +6,56 @@ import kotlin.coroutines.*
6
6
/* *
7
7
* Base class to be extended by all coroutine dispatcher implementations.
8
8
*
9
+ * If `kotlinx-coroutines` is used, it is recommended to avoid [ContinuationInterceptor] instances that are not
10
+ * [CoroutineDispatcher] implementations, as [CoroutineDispatcher] ensures that the
11
+ * debugging facilities in the [newCoroutineContext] function work properly.
12
+ *
13
+ * ## Predefined dispatchers
14
+ *
9
15
* The following standard implementations are provided by `kotlinx.coroutines` as properties on
10
16
* the [Dispatchers] object:
11
17
*
12
- * - [Dispatchers.Default] — is used by all standard builders if no dispatcher or any other [ContinuationInterceptor]
13
- * is specified in their context. It uses a common pool of shared background threads.
18
+ * - [Dispatchers.Default] is used by all standard builders if no dispatcher or any other [ContinuationInterceptor]
19
+ * is specified in their context.
20
+ * It uses a common pool of shared background threads.
14
21
* This is an appropriate choice for compute-intensive coroutines that consume CPU resources.
15
- * - [Dispatchers.IO] — uses a shared pool of on-demand created threads and is designed for offloading of IO-intensive _blocking_
22
+ * - `Dispatchers.IO` (available on the JVM and Native targets)
23
+ * uses a shared pool of on-demand created threads and is designed for offloading of IO-intensive _blocking_
16
24
* operations (like file I/O and blocking socket I/O).
17
- * - [Dispatchers.Unconfined] — starts coroutine execution in the current call-frame until the first suspension,
18
- * whereupon the coroutine builder function returns.
19
- * The coroutine will later resume in whatever thread used by the
20
- * corresponding suspending function, without confining it to any specific thread or pool.
25
+ * - [Dispatchers.Main] represents the UI thread if one is available.
26
+ * - [Dispatchers.Unconfined] starts coroutine execution in the current call-frame until the first suspension,
27
+ * at which point the coroutine builder function returns.
28
+ * When the coroutine is resumed, the thread from which it is resumed will run the coroutine code until the next
29
+ * suspension, and so on.
21
30
* **The `Unconfined` dispatcher should not normally be used in code**.
22
- * - Private thread pools can be created with [newSingleThreadContext] and [newFixedThreadPoolContext].
23
- * - An arbitrary [Executor][java.util.concurrent.Executor] can be converted to a dispatcher with the [asCoroutineDispatcher] extension function.
31
+ * - Calling [limitedParallelism] on any dispatcher creates a view of the dispatcher that limits the parallelism
32
+ * to the given value.
33
+ * This allows creating private thread pools without spawning new threads.
34
+ * For example, `Dispatchers.IO.limitedParallelism(4)` creates a dispatcher that allows running at most
35
+ * 4 tasks in parallel, reusing the existing IO dispatcher threads.
36
+ * - When thread pools completely separate from [Dispatchers.Default] and [Dispatchers.IO] are required,
37
+ * they can be created with `newSingleThreadContext` and `newFixedThreadPoolContext` on the JVM and Native targets.
38
+ * - An arbitrary `java.util.concurrent.Executor` can be converted to a dispatcher with the
39
+ * `asCoroutineDispatcher` extension function.
40
+ *
41
+ * ## Dispatch procedure
24
42
*
25
- * This class ensures that debugging facilities in [newCoroutineContext] function work properly.
43
+ * Typically, a dispatch procedure is performed as follows:
44
+ *
45
+ * - First, [isDispatchNeeded] is invoked to determine whether the coroutine should be dispatched
46
+ * or is already in the right context.
47
+ * - If [isDispatchNeeded] returns `true`, the coroutine is dispatched using the [dispatch] method.
48
+ * It may take a while for the dispatcher to start the task,
49
+ * but the [dispatch] method itself may return immediately, before the task has even begun to execute.
50
+ * - If no dispatch is needed (which is the case for [Dispatchers.Main.immediate][MainCoroutineDispatcher.immediate]
51
+ * when already on the main thread and for [Dispatchers.Unconfined]),
52
+ * [dispatch] is typically not called,
53
+ * and the coroutine is resumed in the thread performing the dispatch procedure,
54
+ * forming an event loop to prevent stack overflows.
55
+ * See [Dispatchers.Unconfined] for a description of event loops.
56
+ *
57
+ * This behavior may be different on the very first dispatch procedure for a given coroutine, depending on the
58
+ * [CoroutineStart] parameter of the coroutine builder.
26
59
*/
27
60
public abstract class CoroutineDispatcher :
28
61
AbstractCoroutineContextElement (ContinuationInterceptor ), ContinuationInterceptor {
@@ -205,7 +238,7 @@ public abstract class CoroutineDispatcher :
205
238
206
239
public final override fun releaseInterceptedContinuation (continuation : Continuation <* >) {
207
240
/*
208
- * Unconditional cast is safe here: we only return DispatchedContinuation from `interceptContinuation`,
241
+ * Unconditional cast is safe here: we return only DispatchedContinuation from `interceptContinuation`,
209
242
* any ClassCastException can only indicate compiler bug
210
243
*/
211
244
val dispatched = continuation as DispatchedContinuation <* >
@@ -229,4 +262,3 @@ public abstract class CoroutineDispatcher :
229
262
/* * @suppress for nicer debugging */
230
263
override fun toString (): String = " $classSimpleName @$hexAddress "
231
264
}
232
-
0 commit comments