or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

channels.mdcoroutine-builders.mdcoroutine-management.mddispatchers.mderror-handling.mdflow-api.mdindex.mdselect-expression.mdsynchronization.md

coroutine-builders.mddocs/

0

# Coroutine Builders

1

2

Functions for creating and launching coroutines with different execution patterns and result handling. These builders provide the primary means of starting concurrent operations within coroutine scopes.

3

4

## Capabilities

5

6

### Launch Builder

7

8

Fire-and-forget coroutine that returns a Job for lifecycle management.

9

10

```kotlin { .api }

11

/**

12

* Launches a new coroutine without blocking the current thread

13

* @param context additional context elements for the coroutine

14

* @param start coroutine start option (DEFAULT, LAZY, ATOMIC, UNDISPATCHED)

15

* @param block the coroutine code

16

* @return Job representing the coroutine

17

*/

18

fun CoroutineScope.launch(

19

context: CoroutineContext = EmptyCoroutineContext,

20

start: CoroutineStart = CoroutineStart.DEFAULT,

21

block: suspend CoroutineScope.() -> Unit

22

): Job

23

```

24

25

**Usage Examples:**

26

27

```kotlin

28

import kotlinx.coroutines.*

29

30

val scope = CoroutineScope(Dispatchers.Default)

31

32

// Basic launch

33

val job = scope.launch {

34

delay(1000)

35

println("Task completed")

36

}

37

38

// Launch with custom context

39

val jobWithContext = scope.launch(Dispatchers.IO + CoroutineName("file-processor")) {

40

// Runs on IO dispatcher with debug name

41

processFile()

42

}

43

44

// Lazy launch (starts when job.start() is called or join() is awaited)

45

val lazyJob = scope.launch(start = CoroutineStart.LAZY) {

46

expensiveComputation()

47

}

48

lazyJob.start() // Explicitly start the coroutine

49

50

// Wait for completion

51

job.join()

52

```

53

54

### Async Builder

55

56

Concurrent computation that returns a Deferred with a result value.

57

58

```kotlin { .api }

59

/**

60

* Creates a coroutine that computes a value concurrently

61

* @param context additional context elements for the coroutine

62

* @param start coroutine start option

63

* @param block the coroutine code that returns a value

64

* @return Deferred representing the future result

65

*/

66

fun <T> CoroutineScope.async(

67

context: CoroutineContext = EmptyCoroutineContext,

68

start: CoroutineStart = CoroutineStart.DEFAULT,

69

block: suspend CoroutineScope.() -> T

70

): Deferred<T>

71

```

72

73

**Usage Examples:**

74

75

```kotlin

76

import kotlinx.coroutines.*

77

78

suspend fun concurrentComputation() {

79

val scope = CoroutineScope(Dispatchers.Default)

80

81

// Launch multiple async computations

82

val deferred1 = scope.async { computeValue1() }

83

val deferred2 = scope.async { computeValue2() }

84

val deferred3 = scope.async { computeValue3() }

85

86

// Wait for all results

87

val result1 = deferred1.await()

88

val result2 = deferred2.await()

89

val result3 = deferred3.await()

90

91

println("Results: $result1, $result2, $result3")

92

}

93

94

// Async with custom context

95

suspend fun asyncWithContext() = coroutineScope {

96

val networkCall = async(Dispatchers.IO) {

97

fetchDataFromNetwork()

98

}

99

100

val localData = async(Dispatchers.Default) {

101

processLocalData()

102

}

103

104

// Combine results

105

CombinedResult(networkCall.await(), localData.await())

106

}

107

```

108

109

### WithContext

110

111

Context switching function that executes a block in a different context and returns the result.

112

113

```kotlin { .api }

114

/**

115

* Calls the specified block with the given coroutine context

116

* @param context the new context for the block

117

* @param block the code to execute in the new context

118

* @return the result of the block

119

*/

120

suspend fun <T> withContext(

121

context: CoroutineContext,

122

block: suspend CoroutineScope.() -> T

123

): T

124

```

125

126

**Usage Examples:**

127

128

```kotlin

129

import kotlinx.coroutines.*

130

131

suspend fun processData() {

132

// Switch to IO context for file operations

133

val fileContent = withContext(Dispatchers.IO) {

134

readFileContent("data.txt")

135

}

136

137

// Switch to Default context for computation

138

val processedData = withContext(Dispatchers.Default) {

139

heavyProcessing(fileContent)

140

}

141

142

// Switch to Main context for UI updates (if available)

143

withContext(Dispatchers.Main) {

144

updateUI(processedData)

145

}

146

}

147

148

// WithContext with timeout

149

suspend fun fetchWithTimeout() {

150

val result = withContext(Dispatchers.IO) {

151

withTimeout(5000) {

152

fetchDataFromServer()

153

}

154

}

155

return result

156

}

157

```

158

159

### RunBlocking

160

161

Blocking bridge between regular and suspend functions (platform-specific availability).

162

163

```kotlin { .api }

164

/**

165

* Runs a new coroutine and blocks the current thread until completion

166

* @param context the context for the new coroutine

167

* @param block the coroutine code

168

* @return the result of the coroutine

169

*/

170

fun <T> runBlocking(

171

context: CoroutineContext = EmptyCoroutineContext,

172

block: suspend CoroutineScope.() -> T

173

): T

174

```

