• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines
6 
7 import kotlinx.coroutines.internal.*
8 
9 /**
10  * Base class for special [CoroutineDispatcher] which is confined to application "Main" or "UI" thread
11  * and used for any UI-based activities. Instance of `MainDispatcher` can be obtained by [Dispatchers.Main].
12  *
13  * Platform may or may not provide instance of `MainDispatcher`, see documentation to [Dispatchers.Main]
14  */
15 public abstract class MainCoroutineDispatcher : CoroutineDispatcher() {
16 
17     /**
18      * Returns dispatcher that executes coroutines immediately when it is already in the right context
19      * (e.g. current looper is the same as this handler's looper) without an additional [re-dispatch][CoroutineDispatcher.dispatch].
20      *
21      * Immediate dispatcher is safe from stack overflows and in case of nested invocations forms event-loop similar to [Dispatchers.Unconfined].
22      * The event loop is an advanced topic and its implications can be found in [Dispatchers.Unconfined] documentation.
23      * The formed event-loop is shared with [Unconfined] and other immediate dispatchers, potentially overlapping tasks between them.
24      *
25      * Example of usage:
26      * ```
27      * suspend fun updateUiElement(val text: String) {
28      *   /*
29      *    * If it is known that updateUiElement can be invoked both from the Main thread and from other threads,
30      *    * `immediate` dispatcher is used as a performance optimization to avoid unnecessary dispatch.
31      *    *
32      *    * In that case, when `updateUiElement` is invoked from the Main thread, `uiElement.text` will be
33      *    * invoked immediately without any dispatching, otherwise, the `Dispatchers.Main` dispatch cycle will be triggered.
34      *    */
35      *   withContext(Dispatchers.Main.immediate) {
36      *     uiElement.text = text
37      *   }
38      *   // Do context-independent logic such as logging
39      * }
40      * ```
41      *
42      * Method may throw [UnsupportedOperationException] if immediate dispatching is not supported by current dispatcher,
43      * please refer to specific dispatcher documentation.
44      *
45      * [Dispatchers.Main] supports immediate execution for Android, JavaFx and Swing platforms.
46      */
47     public abstract val immediate: MainCoroutineDispatcher
48 
49     /**
50      * Returns a name of this main dispatcher for debugging purposes. This implementation returns
51      * `Dispatchers.Main` or `Dispatchers.Main.immediate` if it is the same as the corresponding
52      * reference in [Dispatchers] or a short class-name representation with address otherwise.
53      */
toStringnull54     override fun toString(): String = toStringInternalImpl() ?: "$classSimpleName@$hexAddress"
55 
56     override fun limitedParallelism(parallelism: Int): CoroutineDispatcher {
57         parallelism.checkParallelism()
58         // MainCoroutineDispatcher is single-threaded -- short-circuit any attempts to limit it
59         return this
60     }
61 
62     /**
63      * Internal method for more specific [toString] implementations. It returns non-null
64      * string if this dispatcher is set in the platform as the main one.
65      * @suppress
66      */
67     @InternalCoroutinesApi
toStringInternalImplnull68     protected fun toStringInternalImpl(): String? {
69         val main = Dispatchers.Main
70         if (this === main) return "Dispatchers.Main"
71         val immediate =
72             try { main.immediate }
73             catch (e: UnsupportedOperationException) { null }
74         if (this === immediate) return "Dispatchers.Main.immediate"
75         return null
76     }
77 }
78