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