blob: d5791c79feb941686db4fc6e7da5478416285b31 [file] [log] [blame]
Roman Elizarovecda27f2017-04-06 23:06:26 +03001/*
Vsevolod Tolstopyatov6d1a6e32020-02-18 15:28:00 +03002 * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarovecda27f2017-04-06 23:06:26 +03003 */
Vsevolod Tolstopyatov9cbad7d2020-03-27 17:43:45 +03004@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE")
Roman Elizarov0950dfa2018-07-13 10:33:25 +03005package kotlinx.coroutines
Roman Elizarovecda27f2017-04-06 23:06:26 +03006
Roman Elizarov0950dfa2018-07-13 10:33:25 +03007import kotlinx.coroutines.CoroutineStart.*
8import kotlinx.coroutines.intrinsics.*
9import kotlin.coroutines.*
Roman Elizarovecda27f2017-04-06 23:06:26 +030010
11/**
paolopc51bde02018-06-09 09:40:11 +000012 * Defines start options for coroutines builders.
Roman Elizarovc32579e2018-09-09 19:21:43 +030013 * It is used in `start` parameter of [launch][CoroutineScope.launch], [async][CoroutineScope.async], and other coroutine builder functions.
Roman Elizarov7b10c942017-05-16 21:02:51 +030014 *
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;
Roman Elizarov23fb7282018-01-24 23:09:42 +030018 * * [ATOMIC] -- atomically (in a non-cancellable way) schedules coroutine for execution according to its context;
Roman Elizarov7b10c942017-05-16 21:02:51 +030019 * * [UNDISPATCHED] -- immediately executes coroutine until its first suspension point _in the current thread_.
Roman Elizarovecda27f2017-04-06 23:06:26 +030020 */
Roman Elizarov23fb7282018-01-24 23:09:42 +030021public enum class CoroutineStart {
Roman Elizarovecda27f2017-04-06 23:06:26 +030022 /**
Inego39f92ca2019-04-21 13:30:55 +070023 * Default -- immediately schedules the coroutine for execution according to its context.
Roman Elizarovecda27f2017-04-06 23:06:26 +030024 *
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 *
Inegoebe519a2019-04-21 13:22:27 +070029 * Note that [Dispatchers.Unconfined] always returns `false` from its [CoroutineDispatcher.isDispatchNeeded]
Inego39f92ca2019-04-21 13:30:55 +070030 * function, so starting a coroutine with [Dispatchers.Unconfined] by [DEFAULT] is the same as using [UNDISPATCHED].
Roman Elizarova74eb5f2017-05-11 20:15:18 +030031 *
32 * If coroutine [Job] is cancelled before it even had a chance to start executing, then it will not start its
paolopc51bde02018-06-09 09:40:11 +000033 * execution at all, but will complete with an exception.
Roman Elizarova74eb5f2017-05-11 20:15:18 +030034 *
Inego39f92ca2019-04-21 13:30:55 +070035 * Cancellability of a coroutine at suspension points depends on the particular implementation details of
Roman Elizarova74eb5f2017-05-11 20:15:18 +030036 * suspending functions. Use [suspendCancellableCoroutine] to implement cancellable suspending functions.
Roman Elizarovecda27f2017-04-06 23:06:26 +030037 */
38 DEFAULT,
39
40 /**
Inego39f92ca2019-04-21 13:30:55 +070041 * Starts the coroutine lazily, only when it is needed.
Roman Elizarovecda27f2017-04-06 23:06:26 +030042 *
Roman Elizarov23fb7282018-01-24 23:09:42 +030043 * See the documentation for the corresponding coroutine builders for details
Roman Elizarovc32579e2018-09-09 19:21:43 +030044 * (like [launch][CoroutineScope.launch] and [async][CoroutineScope.async]).
Roman Elizarova74eb5f2017-05-11 20:15:18 +030045 *
46 * If coroutine [Job] is cancelled before it even had a chance to start executing, then it will not start its
paolopc51bde02018-06-09 09:40:11 +000047 * execution at all, but will complete with an exception.
Roman Elizarovecda27f2017-04-06 23:06:26 +030048 */
49 LAZY,
50
51 /**
Inego39f92ca2019-04-21 13:30:55 +070052 * Atomically (i.e., in a non-cancellable way) schedules the coroutine for execution according to its context.
Roman Elizarov7b10c942017-05-16 21:02:51 +030053 * This is similar to [DEFAULT], but the coroutine cannot be cancelled before it starts executing.
Roman Elizarova74eb5f2017-05-11 20:15:18 +030054 *
55 * Cancellability of coroutine at suspension points depends on the particular implementation details of
56 * suspending functions as in [DEFAULT].
57 */
Vsevolod Tolstopyatove16eb9d2020-10-26 07:05:06 -070058 @ExperimentalCoroutinesApi // Since 1.0.0, no ETA on stability
Roman Elizarova74eb5f2017-05-11 20:15:18 +030059 ATOMIC,
60
61 /**
Inego39f92ca2019-04-21 13:30:55 +070062 * Immediately executes the coroutine until its first suspension point _in the current thread_ as if the
Yanis Batura8140cfe2019-04-27 21:31:14 +070063 * coroutine was started using [Dispatchers.Unconfined]. However, when the coroutine is resumed from suspension
Roman Elizarovecda27f2017-04-06 23:06:26 +030064 * it is dispatched according to the [CoroutineDispatcher] in its context.
Roman Elizarov4eae2a82017-05-17 20:55:27 +030065 *
66 * This is similar to [ATOMIC] in the sense that coroutine starts executing even if it was already cancelled,
paolopc51bde02018-06-09 09:40:11 +000067 * but the difference is that it starts executing in the same thread.
Roman Elizarov4eae2a82017-05-17 20:55:27 +030068 *
69 * Cancellability of coroutine at suspension points depends on the particular implementation details of
70 * suspending functions as in [DEFAULT].
Roman Elizarov27b8f452018-09-20 21:23:41 +030071 *
72 * **Note: This is an experimental api.** Execution semantics of coroutines may change in the future when this mode is used.
Roman Elizarovecda27f2017-04-06 23:06:26 +030073 */
Vsevolod Tolstopyatove16eb9d2020-10-26 07:05:06 -070074 @ExperimentalCoroutinesApi // Since 1.0.0, no ETA on stability
Roman Elizarovecda27f2017-04-06 23:06:26 +030075 UNDISPATCHED;
76
77 /**
Inego39f92ca2019-04-21 13:30:55 +070078 * Starts the corresponding block as a coroutine with this coroutine's start strategy.
Roman Elizarov4eae2a82017-05-17 20:55:27 +030079 *
80 * * [DEFAULT] uses [startCoroutineCancellable].
81 * * [ATOMIC] uses [startCoroutine].
82 * * [UNDISPATCHED] uses [startCoroutineUndispatched].
83 * * [LAZY] does nothing.
Roman Elizarov27b8f452018-09-20 21:23:41 +030084 *
85 * @suppress **This an internal API and should not be used from general code.**
Roman Elizarov4eae2a82017-05-17 20:55:27 +030086 */
Roman Elizarov27b8f452018-09-20 21:23:41 +030087 @InternalCoroutinesApi
Vsevolod Tolstopyatov9cbad7d2020-03-27 17:43:45 +030088 public operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>): Unit =
Roman Elizarov4eae2a82017-05-17 20:55:27 +030089 when (this) {
Vsevolod Tolstopyatov9cbad7d2020-03-27 17:43:45 +030090 DEFAULT -> block.startCoroutineCancellable(completion)
91 ATOMIC -> block.startCoroutine(completion)
92 UNDISPATCHED -> block.startCoroutineUndispatched(completion)
93 LAZY -> Unit // will start lazily
Roman Elizarov4eae2a82017-05-17 20:55:27 +030094 }
95
96 /**
Roman Elizarov7b10c942017-05-16 21:02:51 +030097 * Starts the corresponding block with receiver as a coroutine with this coroutine start strategy.
Roman Elizarovecda27f2017-04-06 23:06:26 +030098 *
Roman Elizarova74eb5f2017-05-11 20:15:18 +030099 * * [DEFAULT] uses [startCoroutineCancellable].
100 * * [ATOMIC] uses [startCoroutine].
Roman Elizarovecda27f2017-04-06 23:06:26 +0300101 * * [UNDISPATCHED] uses [startCoroutineUndispatched].
102 * * [LAZY] does nothing.
Roman Elizarov27b8f452018-09-20 21:23:41 +0300103 *
104 * @suppress **This an internal API and should not be used from general code.**
Roman Elizarovecda27f2017-04-06 23:06:26 +0300105 */
Roman Elizarov27b8f452018-09-20 21:23:41 +0300106 @InternalCoroutinesApi
Vsevolod Tolstopyatov9cbad7d2020-03-27 17:43:45 +0300107 public operator fun <R, T> invoke(block: suspend R.() -> T, receiver: R, completion: Continuation<T>): Unit =
Roman Elizarovecda27f2017-04-06 23:06:26 +0300108 when (this) {
Vsevolod Tolstopyatov9cbad7d2020-03-27 17:43:45 +0300109 DEFAULT -> block.startCoroutineCancellable(receiver, completion)
110 ATOMIC -> block.startCoroutine(receiver, completion)
111 UNDISPATCHED -> block.startCoroutineUndispatched(receiver, completion)
112 LAZY -> Unit // will start lazily
Roman Elizarovecda27f2017-04-06 23:06:26 +0300113 }
114
115 /**
116 * Returns `true` when [LAZY].
Roman Elizarov27b8f452018-09-20 21:23:41 +0300117 *
118 * @suppress **This an internal API and should not be used from general code.**
Roman Elizarovecda27f2017-04-06 23:06:26 +0300119 */
Roman Elizarov27b8f452018-09-20 21:23:41 +0300120 @InternalCoroutinesApi
Roman Elizarov23fb7282018-01-24 23:09:42 +0300121 public val isLazy: Boolean get() = this === LAZY
Roman Elizarovecda27f2017-04-06 23:06:26 +0300122}