[K/N] Make SafeContinuation thread-safe
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
package kotlin.coroutines
|
package kotlin.coroutines
|
||||||
|
|
||||||
import kotlin.*
|
import kotlin.*
|
||||||
|
import kotlin.native.concurrent.*
|
||||||
import kotlin.coroutines.intrinsics.CoroutineSingletons.*
|
import kotlin.coroutines.intrinsics.CoroutineSingletons.*
|
||||||
import kotlin.coroutines.intrinsics.*
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|
||||||
@@ -22,26 +23,28 @@ internal actual constructor(
|
|||||||
public actual override val context: CoroutineContext
|
public actual override val context: CoroutineContext
|
||||||
get() = delegate.context
|
get() = delegate.context
|
||||||
|
|
||||||
private var result: Any? = initialResult
|
private var resultRef = FreezableAtomicReference<Any?>(initialResult)
|
||||||
|
|
||||||
public actual override fun resumeWith(result: Result<T>) {
|
public actual override fun resumeWith(result: Result<T>) {
|
||||||
val cur = this.result
|
while (true) {
|
||||||
when {
|
val cur = resultRef.value
|
||||||
cur === UNDECIDED -> this.result = result.value
|
when {
|
||||||
cur === COROUTINE_SUSPENDED -> {
|
cur === UNDECIDED -> if (resultRef.compareAndSet(UNDECIDED, result.value)) return
|
||||||
this.result = RESUMED
|
cur === COROUTINE_SUSPENDED -> if (resultRef.compareAndSet(COROUTINE_SUSPENDED, RESUMED)) {
|
||||||
delegate.resumeWith(result)
|
delegate.resumeWith(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else -> throw IllegalStateException("Already resumed")
|
||||||
}
|
}
|
||||||
else -> throw IllegalStateException("Already resumed")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal actual fun getOrThrow(): Any? {
|
internal actual fun getOrThrow(): Any? {
|
||||||
val result = this.result
|
var result = resultRef.value
|
||||||
if (result === UNDECIDED) {
|
if (result === UNDECIDED) {
|
||||||
this.result = COROUTINE_SUSPENDED
|
if (resultRef.compareAndSet(UNDECIDED, COROUTINE_SUSPENDED)) return COROUTINE_SUSPENDED
|
||||||
return COROUTINE_SUSPENDED
|
result = resultRef.value
|
||||||
}
|
}
|
||||||
return when {
|
return when {
|
||||||
result === RESUMED -> COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream
|
result === RESUMED -> COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream
|
||||||
|
|||||||
Reference in New Issue
Block a user