Package-level declarations

Public API of the runtime toolkit.

Helpers that run inside an existing coroutine respect structured concurrency: they never launch into a scope the caller does not own, they let CancellationException propagate, and anything they start finishes before they return. Diagnostic types (tracing, metrics, signals) are opt-in and have no effect unless they are wired in explicitly.

Public API of the runtime toolkit.

Helpers that run inside an existing coroutine respect structured concurrency: they never launch into a scope the caller does not own, they let CancellationException propagate, and anything they start finishes before they return. Diagnostic types (tracing, metrics, signals) are opt-in and have no effect unless they are wired in explicitly.

Public API of the runtime toolkit.

Helpers that run inside an existing coroutine respect structured concurrency: they never launch into a scope the caller does not own, they let CancellationException propagate, and anything they start finishes before they return. Diagnostic types (tracing, metrics, signals) are opt-in and have no effect unless they are wired in explicitly.

Public API of the runtime toolkit.

Helpers that run inside an existing coroutine respect structured concurrency: they never launch into a scope the caller does not own, they let CancellationException propagate, and anything they start finishes before they return. Diagnostic types (tracing, metrics, signals) are opt-in and have no effect unless they are wired in explicitly.

Public API of the runtime toolkit.

Helpers that run inside an existing coroutine respect structured concurrency: they never launch into a scope the caller does not own, they let CancellationException propagate, and anything they start finishes before they return. Diagnostic types (tracing, metrics, signals) are opt-in and have no effect unless they are wired in explicitly.

Public API of the runtime toolkit.

Helpers that run inside an existing coroutine respect structured concurrency: they never launch into a scope the caller does not own, they let CancellationException propagate, and anything they start finishes before they return. Diagnostic types (tracing, metrics, signals) are opt-in and have no effect unless they are wired in explicitly.

Public API of the runtime toolkit.

Helpers that run inside an existing coroutine respect structured concurrency: they never launch into a scope the caller does not own, they let CancellationException propagate, and anything they start finishes before they return. Diagnostic types (tracing, metrics, signals) are opt-in and have no effect unless they are wired in explicitly.

Public API of the runtime toolkit.

Helpers that run inside an existing coroutine respect structured concurrency: they never launch into a scope the caller does not own, they let CancellationException propagate, and anything they start finishes before they return. Diagnostic types (tracing, metrics, signals) are opt-in and have no effect unless they are wired in explicitly.

Types

Link copied to clipboard
@ExperimentalStructuredCoroutines
class AndroidTraceSink(maxLevel: TraceLevel = TraceLevel.Coroutine) : TraceSink

A TraceSink that writes dispatch activity to the Android system trace (android.os.Trace), so it shows up in Perfetto, Android Studio's system trace and Macrobenchmark TraceSectionMetric.

Link copied to clipboard

Fans every event out to several sinks. Enabled for a level when any sink is. Each sink is called in isolation: an Exception from one does not stop the others (VM errors propagate). Only sinks enabled for the event's level receive it.

Link copied to clipboard

Immutable snapshot of what a StatsSink observed for one dispatcher label. A plain final class with explicit equals/hashCode/toString so fields can be added later without breaking binary compatibility.

Link copied to clipboard

Abstraction over the four standard dispatchers, meant to be injected into classes instead of hardcoding Dispatchers.* so tests can swap in a test dispatcher with virtual time.

Link copied to clipboard
data class DispatcherStats(val label: String, val totalDispatched: Long, val peakConcurrency: Int, val maxQueueDelay: Duration)

Immutable snapshot of what an InstrumentedDispatcher observed.

Link copied to clipboard
class EventChannel<T>(capacity: Int = Channel.BUFFERED, onUndeliveredElement: (T) -> Unit? = null)

One-shot events (navigation, snackbars) that must not be lost when nobody is collecting yet and must be handled once. Backed by a Channel with a buffer, per FLOW_011 (a default MutableSharedFlow with replay = 0 drops events emitted before a collector attaches).

Link copied to clipboard
@RequiresOptIn(level = RequiresOptIn.Level.WARNING, message = "This structured-coroutines runtime API is experimental and may change or be removed without notice while :runtime is on the 0.x line.")
annotation class ExperimentalStructuredCoroutines

Marks declarations in the :runtime optional companion library that are still experimental.

Link copied to clipboard

Immutable view of a latency distribution captured from a histogram.

Link copied to clipboard

A CoroutineDispatcher that wraps delegate and records how many blocks were dispatched, how many ran concurrently at peak, and the longest queue delay (dispatch to block start). Useful to detect saturated dispatchers while diagnosing slow or starved coroutines.

Link copied to clipboard

A DispatcherProvider whose main, io and default dispatchers are InstrumentedDispatchers, created by instrumented. unconfined is returned unwrapped: it never queues work, so its counters would always read zero, and yield() on a wrapped one would count a dispatch that never starts.

Link copied to clipboard
class LoggingSink(val maxLevel: TraceLevel = TraceLevel.Dispatch, log: (String) -> Unit) : TraceSink

Writes each event as one human-readable line (its toString) to log. Never throws: an Exception from log is swallowed so logging cannot break dispatch.

