blob: ccd89f8f2dfae0b1d22042043b8f88e89eb8daea [file] [log] [blame]
Roman Elizarova7db8ec2017-12-21 22:45:12 +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
Roman Elizarove1c0b652017-12-01 14:02:57 +030017package kotlinx.coroutines.experimental
18
19import kotlinx.coroutines.experimental.intrinsics.startCoroutineUndispatched
20import kotlin.coroutines.experimental.Continuation
21import kotlin.coroutines.experimental.startCoroutine
22
23/**
24 * Defines start option for coroutines builders.
25 * It is used in `start` parameter of [launch], [async], and [actor][kotlinx.coroutines.experimental.channels.actor]
26 * coroutine builder functions.
27 *
28 * The summary of coroutine start options is:
29 * * [DEFAULT] -- immediately schedules coroutine for execution according to its context;
30 * * [LAZY] -- starts coroutine lazily, only when it is needed;
31 * * [ATOMIC] -- atomically (non-cancellably) schedules coroutine for execution according to its context;
32 * * [UNDISPATCHED] -- immediately executes coroutine until its first suspension point _in the current thread_.
33 */
34public actual enum class CoroutineStart {
35 /**
36 * Default -- immediately schedules coroutine for execution according to its context.
37 *
38 * If the [CoroutineDispatcher] of the coroutine context returns `true` from [CoroutineDispatcher.isDispatchNeeded]
39 * function as most dispatchers do, then the coroutine code is dispatched for execution later, while the code that
40 * invoked the coroutine builder continues execution.
41 *
42 * Note, that [Unconfined] dispatcher always returns `false` from its [CoroutineDispatcher.isDispatchNeeded]
43 * function, so starting coroutine with [Unconfined] dispatcher by [DEFAULT] is the same as using [UNDISPATCHED].
44 *
45 * If coroutine [Job] is cancelled before it even had a chance to start executing, then it will not start its
46 * execution at all, but complete with an exception.
47 *
48 * Cancellability of coroutine at suspension points depends on the particular implementation details of
49 * suspending functions. Use [suspendCancellableCoroutine] to implement cancellable suspending functions.
50 */
51 DEFAULT,
52
53 /**
54 * Starts coroutine lazily, only when it is needed.
55 *
56 * See the documentation for the corresponding coroutine builders for details:
57 * [launch], [async], and [actor][kotlinx.coroutines.experimental.channels.actor].
58 *
59 * If coroutine [Job] is cancelled before it even had a chance to start executing, then it will not start its
60 * execution at all, but complete with an exception.
61 */
62 LAZY,
63
64 /**
65 * Atomically (non-cancellably) schedules coroutine for execution according to its context.
66 * This is similar to [DEFAULT], but the coroutine cannot be cancelled before it starts executing.
67 *
68 * Cancellability of coroutine at suspension points depends on the particular implementation details of
69 * suspending functions as in [DEFAULT].
70 */
71 ATOMIC,
72
73 /**
74 * Immediately executes coroutine until its first suspension point _in the current thread_ as if it the
75 * coroutine was started using [Unconfined] dispatcher. However, when coroutine is resumed from suspension
76 * it is dispatched according to the [CoroutineDispatcher] in its context.
77 *
78 * This is similar to [ATOMIC] in the sense that coroutine starts executing even if it was already cancelled,
79 * but the difference is that it start executing in the same thread.
80 *
81 * Cancellability of coroutine at suspension points depends on the particular implementation details of
82 * suspending functions as in [DEFAULT].
83 */
84 UNDISPATCHED;
85
86 /**
87 * Starts the corresponding block as a coroutine with this coroutine start strategy.
88 *
89 * * [DEFAULT] uses [startCoroutineCancellable].
90 * * [ATOMIC] uses [startCoroutine].
91 * * [UNDISPATCHED] uses [startCoroutineUndispatched].
92 * * [LAZY] does nothing.
93 */
94 public actual operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>) =
95 when (this) {
96 CoroutineStart.DEFAULT -> block.startCoroutineCancellable(completion)
97 CoroutineStart.ATOMIC -> block.startCoroutine(completion)
98 CoroutineStart.UNDISPATCHED -> block.startCoroutineUndispatched(completion)
99 CoroutineStart.LAZY -> Unit // will start lazily
100 }
101
102 /**
103 * Starts the corresponding block with receiver as a coroutine with this coroutine start strategy.
104 *
105 * * [DEFAULT] uses [startCoroutineCancellable].
106 * * [ATOMIC] uses [startCoroutine].
107 * * [UNDISPATCHED] uses [startCoroutineUndispatched].
108 * * [LAZY] does nothing.
109 */
110 public actual operator fun <R, T> invoke(block: suspend R.() -> T, receiver: R, completion: Continuation<T>) =
111 when (this) {
112 CoroutineStart.DEFAULT -> block.startCoroutineCancellable(receiver, completion)
113 CoroutineStart.ATOMIC -> block.startCoroutine(receiver, completion)
114 CoroutineStart.UNDISPATCHED -> block.startCoroutineUndispatched(receiver, completion)
115 CoroutineStart.LAZY -> Unit // will start lazily
116 }
117
118 /**
119 * Returns `true` when [LAZY].
120 */
121 public actual val isLazy: Boolean get() = this === LAZY
122}