blob: fd3718265307c977c1f0d3fae89737d2ed40ca24 [file] [log] [blame]
Roman Elizarovecda27f2017-04-06 23:06:26 +03001/*
2 * Copyright 2016-2017 JetBrains s.r.o.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package kotlinx.coroutines.experimental
18
Roman Elizarov4eae2a82017-05-17 20:55:27 +030019import kotlinx.coroutines.experimental.CoroutineStart.*
Roman Elizarov2adf8bc2018-01-24 20:09:57 +030020import kotlinx.coroutines.experimental.intrinsics.*
21import kotlin.coroutines.experimental.*
Roman Elizarovecda27f2017-04-06 23:06:26 +030022
23/**
paolopc51bde02018-06-09 09:40:11 +000024 * Defines start options for coroutines builders.
Roman Elizarov23fb7282018-01-24 23:09:42 +030025 * It is used in `start` parameter of [launch], [async], and other coroutine builder functions.
Roman Elizarov7b10c942017-05-16 21:02:51 +030026 *
27 * The summary of coroutine start options is:
28 * * [DEFAULT] -- immediately schedules coroutine for execution according to its context;
29 * * [LAZY] -- starts coroutine lazily, only when it is needed;
Roman Elizarov23fb7282018-01-24 23:09:42 +030030 * * [ATOMIC] -- atomically (in a non-cancellable way) schedules coroutine for execution according to its context;
Roman Elizarov7b10c942017-05-16 21:02:51 +030031 * * [UNDISPATCHED] -- immediately executes coroutine until its first suspension point _in the current thread_.
Roman Elizarovecda27f2017-04-06 23:06:26 +030032 */
Roman Elizarov23fb7282018-01-24 23:09:42 +030033public enum class CoroutineStart {
Roman Elizarovecda27f2017-04-06 23:06:26 +030034 /**
Roman Elizarov7b10c942017-05-16 21:02:51 +030035 * Default -- immediately schedules coroutine for execution according to its context.
Roman Elizarovecda27f2017-04-06 23:06:26 +030036 *
37 * If the [CoroutineDispatcher] of the coroutine context returns `true` from [CoroutineDispatcher.isDispatchNeeded]
38 * function as most dispatchers do, then the coroutine code is dispatched for execution later, while the code that
39 * invoked the coroutine builder continues execution.
40 *
41 * Note, that [Unconfined] dispatcher always returns `false` from its [CoroutineDispatcher.isDispatchNeeded]
42 * function, so starting coroutine with [Unconfined] dispatcher by [DEFAULT] is the same as using [UNDISPATCHED].
Roman Elizarova74eb5f2017-05-11 20:15:18 +030043 *
44 * 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 +000045 * execution at all, but will complete with an exception.
Roman Elizarova74eb5f2017-05-11 20:15:18 +030046 *
47 * Cancellability of coroutine at suspension points depends on the particular implementation details of
48 * suspending functions. Use [suspendCancellableCoroutine] to implement cancellable suspending functions.
Roman Elizarovecda27f2017-04-06 23:06:26 +030049 */
50 DEFAULT,
51
52 /**
53 * Starts coroutine lazily, only when it is needed.
54 *
Roman Elizarov23fb7282018-01-24 23:09:42 +030055 * See the documentation for the corresponding coroutine builders for details
56 * (like [launch] and [async]).
Roman Elizarova74eb5f2017-05-11 20:15:18 +030057 *
58 * 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 +000059 * execution at all, but will complete with an exception.
Roman Elizarovecda27f2017-04-06 23:06:26 +030060 */
61 LAZY,
62
63 /**
paolopc51bde02018-06-09 09:40:11 +000064 * Atomically (i.e., in a non-cancellable way) schedules coroutine for execution according to its context.
Roman Elizarov7b10c942017-05-16 21:02:51 +030065 * This is similar to [DEFAULT], but the coroutine cannot be cancelled before it starts executing.
Roman Elizarova74eb5f2017-05-11 20:15:18 +030066 *
67 * Cancellability of coroutine at suspension points depends on the particular implementation details of
68 * suspending functions as in [DEFAULT].
69 */
70 ATOMIC,
71
72 /**
paolopc51bde02018-06-09 09:40:11 +000073 * Immediately executes coroutine until its first suspension point _in the current thread_ as if the
Roman Elizarovecda27f2017-04-06 23:06:26 +030074 * coroutine was started using [Unconfined] dispatcher. However, when coroutine is resumed from suspension
75 * it is dispatched according to the [CoroutineDispatcher] in its context.
Roman Elizarov4eae2a82017-05-17 20:55:27 +030076 *
77 * This is similar to [ATOMIC] in the sense that coroutine starts executing even if it was already cancelled,
paolopc51bde02018-06-09 09:40:11 +000078 * but the difference is that it starts executing in the same thread.
Roman Elizarov4eae2a82017-05-17 20:55:27 +030079 *
80 * Cancellability of coroutine at suspension points depends on the particular implementation details of
81 * suspending functions as in [DEFAULT].
Roman Elizarovecda27f2017-04-06 23:06:26 +030082 */
83 UNDISPATCHED;
84
85 /**
Roman Elizarov4eae2a82017-05-17 20:55:27 +030086 * Starts the corresponding block as a coroutine with this coroutine start strategy.
87 *
88 * * [DEFAULT] uses [startCoroutineCancellable].
89 * * [ATOMIC] uses [startCoroutine].
90 * * [UNDISPATCHED] uses [startCoroutineUndispatched].
91 * * [LAZY] does nothing.
92 */
Roman Elizarov23fb7282018-01-24 23:09:42 +030093 public operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>) =
Roman Elizarov4eae2a82017-05-17 20:55:27 +030094 when (this) {
95 CoroutineStart.DEFAULT -> block.startCoroutineCancellable(completion)
96 CoroutineStart.ATOMIC -> block.startCoroutine(completion)
97 CoroutineStart.UNDISPATCHED -> block.startCoroutineUndispatched(completion)
98 CoroutineStart.LAZY -> Unit // will start lazily
99 }
100
101 /**
Roman Elizarov7b10c942017-05-16 21:02:51 +0300102 * Starts the corresponding block with receiver as a coroutine with this coroutine start strategy.
Roman Elizarovecda27f2017-04-06 23:06:26 +0300103 *
Roman Elizarova74eb5f2017-05-11 20:15:18 +0300104 * * [DEFAULT] uses [startCoroutineCancellable].
105 * * [ATOMIC] uses [startCoroutine].
Roman Elizarovecda27f2017-04-06 23:06:26 +0300106 * * [UNDISPATCHED] uses [startCoroutineUndispatched].
107 * * [LAZY] does nothing.
108 */
Roman Elizarov23fb7282018-01-24 23:09:42 +0300109 public operator fun <R, T> invoke(block: suspend R.() -> T, receiver: R, completion: Continuation<T>) =
Roman Elizarovecda27f2017-04-06 23:06:26 +0300110 when (this) {
Roman Elizarova74eb5f2017-05-11 20:15:18 +0300111 CoroutineStart.DEFAULT -> block.startCoroutineCancellable(receiver, completion)
112 CoroutineStart.ATOMIC -> block.startCoroutine(receiver, completion)
Roman Elizarovecda27f2017-04-06 23:06:26 +0300113 CoroutineStart.UNDISPATCHED -> block.startCoroutineUndispatched(receiver, completion)
114 CoroutineStart.LAZY -> Unit // will start lazily
115 }
116
117 /**
118 * Returns `true` when [LAZY].
119 */
Roman Elizarov23fb7282018-01-24 23:09:42 +0300120 public val isLazy: Boolean get() = this === LAZY
Roman Elizarovecda27f2017-04-06 23:06:26 +0300121}