@@ -6,14 +6,20 @@ import kotlin.coroutines.*
66 * Defines elements in a [CoroutineContext] that are installed into the thread context
77 * every time the coroutine with this element in the context is resumed on a thread.
88 *
9+ * In this context, by a "thread" we mean an environment where coroutines are executed in parallel to coroutines
10+ * other threads.
11+ * On JVM and Native, this is the same as an operating system thread.
12+ * On JS, Wasm/JS, and Wasm/WASI, because coroutines can not actually execute in parallel,
13+ * we say that there is a single thread running all coroutines.
14+ *
915 * Implementations of this interface define a type [S] of the thread-local state that they need to store
10- * upon resuming a coroutine and restore later upon suspension .
11- * The infrastructure provides the corresponding storage.
16+ * when the coroutine is resumed and restore later on when it suspends .
17+ * The coroutines infrastructure provides the corresponding storage.
1218 *
1319 * Example usage looks like this:
1420 *
1521 * ```
16- * // Appends "name" of a coroutine to a current thread name when coroutine is executed
22+ * // Appends "name" of a coroutine to the current thread name when a coroutine is executed
1723 * class CoroutineName(val name: String) : ThreadContextElement<String> {
1824 * // declare companion object for a key of this element in coroutine context
1925 * companion object Key : CoroutineContext.Key<CoroutineName>
@@ -22,14 +28,14 @@ import kotlin.coroutines.*
2228 * override val key: CoroutineContext.Key<CoroutineName>
2329 * get() = Key
2430 *
25- * // this is invoked before coroutine is resumed on current thread
31+ * // this is invoked before a coroutine is resumed on the current thread
2632 * override fun updateThreadContext(context: CoroutineContext): String {
2733 * val previousName = Thread.currentThread().name
2834 * Thread.currentThread().name = "$previousName # $name"
2935 * return previousName
3036 * }
3137 *
32- * // this is invoked after coroutine has suspended on current thread
38+ * // this is invoked after a coroutine has suspended on the current thread
3339 * override fun restoreThreadContext(context: CoroutineContext, oldState: String) {
3440 * Thread.currentThread().name = oldState
3541 * }
@@ -39,13 +45,13 @@ import kotlin.coroutines.*
3945 * launch(Dispatchers.Main + CoroutineName("Progress bar coroutine")) { ... }
4046 * ```
4147 *
42- * Every time this coroutine is resumed on a thread, UI thread name is updated to
43- * "UI thread original name # Progress bar coroutine" and the thread name is restored to the original one when
48+ * Every time this coroutine is resumed on a thread, the name of the thread backing [Dispatchers.Main] is updated to
49+ * "UI thread original name # Progress bar coroutine", and the thread name is restored to the original one when
4450 * this coroutine suspends.
4551 *
46- * To use [ ThreadLocal] variable within the coroutine use [ ThreadLocal.asContextElement][asContextElement] function.
52+ * On JVM, to use a ` ThreadLocal` variable within the coroutine, use the ` ThreadLocal.asContextElement` function.
4753 *
48- * ### Reentrancy and thread- safety
54+ * ### Reentrancy and thread safety
4955 *
5056 * Correct implementations of this interface must expect that calls to [restoreThreadContext]
5157 * may happen in parallel to the subsequent [updateThreadContext] and [restoreThreadContext] operations.
@@ -56,50 +62,65 @@ import kotlin.coroutines.*
5662 */
5763public interface ThreadContextElement <S > : CoroutineContext .Element {
5864 /* *
59- * Updates context of the current thread.
60- * This function is invoked before the coroutine in the specified [context] is resumed in the current thread
61- * when the context of the coroutine this element.
62- * The result of this function is the old value of the thread-local state that will be passed to [restoreThreadContext].
63- * This method should handle its own exceptions and do not rethrow it. Thrown exceptions will leave coroutine which
64- * context is updated in an undefined state and may crash an application.
65+ * Updates the context of the current thread.
66+ *
67+ * This function is invoked before the coroutine in the specified [context] is started or resumed
68+ * in the current thread when this element is present in the context of the coroutine.
69+ * The result of this function is the old value of the thread-local state
70+ * that will be passed to [restoreThreadContext] when the coroutine eventually suspends or completes.
71+ * This method should handle its own exceptions and not rethrow them.
72+ * Thrown exceptions will leave the coroutine whose context is updated in an undefined state
73+ * and may crash the application.
6574 *
66- * @param context the coroutine context .
75+ * @param context the context of the coroutine that's being started or resumed .
6776 */
6877 public fun updateThreadContext (context : CoroutineContext ): S
6978
7079 /* *
71- * Restores context of the current thread.
72- * This function is invoked after the coroutine in the specified [context] is suspended in the current thread
73- * if [updateThreadContext] was previously invoked on resume of this coroutine.
74- * The value of [oldState] is the result of the previous invocation of [updateThreadContext] and it should
75- * be restored in the thread-local state by this function.
76- * This method should handle its own exceptions and do not rethrow it. Thrown exceptions will leave coroutine which
77- * context is updated in an undefined state and may crash an application.
80+ * Restores the context of the current thread.
7881 *
79- * @param context the coroutine context.
80- * @param oldState the value returned by the previous invocation of [updateThreadContext].
82+ * This function is invoked after the coroutine in the specified [context] has suspended or finished
83+ * in the current thread if [updateThreadContext] was previously invoked when this coroutine was started or resumed.
84+ * [oldState] is the result of the preceding invocation of [updateThreadContext],
85+ * and this value should be restored in the thread-local state by this function.
86+ * This method should handle its own exceptions and not rethrow them.
87+ * Thrown exceptions will leave the coroutine whose context is updated in an undefined state
88+ * and may crash the application.
89+ *
90+ * @param context the context of the coroutine that has suspended or finished.
91+ * @param oldState the value returned by the preceding invocation of [updateThreadContext].
8192 */
8293 public fun restoreThreadContext (context : CoroutineContext , oldState : S )
8394}
8495
8596/* *
86- * A [ThreadContextElement] copied whenever a child coroutine inherits a context containing it.
87- *
88- * When an API uses a _mutable_ [ThreadLocal] for consistency, a [CopyableThreadContextElement]
89- * can give coroutines "coroutine-safe" write access to that `ThreadLocal`.
90- *
91- * A write made to a `ThreadLocal` with a matching [CopyableThreadContextElement] by a coroutine
92- * will be visible to _itself_ and any child coroutine launched _after_ that write.
93- *
94- * Writes will not be visible to the parent coroutine, peer coroutines, or coroutines that happen
95- * to use the same thread. Writes made to the `ThreadLocal` by the parent coroutine _after_
96- * launching a child coroutine will not be visible to that child coroutine.
97- *
98- * This can be used to allow a coroutine to use a mutable ThreadLocal API transparently and
97+ * A [ThreadContextElement] that is copied whenever a child coroutine inherits a context containing it.
98+ *
99+ * [ThreadContextElement] can be used to ensure that when several coroutines share the same thread,
100+ * they can each have their personal (though immutable) thread-local state without affecting the other coroutines.
101+ * Often, however, it is desirable to propagate the thread-local state across coroutine suspensions
102+ * and to child coroutines.
103+ * A [CopyableThreadContextElement] is an instrument for implementing exactly this kind of
104+ * hierarchical mutable thread-local state.
105+ *
106+ * A change made to a thread-local value with a matching [CopyableThreadContextElement] by a coroutine
107+ * will be visible to _itself_ (even after the coroutine suspends and subsequently resumes)
108+ * and any child coroutine launched _after_ that write.
109+ * Changes introduced to the thread-local value by the parent coroutine _after_ launching a child coroutine
110+ * will not be visible to that child coroutine.
111+ * Changes will not be visible to the parent coroutine, peer coroutines, or coroutines that also have
112+ * this [CopyableThreadContextElement] in their context and simply happen to use the same thread.
113+ *
114+ * This can be used to allow a coroutine to use a mutable-thread-local-value-based API transparently and
99115 * correctly, regardless of the coroutine's structured concurrency.
100116 *
101- * This example adapts a `ThreadLocal` method trace to be "coroutine local" while the method trace
102- * is in a coroutine:
117+ * The changes *may* be visible to unrelated coroutines that are launched on the same thread if those coroutines
118+ * do not have a [CopyableThreadContextElement] with the same key in their context.
119+ * Because of this, it is an error to access a thread-local value from a coroutine without the corresponding
120+ * [CopyableThreadContextElement] when other coroutines may have modified it.
121+ *
122+ * This example adapts thread-local-value-based method tracing to follow coroutine switches and child coroutine creation.
123+ * when the tracing happens inside a coroutine:
103124 *
104125 * ```
105126 * class TraceContextElement(private val traceData: TraceData?) : CopyableThreadContextElement<TraceData?> {
@@ -118,14 +139,14 @@ public interface ThreadContextElement<S> : CoroutineContext.Element {
118139 * }
119140 *
120141 * override fun copyForChild(): TraceContextElement {
121- * // Copy from the ThreadLocal source of truth at child coroutine launch time. This makes
122- * // ThreadLocal writes between resumption of the parent coroutine and the launch of the
142+ * // Copy from the ThreadLocal source of truth at the child coroutine launch time. This makes
143+ * // ThreadLocal writes between the resumption of the parent coroutine and the launch of the
123144 * // child coroutine visible to the child.
124145 * return TraceContextElement(traceThreadLocal.get()?.copy())
125146 * }
126147 *
127148 * override fun mergeForChild(overwritingElement: CoroutineContext.Element): CoroutineContext {
128- * // Merge operation defines how to handle situations when both
149+ * // The merge operation defines how to handle situations when both
129150 * // the parent coroutine has an element in the context and
130151 * // an element with the same key was also
131152 * // explicitly passed to the child coroutine.
@@ -136,8 +157,8 @@ public interface ThreadContextElement<S> : CoroutineContext.Element {
136157 * }
137158 * ```
138159 *
139- * A coroutine using this mechanism can safely call Java code that assumes the corresponding thread local element's
140- * value is installed into the target thread local.
160+ * A coroutine using this mechanism can safely call coroutine-oblivious code that assumes
161+ * a specific thread local element's value is installed into the target thread local.
141162 *
142163 * ### Reentrancy and thread-safety
143164 *
@@ -165,7 +186,7 @@ public interface ThreadContextElement<S> : CoroutineContext.Element {
165186public interface CopyableThreadContextElement <S > : ThreadContextElement <S > {
166187
167188 /* *
168- * Returns a [CopyableThreadContextElement] to replace `this` `CopyableThreadContextElement` in the child
189+ * Returns the [CopyableThreadContextElement] to replace `this` `CopyableThreadContextElement` in the child
169190 * coroutine's context that is under construction if the added context does not contain an element with the same [key].
170191 *
171192 * This function is called on the element each time a new coroutine inherits a context containing it,
@@ -177,7 +198,7 @@ public interface CopyableThreadContextElement<S> : ThreadContextElement<S> {
177198 public fun copyForChild (): CopyableThreadContextElement <S >
178199
179200 /* *
180- * Returns a [CopyableThreadContextElement] to replace `this` `CopyableThreadContextElement` in the child
201+ * Returns the [CopyableThreadContextElement] to replace `this` `CopyableThreadContextElement` in the child
181202 * coroutine's context that is under construction if the added context does contain an element with the same [key].
182203 *
183204 * This method is invoked on the original element, accepting as the parameter
0 commit comments