175

176

**Usage Examples:**

177

178

```kotlin

179

import kotlinx.coroutines.*

180

181

// In main function or tests

182

fun main() = runBlocking {

183

launch {

184

delay(1000)

185

println("World!")

186

}

187

println("Hello,")

188

delay(2000)

189

}

190

191

// In tests

192

@Test

193

fun testCoroutine() = runBlocking {

194

val result = async { computeAsync() }

195

assertEquals(42, result.await())

196

}

197

198

// Bridge to suspend functions

199

fun synchronousFunction(): String {

200

return runBlocking {

201

suspendingFunction()

202

}

203

}

204

```

205

206

### Producer (Channel Builder)

207

208

Creates a receive channel from a coroutine that produces values.

209

210

```kotlin { .api }

211

/**

212

* Creates a coroutine that produces values and sends them to a channel

213

* @param context additional context elements

214

* @param capacity channel capacity

215

* @param block the producer coroutine code

216

* @return ReceiveChannel to consume produced values

217

*/

218

fun <E> CoroutineScope.produce(

219

context: CoroutineContext = EmptyCoroutineContext,

220

capacity: Int = 0,

221

block: suspend ProducerScope<E>.() -> Unit

222

): ReceiveChannel<E>

223

224

/**

225

* Scope for the producer coroutine

226

*/

227

interface ProducerScope<in E> : CoroutineScope, SendChannel<E>

228

```

229

230

**Usage Examples:**

231

232

```kotlin

233

import kotlinx.coroutines.*

234

import kotlinx.coroutines.channels.*

235

236

suspend fun numberProducer() {

237

val numbers = produce {

238

for (i in 1..10) {

239

send(i * i) // Send squares

240

delay(100) // Simulate work

241

}

242

}

243

244

// Consume the numbers

245

for (number in numbers) {

246

println("Received: $number")

247

}

248

}

249

250

// Producer with custom capacity

251

suspend fun bufferedProducer() {

252

val channel = produce(capacity = 5) {

253

repeat(20) { i ->

254

send("Item $i")

255

println("Sent item $i")

256

}

257

}

258

259

// Consumer can lag behind due to buffering

260

for (item in channel) {

261

delay(200) // Slow consumer

262

println("Received: $item")

263

}

264

}

265

```

266

267

### CoroutineStart Options

268

269

Configuration for how coroutines are started.

270

271

```kotlin { .api }

272

/**

273

* Defines options for starting coroutines

274

*/

275

enum class CoroutineStart {

276

/** Start coroutine immediately in the current thread until first suspension */

277

DEFAULT,

278

/** Start coroutine lazily when start() or join() is called */

279

LAZY,

280

/** Start coroutine atomically - cannot be cancelled until it starts */

281

ATOMIC,

282

/** Start coroutine immediately in the current thread */

283

UNDISPATCHED

284

}

285

```

286

287

**Usage Examples:**

288

289

```kotlin

290

import kotlinx.coroutines.*

291

292

suspend fun startOptions() = coroutineScope {

293

// Default: scheduled immediately, suspends at first suspension point

294

val defaultJob = launch(start = CoroutineStart.DEFAULT) {

295

delay(100)

296

println("Default started")

297

}

298

299

// Lazy: doesn't start until explicitly started

300

val lazyJob = launch(start = CoroutineStart.LAZY) {

301

println("Lazy started")

302

}

303

304

// Atomic: cannot be cancelled before it starts running

305

val atomicJob = launch(start = CoroutineStart.ATOMIC) {

306

println("Atomic started")

307

}

308

309

// Undispatched: runs immediately in current thread until first suspension

310

val undispatchedJob = launch(start = CoroutineStart.UNDISPATCHED) {

311

println("Undispatched runs immediately")

312

delay(1) // Now it gets dispatched

313

println("After suspension")

314

}

315

316

// Start the lazy job

317

lazyJob.start()

318

319

// Wait for all

320

joinAll(defaultJob, lazyJob, atomicJob, undispatchedJob)

321

}

322

```

323

324

## Builder Comparison

325

326

| Builder | Returns | Use Case | Blocking |

327

|---------|---------|----------|----------|

328

| `launch` | `Job` | Fire-and-forget operations | No |

329

| `async` | `Deferred<T>` | Concurrent computations with results | No |

330

| `withContext` | `T` | Context switching with result | Suspending |

331

| `runBlocking` | `T` | Bridge to blocking code | Yes |

332

| `produce` | `ReceiveChannel<E>` | Value production over time | No |

333

334

## Exception Handling in Builders

335

336

Different builders handle exceptions differently:

337

338

- **launch**: Exceptions are handled by the parent's exception handler or crash the application

339

- **async**: Exceptions are stored in the Deferred and re-thrown when `await()` is called

340

- **withContext**: Exceptions propagate directly to the caller

341

- **runBlocking**: Exceptions propagate to the calling thread

342

- **produce**: Exceptions close the channel and propagate to consumers

343

344

This makes `async` safe for operations that might fail, as exceptions don't crash the parent scope until explicitly checked with `await()`.