blob: daba38f0fdc9dbe784644e645f80892ca161fa2d [file] [log] [blame]
/*
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines
/**
* Base class for special [CoroutineDispatcher] which is confined to application "Main" or "UI" thread
* and used for any UI-based activities. Instance of `MainDispatcher` can be obtained by [Dispatchers.Main].
*
* Platform may or may not provide instance of `MainDispatcher`, see documentation to [Dispatchers.Main]
*/
public abstract class MainCoroutineDispatcher : CoroutineDispatcher() {
/**
* Returns dispatcher that executes coroutines immediately when it is already in the right context
* (e.g. current looper is the same as this handler's looper) without an additional [re-dispatch][CoroutineDispatcher.dispatch].
*
* Immediate dispatcher is safe from stack overflows and in case of nested invocations forms event-loop similar to [Dispatchers.Unconfined].
* The event loop is an advanced topic and its implications can be found in [Dispatchers.Unconfined] documentation.
* The formed event-loop is shared with [Unconfined] and other immediate dispatchers, potentially overlapping tasks between them.
*
* Example of usage:
* ```
* suspend fun updateUiElement(val text: String) {
* /*
* * If it is known that updateUiElement can be invoked both from the Main thread and from other threads,
* * `immediate` dispatcher is used as a performance optimization to avoid unnecessary dispatch.
* *
* * In that case, when `updateUiElement` is invoked from the Main thread, `uiElement.text` will be
* * invoked immediately without any dispatching, otherwise, the `Dispatchers.Main` dispatch cycle will be triggered.
* */
* withContext(Dispatchers.Main.immediate) {
* uiElement.text = text
* }
* // Do context-independent logic such as logging
* }
* ```
*
* Method may throw [UnsupportedOperationException] if immediate dispatching is not supported by current dispatcher,
* please refer to specific dispatcher documentation.
*
* [Dispatchers.Main] supports immediate execution for Android, JavaFx and Swing platforms.
*/
public abstract val immediate: MainCoroutineDispatcher
/**
* Returns a name of this main dispatcher for debugging purposes. This implementation returns
* `Dispatchers.Main` or `Dispatchers.Main.immediate` if it is the same as the corresponding
* reference in [Dispatchers] or a short class-name representation with address otherwise.
*/
override fun toString(): String = toStringInternalImpl() ?: "$classSimpleName@$hexAddress"
/**
* Internal method for more specific [toString] implementations. It returns non-null
* string if this dispatcher is set in the platform as the main one.
* @suppress
*/
@InternalCoroutinesApi
protected fun toStringInternalImpl(): String? {
val main = Dispatchers.Main
if (this === main) return "Dispatchers.Main"
val immediate =
try { main.immediate }
catch (e: UnsupportedOperationException) { null }
if (this === immediate) return "Dispatchers.Main.immediate"
return null
}
}