1 package kotlinx.coroutines 2 3 import kotlinx.coroutines.CoroutineStart.* 4 import kotlinx.coroutines.intrinsics.* 5 import kotlin.coroutines.* 6 7 /** 8 * Defines start options for coroutines builders. 9 * It is used in `start` parameter of [launch][CoroutineScope.launch], [async][CoroutineScope.async], and other coroutine builder functions. 10 * 11 * The summary of coroutine start options is: 12 * - [DEFAULT] -- immediately schedules coroutine for execution according to its context; 13 * - [LAZY] -- starts coroutine lazily, only when it is needed; 14 * - [ATOMIC] -- atomically (in a non-cancellable way) schedules coroutine for execution according to its context; 15 * - [UNDISPATCHED] -- immediately executes coroutine until its first suspension point _in the current thread_. 16 */ 17 public enum class CoroutineStart { 18 /** 19 * Default -- immediately schedules the coroutine for execution according to its context. 20 * 21 * If the [CoroutineDispatcher] of the coroutine context returns `true` from [CoroutineDispatcher.isDispatchNeeded] 22 * function as most dispatchers do, then the coroutine code is dispatched for execution later, while the code that 23 * invoked the coroutine builder continues execution. 24 * 25 * Note that [Dispatchers.Unconfined] always returns `false` from its [CoroutineDispatcher.isDispatchNeeded] 26 * function, so starting a coroutine with [Dispatchers.Unconfined] by [DEFAULT] is the same as using [UNDISPATCHED]. 27 * 28 * If coroutine [Job] is cancelled before it even had a chance to start executing, then it will not start its 29 * execution at all, but will complete with an exception. 30 * 31 * Cancellability of a coroutine at suspension points depends on the particular implementation details of 32 * suspending functions. Use [suspendCancellableCoroutine] to implement cancellable suspending functions. 33 */ 34 DEFAULT, 35 36 /** 37 * Starts the coroutine lazily, only when it is needed. 38 * 39 * See the documentation for the corresponding coroutine builders for details 40 * (like [launch][CoroutineScope.launch] and [async][CoroutineScope.async]). 41 * 42 * If coroutine [Job] is cancelled before it even had a chance to start executing, then it will not start its 43 * execution at all, but will complete with an exception. 44 */ 45 LAZY, 46 47 /** 48 * Atomically (i.e., in a non-cancellable way) schedules the coroutine for execution according to its context. 49 * This is similar to [DEFAULT], but the coroutine cannot be cancelled before it starts executing. 50 * 51 * Cancellability of coroutine at suspension points depends on the particular implementation details of 52 * suspending functions as in [DEFAULT]. 53 */ 54 @ExperimentalCoroutinesApi // Since 1.0.0, no ETA on stability 55 ATOMIC, 56 57 /** 58 * Immediately executes the coroutine until its first suspension point _in the current thread_ similarly to 59 * the coroutine being started using [Dispatchers.Unconfined]. However, when the coroutine is resumed from suspension 60 * it is dispatched according to the [CoroutineDispatcher] in its context. 61 * 62 * This is similar to [ATOMIC] in the sense that coroutine starts executing even if it was already cancelled, 63 * but the difference is that it starts executing in the same thread. 64 * 65 * Cancellability of coroutine at suspension points depends on the particular implementation details of 66 * suspending functions as in [DEFAULT]. 67 * 68 * ### Unconfined event loop 69 * 70 * Unlike [Dispatchers.Unconfined] and [MainCoroutineDispatcher.immediate], nested undispatched coroutines do not form 71 * an event loop that otherwise prevents potential stack overflow in case of unlimited nesting. 72 */ 73 UNDISPATCHED; 74 75 /** 76 * Starts the corresponding block with receiver as a coroutine with this coroutine start strategy. 77 * 78 * - [DEFAULT] uses [startCoroutineCancellable]. 79 * - [ATOMIC] uses [startCoroutine]. 80 * - [UNDISPATCHED] uses [startCoroutineUndispatched]. 81 * - [LAZY] does nothing. 82 * 83 * @suppress **This an internal API and should not be used from general code.** 84 */ 85 @InternalCoroutinesApi invokenull86 public operator fun <R, T> invoke(block: suspend R.() -> T, receiver: R, completion: Continuation<T>): Unit = 87 when (this) { 88 DEFAULT -> block.startCoroutineCancellable(receiver, completion) 89 ATOMIC -> block.startCoroutine(receiver, completion) 90 UNDISPATCHED -> block.startCoroutineUndispatched(receiver, completion) 91 LAZY -> Unit // will start lazily 92 } 93 94 /** 95 * Returns `true` when [LAZY]. 96 * 97 * @suppress **This an internal API and should not be used from general code.** 98 */ 99 @InternalCoroutinesApi 100 public val isLazy: Boolean get() = this === LAZY 101 } 102