xref: /aosp_15_r20/external/kotlinx.coroutines/kotlinx-coroutines-core/common/src/CompletionState.kt (revision 7a7160fed73afa6648ef8aa100d4a336fe921d9a)
1 package kotlinx.coroutines
2 
3 import kotlinx.atomicfu.*
4 import kotlinx.coroutines.internal.*
5 import kotlin.coroutines.*
6 import kotlin.jvm.*
7 
toStatenull8 internal fun <T> Result<T>.toState(
9     onCancellation: ((cause: Throwable) -> Unit)? = null
10 ): Any? = fold(
11     onSuccess = { if (onCancellation != null) CompletedWithCancellation(it, onCancellation) else it },
<lambda>null12     onFailure = { CompletedExceptionally(it) }
13 )
14 
toStatenull15 internal fun <T> Result<T>.toState(caller: CancellableContinuation<*>): Any? = fold(
16     onSuccess = { it },
<lambda>null17     onFailure = { CompletedExceptionally(recoverStackTrace(it, caller)) }
18 )
19 
20 @Suppress("RESULT_CLASS_IN_RETURN_TYPE", "UNCHECKED_CAST")
recoverResultnull21 internal fun <T> recoverResult(state: Any?, uCont: Continuation<T>): Result<T> =
22     if (state is CompletedExceptionally)
23         Result.failure(recoverStackTrace(state.cause, uCont))
24     else
25         Result.success(state as T)
26 
27 internal data class CompletedWithCancellation(
28     @JvmField val result: Any?,
29     @JvmField val onCancellation: (cause: Throwable) -> Unit
30 )
31 
32 /**
33  * Class for an internal state of a job that was cancelled (completed exceptionally).
34  *
35  * @param cause the exceptional completion cause. It's either original exceptional cause
36  *        or artificial [CancellationException] if no cause was provided
37  */
38 internal open class CompletedExceptionally(
39     @JvmField val cause: Throwable,
40     handled: Boolean = false
41 ) {
42     private val _handled = atomic(handled)
43     val handled: Boolean get() = _handled.value
44     fun makeHandled(): Boolean = _handled.compareAndSet(false, true)
45     override fun toString(): String = "$classSimpleName[$cause]"
46 }
47 
48 /**
49  * A specific subclass of [CompletedExceptionally] for cancelled [AbstractContinuation].
50  *
51  * @param continuation the continuation that was cancelled.
52  * @param cause the exceptional completion cause. If `cause` is null, then a [CancellationException]
53  *        if created on first access to [exception] property.
54  */
55 internal class CancelledContinuation(
56     continuation: Continuation<*>,
57     cause: Throwable?,
58     handled: Boolean
59 ) : CompletedExceptionally(cause ?: CancellationException("Continuation $continuation was cancelled normally"), handled) {
60     private val _resumed = atomic(false)
makeResumednull61     fun makeResumed(): Boolean = _resumed.compareAndSet(false, true)
62 }
63