CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlinx--kotlinx-coroutines-core-iosx64

Kotlin coroutines library providing comprehensive asynchronous programming support with structured concurrency for iOS x64 platforms

Pending
Overview
Eval results
Files

dispatchers.mddocs/

Dispatchers

Execution context control for coroutines including standard dispatchers and custom dispatcher creation. Dispatchers determine which thread or thread pool coroutines execute on.

Capabilities

CoroutineDispatcher Base Class

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
}

Standard Dispatchers

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}")
}

Main Dispatcher

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
}

Custom Dispatchers

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): ExecutorCoroutineDispatcher

Usage 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()
}

Dispatcher Characteristics

Dispatchers.Default

  • Purpose: CPU-intensive computations
  • Thread Pool: Shared pool sized to number of CPU cores
  • Use Cases: Mathematical calculations, data processing, algorithms
  • Avoid: Blocking I/O operations
// 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!
}

Dispatchers.IO

  • Purpose: Blocking I/O operations
  • Thread Pool: Larger pool that can grow as needed
  • Use Cases: File operations, network calls, database access
  • Design: Can handle thread blocking without starving other coroutines
// 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")
}

Dispatchers.Main

  • Purpose: UI thread operations
  • Thread: Single UI thread (platform-specific)
  • Use Cases: UI updates, view modifications
  • Platform: Android, Swing, JavaFX, etc.
// UI updates
withContext(Dispatchers.Main) {
    progressBar.progress = 100
    statusLabel.text = "Complete"
}

Dispatchers.Unconfined

  • Purpose: Special dispatcher that doesn't confine execution
  • Behavior: Starts in caller thread, resumes in whatever thread the suspended function uses
  • Use Cases: Testing, specific performance scenarios
  • Caution: Can lead to unpredictable thread switching
launch(Dispatchers.Unconfined) {
    println("1: ${Thread.currentThread().name}")
    delay(100) // May resume on different thread
    println("2: ${Thread.currentThread().name}")
}

Best Practices

Choose Appropriate Dispatcher

// 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)
}

Avoid Unnecessary Context Switches

// 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()
    }
}

Resource Management

// 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 closed

JVM Integration

CompletableFuture Integration

Coroutines 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(): T

Usage 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()

Thread Context Propagation

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

docs

channels.md

coroutine-builders.md

coroutine-management.md

dispatchers.md

error-handling.md

flow-api.md

index.md

select-expression.md

synchronization.md

tile.json