Link copied to clipboard

Periodically turns the cumulative state of a StatsSink into TraceEvent.PoolSamples so a pool can be watched over time. One sample is emitted per dispatcher label that stats knows.

Link copied to clipboard

A heuristic hint derived from DispatcherMetrics. Sealed so more signals can be added later. Signals are hints, not proof: they say where to look, not what is wrong.

Link copied to clipboard
class RingBufferSink(val capacity: Int, val maxLevel: TraceLevel = TraceLevel.Pool) : TraceSink

Keeps the last capacity events, for tests, crash reports and ad-hoc export.

Link copied to clipboard
class SignalThresholds(val starvationQueueDelayP95: Duration = 50.milliseconds, val longRunningSegment: Duration = 100.milliseconds)

Thresholds used by signals to turn DispatcherMetrics into PoolSignals. Plain final class with explicit equals/hashCode/toString so options can be added later.

Link copied to clipboard

Holds a piece of UI/domain state and exposes it read-only, implementing the FLOW_010 backing property pattern: the MutableStateFlow is private, so external code can only change state through set and update.

Link copied to clipboard
class StatsSink(val maxLevel: TraceLevel = TraceLevel.Coroutine) : TraceSink

A TraceSink that aggregates events into per-dispatcher DispatcherMetrics: counters, running and peak concurrency, queue-delay and run-time histograms, failures and distinct threads.

Link copied to clipboard

Identity of a platform thread. A plain final class (not a data class) so fields can be added later without a binary-incompatible copy/componentN change.

Link copied to clipboard
class TraceCapabilities(val threadIdentity: Boolean, val systemTraceIntegration: Boolean, val counters: Boolean, val flows: Boolean)

What the current target can do for tracing out of the box, as shipped in :runtime. This is the extension seam for new platforms: a target compiles and works with every flag false, and gains fidelity when someone writes its actual of platformCapabilities and platformTraceSink.

Link copied to clipboard

A DispatcherProvider whose main, io and default dispatchers are TracingDispatchers reporting to sink, created by traced. unconfined is returned unwrapped: tracing it is pointless (it never queues) and would leave dangling TraceEvent.Queued events on yield().

Link copied to clipboard

An observation emitted to a TraceSink. Sealed so subtypes can be added later; sinks must ignore subtypes they do not know.

Link copied to clipboard

How much detail a TraceSink wants to receive. Levels are cumulative by ordinal: enabling a level also enables every level below it, so level <= maxLevel is the enablement test.

Link copied to clipboard

How a traced block ended.

Link copied to clipboard

Port that receives TraceEvents. Backends (logging, ring buffers, platform tracers) implement it.

Link copied to clipboard

A unit of traced work, carried in the coroutine context. TracingDispatcher reads it from the context of every dispatch and attaches id, parentId and name to the run events, so a backend can draw parent-child links and show the span label.

Link copied to clipboard

A CoroutineDispatcher that wraps delegate and emits a TraceEvent.Queued, TraceEvent.Started and TraceEvent.Finished event to sink for every block dispatched through it. label identifies this dispatcher in the events.

Properties

Link copied to clipboard

A dispatcher for blocking IO that is usable from common code, where Dispatchers.IO does not resolve.

@ExperimentalStructuredCoroutines
actual val Dispatchers.ioCompat: CoroutineDispatcher

Actual for JS: Dispatchers.Default, as there is no dedicated IO dispatcher.

actual val ERROR CLASS: Symbol not found for Dispatchers.ioCompat: ERROR CLASS: Symbol not found for CoroutineDispatcher

Actual for JVM and Android: Dispatchers.IO.

Actual for Native targets: Dispatchers.IO.

@ExperimentalStructuredCoroutines
actual val Dispatchers.ioCompat: CoroutineDispatcher

Actual for Wasm (JS): Dispatchers.Default, as there is no dedicated IO dispatcher.

Actual for Wasm (WASI): Dispatchers.Default, as there is no dedicated IO dispatcher.

Link copied to clipboard
@ExperimentalStructuredCoroutines
actual val platformCapabilities: TraceCapabilities

Actual for Android: thread identity and system-trace integration are true; TraceCapabilities.counters is true on API 29+; flows are not supported.

The tracing capabilities of the current target. Truthful, never throws; all flags are false on targets without a backend.

@ExperimentalStructuredCoroutines
actual val platformCapabilities: TraceCapabilities

Actual for JS: no capability is available, every flag is false.

@ExperimentalStructuredCoroutines
actual val platformCapabilities: TraceCapabilities

Actual for the JVM: only TraceCapabilities.threadIdentity is true. The Perfetto sink lives in the separate :runtime-tracing artifact.

Actual for Native: no capability is available, every flag is false.

@ExperimentalStructuredCoroutines
actual val platformCapabilities: TraceCapabilities

Actual for Wasm (JS): no capability is available, every flag is false.

Actual for Wasm (WASI): no capability is available, every flag is false.

Functions

Link copied to clipboard
Link copied to clipboard
fun <T> Iterable<suspend () -> T>.concurrentOrdered(concurrency: Int = Int.MAX_VALUE): Flow<T>

