• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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