@@ -27,46 +27,30 @@ import kotlin.coroutines.*
27
27
*
28
28
* This class ensures that debugging facilities in [newCoroutineContext] function work properly.
29
29
*/
30
- public abstract class CoroutineDispatcher :
31
- AbstractCoroutineContextElement (ContinuationInterceptor ), ContinuationInterceptor {
30
+ public abstract class CoroutineDispatcher
31
+ : AbstractCoroutineContextElement (ContinuationInterceptor ), ContinuationInterceptor {
32
+
32
33
/* *
33
- * Returns `true` if the execution shall be dispatched onto another thread .
34
+ * Returns `true` if the execution of the coroutine should be performed with [dispatch] method .
34
35
* The default behavior for most dispatchers is to return `true`.
35
36
*
36
- * This method should never be used from general code, it is used only by `kotlinx.coroutines`
37
- * internals and its contract with the rest of the API is an implementation detail.
38
- *
39
- * UI dispatchers _should not_ override `isDispatchNeeded`, but leave the default implementation that
40
- * returns `true`. To understand the rationale beyond this recommendation, consider the following code:
41
- *
42
- * ```kotlin
43
- * fun asyncUpdateUI() = async(Dispatchers.Main) {
44
- * // do something here that updates something in UI
45
- * }
46
- * ```
47
- *
48
- * When you invoke `asyncUpdateUI` in some background thread, it immediately continues to the next
49
- * line, while the UI update happens asynchronously in the UI thread. However, if you invoke
50
- * it in the UI thread itself, it will update the UI _synchronously_ if your `isDispatchNeeded` is
51
- * overridden with a thread check. Checking if we are already in the UI thread seems more
52
- * efficient (and it might indeed save a few CPU cycles), but this subtle and context-sensitive
53
- * difference in behavior makes the resulting async code harder to debug.
37
+ * If this method returns `false`, the coroutine is resumed immediately in the current thread,
38
+ * potentially forming an event-loop to prevent stack overflows.
39
+ * The event loop is an advanced topic and its implications can be found in [Dispatchers.Unconfined] documentation.
54
40
*
55
- * Basically, the choice here is between the "JS-style" asynchronous approach (async actions
56
- * are always postponed to be executed later in the event dispatch thread) and "C#-style" approach
57
- * (async actions are executed in the invoker thread until the first suspension point).
58
- * While the C# approach seems to be more efficient, it ends up with recommendations like
59
- * "use `yield` if you need to ....". This is error-prone. The JS-style approach is more consistent
60
- * and does not require programmers to think about whether they need to yield or not.
41
+ * A dispatcher can override this method to provide a performance optimization and avoid paying a cost of an unnecessary dispatch.
42
+ * E.g. [MainCoroutineDispatcher.immediate] checks whether we are already in the required UI thread in this method and avoids
43
+ * an additional dispatch when it is not required. But this method should not return `false` by default, because
44
+ * it may expose unexpected behaviour (e.g. with interleaved event-loops) and unexpected order of events.
61
45
*
62
- * However, coroutine builders like [launch][CoroutineScope.launch] and [async][CoroutineScope.async] accept an optional [CoroutineStart]
63
- * parameter that allows one to optionally choose the C#-style [ CoroutineStart.UNDISPATCHED] behavior
64
- * whenever it is needed for efficiency .
46
+ * Coroutine builders like [launch][CoroutineScope.launch] and [async][CoroutineScope.async] accept an optional [CoroutineStart]
47
+ * parameter that allows one to optionally choose the [undispatched][ CoroutineStart.UNDISPATCHED] behavior to start coroutine immediately,
48
+ * but to be resumed only in the provided dispatcher .
65
49
*
66
50
* This method should generally be exception-safe. An exception thrown from this method
67
51
* may leave the coroutines that use this dispatcher in the inconsistent and hard to debug state.
68
52
*
69
- * **Note: This is an experimental api.** Execution semantics of coroutines may change in the future when this function returns `false`.
53
+ * **This is an experimental api.** Execution semantics of coroutines may change in the future when this function returns `false`.
70
54
*/
71
55
@ExperimentalCoroutinesApi
72
56
public open fun isDispatchNeeded (context : CoroutineContext ): Boolean = true
0 commit comments