Server-side ordered fan-in: when the returned flow is collected, launches every task concurrently with async and then awaits them in input order, emitting each result as soon as its turn is ready.

Link copied to clipboard
suspend fun <T> hedged(hedgeAfter: Duration, maxAttempts: Int = 2, shouldHedge: (Throwable) -> Boolean = { true }, block: suspend (attempt: Int) -> T): T

Hedged request: starts the primary attempt and, whenever the latest attempt has not completed within hedgeAfter, starts another identical attempt (up to maxAttempts in total). Returns the FIRST SUCCESSFUL result and cancels every attempt still running, so slower redundant requests never waste resources.

Link copied to clipboard

Wraps this provider's main, io and default dispatchers in InstrumentedDispatchers with those labels; unconfined is returned as is (see InstrumentedDispatcherProvider). Wrapping is lazy: nothing (including Dispatchers.Main) is read until the corresponding property is accessed.

Link copied to clipboard

Launches the collection of this flow in scope, routing any upstream failure to onError instead of letting it propagate to (and cancel) the parent scope.

Link copied to clipboard
suspend fun <T> Iterable<suspend () -> T>.parallel(concurrency: Int = Int.MAX_VALUE): List<T>

Runs every suspending task concurrently and returns the results in input order.

Link copied to clipboard

The maximum concurrency of the traced dispatcher label, or null when unknown. Meant to feed PoolSampler's parallelism argument.

Link copied to clipboard
@ExperimentalStructuredCoroutines
actual fun platformTraceSink(): TraceSink?

Actual for Android: returns a new AndroidTraceSink with default settings.

The default system-trace sink for the current target, or null when :runtime ships none (every target except Android). Null is the degraded answer, not an error: compose your own sinks.

@ExperimentalStructuredCoroutines
actual fun platformTraceSink(): TraceSink?

Actual for JS: returns null, no system tracer ships with :runtime.

@ExperimentalStructuredCoroutines
actual fun platformTraceSink(): TraceSink?

Actual for the JVM: returns null; use PerfettoTraceSink from :runtime-tracing for system-trace output.

Actual for Native: returns null, no system tracer ships with :runtime.

@ExperimentalStructuredCoroutines
actual fun platformTraceSink(): TraceSink?

Actual for Wasm (JS): returns null, no system tracer ships with :runtime.

Actual for Wasm (WASI): returns null, no system tracer ships with :runtime.

Link copied to clipboard
Link copied to clipboard

Receiver variant of runCatchingCancellable: runs block with this as its receiver, capturing ordinary exceptions into a Result and rethrowing CancellationException.

Link copied to clipboard
fun <T> safeCallbackFlow(buffer: Int = Channel.BUFFERED, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND, register: (SendChannel<T>) -> DisposableHandle): Flow<T>

Builds a Flow from a callback-based API while making cleanup impossible to forget.

Link copied to clipboard

Derives heuristic PoolSignals from these metrics using thresholds.

Derives heuristic PoolSignals from a chronological series of TraceEvent.PoolSamples, such as those a PoolSampler emits. Each label is evaluated on its own over its last minSamples samples; a label with fewer samples yields no signal.

Link copied to clipboard
fun <T> Flow<T>.stateInWhileSubscribed(scope: CoroutineScope, initialValue: T, stopTimeoutMillis: Long, replayExpirationMillis: Long = Long.MAX_VALUE): StateFlow<T>

Converts this flow into a StateFlow that only runs upstream while it has subscribers, plus a stopTimeoutMillis grace period after the last one leaves.

Link copied to clipboard
suspend fun <T> Iterable<suspend () -> T>.supervisedAll(concurrency: Int = Int.MAX_VALUE): List<Result<T>>

Runs every suspending task concurrently, isolating failures, and returns one Result per task in input order (supervisorScope + async).

Link copied to clipboard

Wraps this provider's main, io and default dispatchers in TracingDispatchers labeled "main", "io" and "default" that report to sink. unconfined is returned as is.

Link copied to clipboard

Warm flow: a hybrid between cold and hot. The upstream does not start until the first collector asks for data, runs exactly once in scope, and memoizes every emitted value, so later (or concurrent) collectors replay the stored values and then follow the live upstream instead of re-running it.

Link copied to clipboard
suspend fun <T> withCleanup(cleanup: suspend () -> Unit, block: suspend () -> T): T

Runs block and then always runs cleanup inside withContext(NonCancellable), so cleanup is allowed to suspend even when the coroutine is already cancelled.

Link copied to clipboard
suspend fun <T> withTimeoutResult(timeoutMillis: Long, block: suspend CoroutineScope.() -> T): Result<T>

Runs block with a timeout of timeoutMillis and reports a timeout as a failed Result instead of throwing, so it never cancels the parent scope.

suspend fun <T> withTimeoutResult(timeout: Duration, block: suspend CoroutineScope.() -> T): Result<T>
Link copied to clipboard
suspend fun <T> withTraceSpan(name: String, block: suspend () -> T): T

Runs block inside a new TraceSpan named name. Its parent is the span already in the current context, or none (a root span) when there is no span.