0
# Coroutine Builders and Scopes
1
2
Core building blocks for creating and managing coroutines with structured concurrency guarantees. These provide the foundation for launching concurrent operations and managing their lifecycle.
3
4
## Capabilities
5
6
### CoroutineScope Interface
7
8
The fundamental interface that defines a scope for coroutines, providing context inheritance and structured concurrency.
9
10
```kotlin { .api }
11
/**
12
* Defines a scope for new coroutines. Every coroutine builder is an extension
13
* on CoroutineScope and inherits its coroutineContext to automatically
14
* propagate all context elements and cancellation.
15
*/
16
interface CoroutineScope {
17
/**
18
* The context of this scope.
19
* Context is encapsulated by the scope and used for implementation of coroutine builders.
20
*/
21
val coroutineContext: CoroutineContext
22
}
23
24
/**
25
* Adds the specified coroutine context to this scope, overriding existing elements
26
* in the current scope's context with the corresponding keys.
27
*/
28
operator fun CoroutineScope.plus(context: CoroutineContext): CoroutineScope
29
```
30
31
### Launch Builder
32
33
Creates and starts a coroutine that doesn't return a result, ideal for fire-and-forget operations.
34
35
```kotlin { .api }
36
/**
37
* Launches a new coroutine without blocking the current thread and returns
38
* a reference to the coroutine as a Job. The coroutine is cancelled when
39
* the resulting job is cancelled.
40
*
41
* @param context additional to CoroutineScope.coroutineContext context of the coroutine
42
* @param start coroutine start option. The default value is CoroutineStart.DEFAULT
43
* @param block the coroutine code which will be invoked in the context of the provided scope
44
*/
45
fun CoroutineScope.launch(
46
context: CoroutineContext = EmptyCoroutineContext,
47
start: CoroutineStart = CoroutineStart.DEFAULT,
48
block: suspend CoroutineScope.() -> Unit
49
): Job
50
```
51
52
**Usage Examples:**
53
54
```kotlin
55
import kotlinx.coroutines.*
56
57
val scope = MainScope()
58
59
// Basic launch
60
val job = scope.launch {
61
delay(1000)
62
println("Task completed!")
63
}
64
65
// Launch with custom context
66
val job2 = scope.launch(Dispatchers.IO) {
67
// Perform I/O operations
68
println("Running on IO dispatcher")
69
}
70
71
// Launch with lazy start
72
val lazyJob = scope.launch(start = CoroutineStart.LAZY) {
73
println("This won't run until started")
74
}
75
lazyJob.start() // Explicitly start the lazy coroutine
76
77
// Launch with custom name for debugging
78
val namedJob = scope.launch(CoroutineName("DataProcessor")) {
79
println("Processing data...")
80
}
81
```
82
83
### Async Builder
84
85
Creates a coroutine that computes and returns a result, returning a Deferred that can be awaited.
86
87
```kotlin { .api }
88
/**
89
* Creates a coroutine and returns its future result as an implementation of Deferred.
90
* The running coroutine is cancelled when the resulting deferred is cancelled.
91
*
92
* @param context additional to CoroutineScope.coroutineContext context of the coroutine
93
* @param start coroutine start option. The default value is CoroutineStart.DEFAULT
94
* @param block the coroutine code
95
*/
96
fun <T> CoroutineScope.async(
97
context: CoroutineContext = EmptyCoroutineContext,
98
start: CoroutineStart = CoroutineStart.DEFAULT,
99
block: suspend CoroutineScope.() -> T
100
): Deferred<T>
101
```
102
103
**Usage Examples:**
104
105
```kotlin
106
import kotlinx.coroutines.*
107
108
val scope = MainScope()
109
110
// Basic async operation
111
val deferred = scope.async {
112
delay(1000)
113
"Hello from async!"
114
}
115
116
scope.launch {
117
val result = deferred.await()
118
println(result) // Prints: Hello from async!
119
}
120
121
// Multiple concurrent operations
122
val results = scope.async {
123
val task1 = async { computeTask1() }
124
val task2 = async { computeTask2() }
125
val task3 = async { computeTask3() }
126
127
// Wait for all tasks to complete
128
listOf(task1.await(), task2.await(), task3.await())
129
}
130
131
// Async with error handling
132
val deferredWithErrorHandling = scope.async {
133
try {
134
riskyOperation()
135
} catch (e: Exception) {
136
"Fallback result"
137
}
138
}
139
```
140
141
### Scope Factory Functions
142
143
Functions for creating new coroutine scopes with specific configurations.
144
145
```kotlin { .api }
146
/**
147
* Creates a CoroutineScope that wraps the given coroutine context.
148
* If the given context does not contain a Job element, then a default Job() is created.
149
*
150
* @param context the coroutine context for the new scope
151
*/
152
fun CoroutineScope(context: CoroutineContext): CoroutineScope
153
154
/**
155
* Creates a CoroutineScope for main thread operations.
156
* Uses Dispatchers.Main for its coroutines and has a SupervisorJob.
157
*/
158
fun MainScope(): CoroutineScope
159
```
160
161
**Usage Examples:**
162
163
```kotlin
164
import kotlinx.coroutines.*
165
166
// Create a scope with custom context
167
val customScope = CoroutineScope(Dispatchers.Default + CoroutineName("MyScope"))
168
169
// Create a main scope for UI operations
170
val mainScope = MainScope()
171
172
// Create a scope with supervisor job (failures don't cancel siblings)
173
val supervisorScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
174
175
// Remember to cancel scopes when done
176
class MyClass {
177
private val scope = MainScope()
178
179
fun cleanup() {
180
scope.cancel()
181
}
182
}
183
```
184
185
### GlobalScope
186
187
A global coroutine scope not bound to any job (use with extreme caution).
188
189
```kotlin { .api }
190
/**
191
* A global CoroutineScope not bound to any job.
192
*
193
* Global scope is used to launch top-level coroutines which are operating on the
194
* whole application lifetime and are not cancelled prematurely.
195
*
196
* Application code usually should use an application-defined CoroutineScope,
197
* using async or launch on the instance of GlobalScope is highly discouraged.
198
*/
199
object GlobalScope : CoroutineScope
200
```
201
202
**Warning:** GlobalScope should be used sparingly as it can lead to resource leaks and makes testing difficult.
203
204
### Await Utility Functions
205
206
Convenience functions for waiting on multiple coroutines.
207
208
```kotlin { .api }
209
/**
210
* Awaits for completion of given deferred values without blocking a thread
211
* and returns a list of resulting values.
212
*/
213
suspend fun <T> awaitAll(vararg deferreds: Deferred<T>): List<T>
214
215
/**
216
* Suspends current coroutine until all given jobs are complete.
217
*/
218
suspend fun joinAll(vararg jobs: Job)
219
```
220
221
**Usage Examples:**
222
223
```kotlin
224
import kotlinx.coroutines.*
225
226
val scope = MainScope()
227
228
scope.launch {
229
// Wait for multiple async operations
230
val task1 = async { fetchUserData() }
231
val task2 = async { fetchUserPosts() }
232
val task3 = async { fetchUserSettings() }
233
234
val results = awaitAll(task1, task2, task3)
235
val (userData, userPosts, userSettings) = results
236
237
// Process combined results
238
displayUserProfile(userData, userPosts, userSettings)
239
}
240
241
scope.launch {
242
// Wait for multiple jobs to complete
243
val job1 = launch { updateDatabase() }
244
val job2 = launch { clearCache() }
245
val job3 = launch { notifyUsers() }
246
247
joinAll(job1, job2, job3)
248
println("All maintenance tasks completed!")
249
}
250
```
251
252
## Coroutine Start Options
253
254
```kotlin { .api }
255
/**
256
* Defines start options for coroutines builders.
257
*/
258
enum class CoroutineStart {
259
/**
260
* Default -- immediately schedules coroutine for execution according to its context.
261
*/
262
DEFAULT,
263
264
/**
265
* Lazily -- starts coroutine lazily, only when it is needed.
266
*/
267
LAZY,
268
269
/**
270
* Atomically -- atomically (in a non-cancellable way) schedules coroutine for execution.
271
*/
272
ATOMIC,
273
274
/**
275
* Immediately executes coroutine until its first suspension point in the current thread.
276
*/
277
UNDISPATCHED
278
}
279
```
280
281
**Usage Examples:**
282
283
```kotlin
284
import kotlinx.coroutines.*
285
286
val scope = MainScope()
287
288
// Lazy start - coroutine won't run until explicitly started
289
val lazyJob = scope.launch(start = CoroutineStart.LAZY) {
290
println("This runs only when explicitly started")
291
}
292
// Later...
293
lazyJob.start()
294
295
// ATOMIC start - cannot be cancelled before first suspension
296
val atomicJob = scope.launch(start = CoroutineStart.ATOMIC) {
297
println("This will definitely print even if cancelled immediately")
298
delay(100) // First suspension point - cancellation can happen after this
299
}
300
301
// UNDISPATCHED - runs immediately in current thread until first suspension
302
val undispatchedJob = scope.launch(start = CoroutineStart.UNDISPATCHED) {
303
println("This runs immediately in current thread")
304
delay(100) // Will be dispatched according to context after this suspension
305
}
306
```