CopyableThreadContextElement

A ThreadContextElement copied whenever a child coroutine inherits a context containing it.

When an API uses a mutableThreadLocal for consistency, a CopyableThreadContextElement can give coroutines "coroutine-safe" write access to that ThreadLocal.

A write made to a ThreadLocal with a matching CopyableThreadContextElement by a coroutine will be visible to itself and any child coroutine launched after that write.

Writes will not be visible to the parent coroutine, peer coroutines, or coroutines that happen to use the same thread. Writes made to the ThreadLocal by the parent coroutine after launching a child coroutine will not be visible to that child coroutine.

This can be used to allow a coroutine to use a mutable ThreadLocal API transparently and correctly, regardless of the coroutine's structured concurrency.

This example adapts a ThreadLocal method trace to be "coroutine local" while the method trace is in a coroutine:

class TraceContextElement(val traceData: TraceData?) : CopyableThreadContextElement<TraceData?> {
companion object Key : CoroutineContext.Key<ThreadTraceContextElement>
override val key: CoroutineContext.Key<ThreadTraceContextElement>
get() = Key

override fun updateThreadContext(context: CoroutineContext): TraceData? {
val oldState = traceThreadLocal.get()
traceThreadLocal.set(data)
return oldState
}

override fun restoreThreadContext(context: CoroutineContext, oldData: TraceData?) {
traceThreadLocal.set(oldState)
}

override fun copyForChildCoroutine(): CopyableThreadContextElement<MyData?> {
// Copy from the ThreadLocal source of truth at child coroutine launch time. This makes
// ThreadLocal writes between resumption of the parent coroutine and the launch of the
// child coroutine visible to the child.
return CopyForChildCoroutineElement(traceThreadLocal.get())
}
}

A coroutine using this mechanism can safely call Java code that assumes it's called using a Thread.

Functions

copyForChildCoroutine
Link copied to clipboard
abstract fun copyForChildCoroutine(): CopyableThreadContextElement<S>

Returns a CopyableThreadContextElement to replace thisCopyableThreadContextElement in the child coroutine's context that is under construction.

Sources

jvm source
Link copied to clipboard