blob: f09aa3ccd951497362357ae4fedf6c7a133bbf9a [file] [log] [blame]
/*
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines
import kotlinx.atomicfu.*
import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
import kotlin.jvm.*
internal fun <T> Result<T>.toState(
onCancellation: ((cause: Throwable) -> Unit)? = null
): Any? = fold(
onSuccess = { if (onCancellation != null) CompletedWithCancellation(it, onCancellation) else it },
onFailure = { CompletedExceptionally(it) }
)
internal fun <T> Result<T>.toState(caller: CancellableContinuation<*>): Any? = fold(
onSuccess = { it },
onFailure = { CompletedExceptionally(recoverStackTrace(it, caller)) }
)
@Suppress("RESULT_CLASS_IN_RETURN_TYPE", "UNCHECKED_CAST")
internal fun <T> recoverResult(state: Any?, uCont: Continuation<T>): Result<T> =
if (state is CompletedExceptionally)
Result.failure(recoverStackTrace(state.cause, uCont))
else
Result.success(state as T)
internal data class CompletedWithCancellation(
@JvmField val result: Any?,
@JvmField val onCancellation: (cause: Throwable) -> Unit
)
/**
* Class for an internal state of a job that was cancelled (completed exceptionally).
*
* @param cause the exceptional completion cause. It's either original exceptional cause
* or artificial [CancellationException] if no cause was provided
*/
internal open class CompletedExceptionally(
@JvmField public val cause: Throwable,
handled: Boolean = false
) {
private val _handled = atomic(handled)
val handled: Boolean get() = _handled.value
fun makeHandled(): Boolean = _handled.compareAndSet(false, true)
override fun toString(): String = "$classSimpleName[$cause]"
}
/**
* A specific subclass of [CompletedExceptionally] for cancelled [AbstractContinuation].
*
* @param continuation the continuation that was cancelled.
* @param cause the exceptional completion cause. If `cause` is null, then a [CancellationException]
* if created on first access to [exception] property.
*/
internal class CancelledContinuation(
continuation: Continuation<*>,
cause: Throwable?,
handled: Boolean
) : CompletedExceptionally(cause ?: CancellationException("Continuation $continuation was cancelled normally"), handled) {
private val _resumed = atomic(false)
fun makeResumed(): Boolean = _resumed.compareAndSet(false, true)
}