Coroutines support libraries for Kotlin providing structured concurrency primitives, Flow API for reactive streams, channels for communication, and synchronization utilities across all Kotlin platforms
—
Core building blocks for creating and managing coroutines with structured concurrency guarantees. These provide the foundation for launching concurrent operations and managing their lifecycle.
The fundamental interface that defines a scope for coroutines, providing context inheritance and structured concurrency.
/**
* Defines a scope for new coroutines. Every coroutine builder is an extension
* on CoroutineScope and inherits its coroutineContext to automatically
* propagate all context elements and cancellation.
*/
interface CoroutineScope {
/**
* The context of this scope.
* Context is encapsulated by the scope and used for implementation of coroutine builders.
*/
val coroutineContext: CoroutineContext
}
/**
* Adds the specified coroutine context to this scope, overriding existing elements
* in the current scope's context with the corresponding keys.
*/
operator fun CoroutineScope.plus(context: CoroutineContext): CoroutineScopeCreates and starts a coroutine that doesn't return a result, ideal for fire-and-forget operations.
/**
* Launches a new coroutine without blocking the current thread and returns
* a reference to the coroutine as a Job. The coroutine is cancelled when
* the resulting job is cancelled.
*
* @param context additional to CoroutineScope.coroutineContext context of the coroutine
* @param start coroutine start option. The default value is CoroutineStart.DEFAULT
* @param block the coroutine code which will be invoked in the context of the provided scope
*/
fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): JobUsage Examples:
import kotlinx.coroutines.*
val scope = MainScope()
// Basic launch
val job = scope.launch {
delay(1000)
println("Task completed!")
}
// Launch with custom context
val job2 = scope.launch(Dispatchers.IO) {
// Perform I/O operations
println("Running on IO dispatcher")
}
// Launch with lazy start
val lazyJob = scope.launch(start = CoroutineStart.LAZY) {
println("This won't run until started")
}
lazyJob.start() // Explicitly start the lazy coroutine
// Launch with custom name for debugging
val namedJob = scope.launch(CoroutineName("DataProcessor")) {
println("Processing data...")
}Creates a coroutine that computes and returns a result, returning a Deferred that can be awaited.
/**
* Creates a coroutine and returns its future result as an implementation of Deferred.
* The running coroutine is cancelled when the resulting deferred is cancelled.
*
* @param context additional to CoroutineScope.coroutineContext context of the coroutine
* @param start coroutine start option. The default value is CoroutineStart.DEFAULT
* @param block the coroutine code
*/
fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T>Usage Examples:
import kotlinx.coroutines.*
val scope = MainScope()
// Basic async operation
val deferred = scope.async {
delay(1000)
"Hello from async!"
}
scope.launch {
val result = deferred.await()
println(result) // Prints: Hello from async!
}
// Multiple concurrent operations
val results = scope.async {
val task1 = async { computeTask1() }
val task2 = async { computeTask2() }
val task3 = async { computeTask3() }
// Wait for all tasks to complete
listOf(task1.await(), task2.await(), task3.await())
}
// Async with error handling
val deferredWithErrorHandling = scope.async {
try {
riskyOperation()
} catch (e: Exception) {
"Fallback result"
}
}Functions for creating new coroutine scopes with specific configurations.
/**
* Creates a CoroutineScope that wraps the given coroutine context.
* If the given context does not contain a Job element, then a default Job() is created.
*
* @param context the coroutine context for the new scope
*/
fun CoroutineScope(context: CoroutineContext): CoroutineScope
/**
* Creates a CoroutineScope for main thread operations.
* Uses Dispatchers.Main for its coroutines and has a SupervisorJob.
*/
fun MainScope(): CoroutineScopeUsage Examples:
import kotlinx.coroutines.*
// Create a scope with custom context
val customScope = CoroutineScope(Dispatchers.Default + CoroutineName("MyScope"))
// Create a main scope for UI operations
val mainScope = MainScope()
// Create a scope with supervisor job (failures don't cancel siblings)
val supervisorScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
// Remember to cancel scopes when done
class MyClass {
private val scope = MainScope()
fun cleanup() {
scope.cancel()
}
}A global coroutine scope not bound to any job (use with extreme caution).
/**
* A global CoroutineScope not bound to any job.
*
* Global scope is used to launch top-level coroutines which are operating on the
* whole application lifetime and are not cancelled prematurely.
*
* Application code usually should use an application-defined CoroutineScope,
* using async or launch on the instance of GlobalScope is highly discouraged.
*/
object GlobalScope : CoroutineScopeWarning: GlobalScope should be used sparingly as it can lead to resource leaks and makes testing difficult.
Convenience functions for waiting on multiple coroutines.
/**
* Awaits for completion of given deferred values without blocking a thread
* and returns a list of resulting values.
*/
suspend fun <T> awaitAll(vararg deferreds: Deferred<T>): List<T>
/**
* Suspends current coroutine until all given jobs are complete.
*/
suspend fun joinAll(vararg jobs: Job)Usage Examples:
import kotlinx.coroutines.*
val scope = MainScope()
scope.launch {
// Wait for multiple async operations
val task1 = async { fetchUserData() }
val task2 = async { fetchUserPosts() }
val task3 = async { fetchUserSettings() }
val results = awaitAll(task1, task2, task3)
val (userData, userPosts, userSettings) = results
// Process combined results
displayUserProfile(userData, userPosts, userSettings)
}
scope.launch {
// Wait for multiple jobs to complete
val job1 = launch { updateDatabase() }
val job2 = launch { clearCache() }
val job3 = launch { notifyUsers() }
joinAll(job1, job2, job3)
println("All maintenance tasks completed!")
}/**
* Defines start options for coroutines builders.
*/
enum class CoroutineStart {
/**
* Default -- immediately schedules coroutine for execution according to its context.
*/
DEFAULT,
/**
* Lazily -- starts coroutine lazily, only when it is needed.
*/
LAZY,
/**
* Atomically -- atomically (in a non-cancellable way) schedules coroutine for execution.
*/
ATOMIC,
/**
* Immediately executes coroutine until its first suspension point in the current thread.
*/
UNDISPATCHED
}Usage Examples:
import kotlinx.coroutines.*
val scope = MainScope()
// Lazy start - coroutine won't run until explicitly started
val lazyJob = scope.launch(start = CoroutineStart.LAZY) {
println("This runs only when explicitly started")
}
// Later...
lazyJob.start()
// ATOMIC start - cannot be cancelled before first suspension
val atomicJob = scope.launch(start = CoroutineStart.ATOMIC) {
println("This will definitely print even if cancelled immediately")
delay(100) // First suspension point - cancellation can happen after this
}
// UNDISPATCHED - runs immediately in current thread until first suspension
val undispatchedJob = scope.launch(start = CoroutineStart.UNDISPATCHED) {
println("This runs immediately in current thread")
delay(100) // Will be dispatched according to context after this suspension
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlinx--kotlinx-coroutines-core