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