Kotlin coroutines library providing comprehensive asynchronous programming support with structured concurrency for iOS x64 platforms
—
Execution context control for coroutines including standard dispatchers and custom dispatcher creation. Dispatchers determine which thread or thread pool coroutines execute on.
Abstract base class for all coroutine dispatchers.
/**
* Base class for coroutine dispatchers
*/
abstract class CoroutineDispatcher : ContinuationInterceptor {
/** Dispatch the coroutine to appropriate thread/context */
abstract fun dispatch(context: CoroutineContext, block: Runnable)
/** Check if dispatch is needed for the current context */
open fun isDispatchNeeded(context: CoroutineContext): Boolean = true
/** Create a dispatcher with limited parallelism */
open fun limitedParallelism(parallelism: Int): CoroutineDispatcher
/** Operator overload for withContext-like behavior */
suspend operator fun <T> invoke(block: suspend CoroutineScope.() -> T): T
}Built-in dispatchers for common execution contexts.
/**
* Contains standard coroutine dispatchers
*/
object Dispatchers {
/** Optimized for CPU-intensive work */
val Default: CoroutineDispatcher
/** For UI operations (platform-specific) */
val Main: MainCoroutineDispatcher
/** For blocking I/O operations */
val IO: CoroutineDispatcher
/** Not confined to any specific thread */
val Unconfined: CoroutineDispatcher
}Usage Examples:
import kotlinx.coroutines.*
// CPU-intensive work
val result = withContext(Dispatchers.Default) {
heavyComputation()
}
// I/O operations
val data = withContext(Dispatchers.IO) {
readFile("data.txt")
}
// UI updates (Android/Desktop)
withContext(Dispatchers.Main) {
updateUI(result)
}
// Unconfined execution
launch(Dispatchers.Unconfined) {
// Runs in caller thread until first suspension
println("Start: ${Thread.currentThread().name}")
delay(100)
println("After delay: ${Thread.currentThread().name}")
}Specialized dispatcher for UI thread operations.
/**
* Dispatcher for UI operations
*/
abstract class MainCoroutineDispatcher : CoroutineDispatcher() {
/** Immediate execution if already on main thread */
abstract val immediate: MainCoroutineDispatcher
/** Factory for creating main dispatcher */
companion object {
fun createDispatcher(): MainCoroutineDispatcher
}
}Usage Examples:
// Regular main dispatcher
withContext(Dispatchers.Main) {
updateUI() // May dispatch even if already on main thread
}
// Immediate main dispatcher
withContext(Dispatchers.Main.immediate) {
updateUI() // No dispatch if already on main thread
}Creating custom dispatchers from executors and thread pools.
/**
* Executor-based dispatcher
*/
abstract class ExecutorCoroutineDispatcher : CoroutineDispatcher(), Closeable {
/** The underlying executor */
abstract val executor: Executor
/** Close the dispatcher and shutdown executor */
abstract override fun close()
}
/**
* Convert Executor to CoroutineDispatcher
*/
fun Executor.asCoroutineDispatcher(): ExecutorCoroutineDispatcher
/**
* Convert ExecutorService to CoroutineDispatcher
*/
fun ExecutorService.asCoroutineDispatcher(): ExecutorCoroutineDispatcher
/**
* Convert CoroutineDispatcher to Executor
*/
fun CoroutineDispatcher.asExecutor(): Executor
/**
* Create single-threaded dispatcher
*/
fun newSingleThreadContext(name: String): ExecutorCoroutineDispatcher
/**
* Create fixed thread pool dispatcher
*/
fun newFixedThreadPoolContext(nThreads: Int, name: String): ExecutorCoroutineDispatcherUsage Examples:
import kotlinx.coroutines.*
import java.util.concurrent.*
// Custom thread pool
val customDispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher()
// Use custom dispatcher
val result = withContext(customDispatcher) {
performWork()
}
// Always close custom dispatchers
customDispatcher.close()
// Single thread dispatcher
val singleThreadDispatcher = newSingleThreadContext("MyThread")
try {
launch(singleThreadDispatcher) {
// Runs on dedicated thread "MyThread"
serialProcessing()
}
} finally {
singleThreadDispatcher.close()
}// Good use of Default
val primes = withContext(Dispatchers.Default) {
findPrimesInRange(1..1000000)
}
// Bad use of Default - blocks threads
withContext(Dispatchers.Default) {
Thread.sleep(1000) // Don't do this!
}// File I/O
val content = withContext(Dispatchers.IO) {
File("large-file.txt").readText()
}
// Network calls
val response = withContext(Dispatchers.IO) {
httpClient.get("https://api.example.com/data")
}
// Database operations
val users = withContext(Dispatchers.IO) {
database.query("SELECT * FROM users")
}// UI updates
withContext(Dispatchers.Main) {
progressBar.progress = 100
statusLabel.text = "Complete"
}launch(Dispatchers.Unconfined) {
println("1: ${Thread.currentThread().name}")
delay(100) // May resume on different thread
println("2: ${Thread.currentThread().name}")
}// CPU work
val computed = withContext(Dispatchers.Default) {
expensiveCalculation()
}
// I/O work
val data = withContext(Dispatchers.IO) {
loadFromDatabase()
}
// UI updates
withContext(Dispatchers.Main) {
displayResult(computed, data)
}// Inefficient - multiple context switches
suspend fun processData() {
val data1 = withContext(Dispatchers.IO) { loadData1() }
val data2 = withContext(Dispatchers.IO) { loadData2() }
val data3 = withContext(Dispatchers.IO) { loadData3() }
}
// Better - single context switch
suspend fun processDataEfficient() {
withContext(Dispatchers.IO) {
val data1 = loadData1()
val data2 = loadData2()
val data3 = loadData3()
}
}// Always close custom dispatchers
val customDispatcher = newFixedThreadPoolContext(4, "Custom")
try {
// Use dispatcher
withContext(customDispatcher) {
performWork()
}
} finally {
customDispatcher.close()
}
// Or use 'use' extension
newSingleThreadContext("Worker").use { dispatcher ->
withContext(dispatcher) {
performWork()
}
} // Automatically closedCoroutines can interoperate seamlessly with Java's CompletableFuture.
/**
* Start coroutine and return CompletableFuture
*/
fun <T> CoroutineScope.future(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): CompletableFuture<T>
/**
* Convert Deferred to CompletableFuture
*/
fun <T> Deferred<T>.asCompletableFuture(): CompletableFuture<T>
/**
* Await CompletableFuture completion
*/
suspend fun <T> CompletableFuture<T>.await(): TUsage Examples:
import kotlinx.coroutines.*
import java.util.concurrent.CompletableFuture
// Create CompletableFuture from coroutine
val future: CompletableFuture<String> = GlobalScope.future {
delay(100)
"Hello from coroutine"
}
// Use traditional CompletableFuture API
future.thenAccept { result ->
println(result)
}
// Await Java CompletableFuture in coroutine
suspend fun processJavaFuture() {
val javaFuture: CompletableFuture<String> = CompletableFuture.supplyAsync {
Thread.sleep(100)
"Hello from Java"
}
val result = javaFuture.await()
println(result)
}
// Convert Deferred to CompletableFuture
val deferred = async { computeValue() }
val future = deferred.asCompletableFuture()Support for propagating thread-local variables across coroutine boundaries.
/**
* Element for propagating thread-local data
*/
interface ThreadContextElement<S> : CoroutineContext.Element {
/** Update thread-local state and return previous state */
fun updateThreadContext(context: CoroutineContext): S
/** Restore previous thread-local state */
fun restoreThreadContext(context: CoroutineContext, oldState: S)
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlinx--kotlinx-coroutines-core-iosx64