Skip to content

Commit

Permalink
Clarify thread locals documentation
Browse files Browse the repository at this point in the history
Fixes #985
  • Loading branch information
qwwdfsad committed Mar 6, 2019
1 parent ab92346 commit b782adb
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions kotlinx-coroutines-core/jvm/src/ThreadContextElement.kt
Expand Up @@ -81,9 +81,11 @@ public interface ThreadContextElement<S> : CoroutineContext.Element {
* Wraps [ThreadLocal] into [ThreadContextElement]. The resulting [ThreadContextElement]
* maintains the given [value] of the given [ThreadLocal] for coroutine regardless of the actual thread its is resumed on.
* By default [ThreadLocal.get] is used as a value for the thread-local variable, but it can be overridden with [value] parameter.
* Beware that context element **does not track** modifications of the thread-local and accessing thread-local from coroutine
* without the corresponding context element returns **undefined** value. See the examples for a detailed description.
*
* Example usage looks like this:
*
* Example usage:
* ```
* val myThreadLocal = ThreadLocal<String?>()
* ...
Expand All @@ -97,7 +99,7 @@ public interface ThreadContextElement<S> : CoroutineContext.Element {
* println(myThreadLocal.get()) // Prints "null"
* ```
*
* Note that the context element does not track modifications of the thread-local variable, for example:
* The context element does not track modifications of the thread-local variable, for example:
*
* ```
* myThreadLocal.set("main")
Expand All @@ -109,12 +111,27 @@ public interface ThreadContextElement<S> : CoroutineContext.Element {
* ```
*
* Use `withContext` to update the corresponding thread-local variable to a different value, for example:
*
* ```
* withContext(myThreadLocal.asContextElement("foo")) {
* println(myThreadLocal.get()) // Prints "foo"
* }
* ```
*
* Accessing the thread-local without corresponding context element leads to undefined value:
* ```
* val tl = ThreadLocal.withInitial { "initial" }
*
* runBlocking {
* println(tl.get()) // Will print "initial"
* // Change context
* withContext(tl.asContextElement("modified")) {
* println(tl.get()) // Will print "modified"
* }
* // Context is changed again
* println(tl.get()) // <- WARN: can print either "modified" or "initial"
* }
* ```
* to fix this behaviour use `runBlocking(tl.asContextElement())`
*/
public fun <T> ThreadLocal<T>.asContextElement(value: T = get()): ThreadContextElement<T> =
ThreadLocalElement(value, this)

0 comments on commit b782adb

Please sign in to comment.