commonMain.CompletableDeferred.kt Maven / Gradle / Ivy
@file:Suppress("DEPRECATION_ERROR")
package kotlinx.coroutines
import kotlinx.coroutines.selects.*
/**
* A [Deferred] that can be completed via public functions [complete] or [cancel][Job.cancel].
*
* Note that the [complete] function returns `false` when this deferred value is already complete or completing,
* while [cancel][Job.cancel] returns `true` as long as the deferred is still _cancelling_ and the corresponding
* exception is incorporated into the final [completion exception][getCompletionExceptionOrNull].
*
* An instance of completable deferred can be created by `CompletableDeferred()` function in _active_ state.
*
* All functions on this interface are **thread-safe** and can
* be safely invoked from concurrent coroutines without external synchronization.
*/
@OptIn(ExperimentalSubclassOptIn::class)
@SubclassOptInRequired(markerClass = InternalForInheritanceCoroutinesApi::class)
public interface CompletableDeferred : Deferred {
/**
* Completes this deferred value with a given [value]. The result is `true` if this deferred was
* completed as a result of this invocation and `false` otherwise (if it was already completed).
*
* Subsequent invocations of this function have no effect and always produce `false`.
*
* This function transitions this deferred into _completed_ state if it was not completed or cancelled yet.
* However, if this deferred has children, then it transitions into _completing_ state and becomes _complete_
* once all its children are [complete][isCompleted]. See [Job] for details.
*/
public fun complete(value: T): Boolean
/**
* Completes this deferred value exceptionally with a given [exception]. The result is `true` if this deferred was
* completed as a result of this invocation and `false` otherwise (if it was already completed).
*
* Subsequent invocations of this function have no effect and always produce `false`.
*
* This function transitions this deferred into _cancelled_ state if it was not completed or cancelled yet.
* However, that if this deferred has children, then it transitions into _cancelling_ state and becomes _cancelled_
* once all its children are [complete][isCompleted]. See [Job] for details.
*/
public fun completeExceptionally(exception: Throwable): Boolean
}
/**
* Completes this deferred value with the value or exception in the given [result]. Returns `true` if this deferred
* was completed as a result of this invocation and `false` otherwise (if it was already completed).
*
* Subsequent invocations of this function have no effect and always produce `false`.
*
* This function transitions this deferred in the same ways described by [CompletableDeferred.complete] and
* [CompletableDeferred.completeExceptionally].
*/
public fun CompletableDeferred.completeWith(result: Result): Boolean =
result.fold({ complete(it) }, { completeExceptionally(it) })
/**
* Creates a [CompletableDeferred] in an _active_ state.
* It is optionally a child of a [parent] job.
*/
@Suppress("FunctionName")
public fun CompletableDeferred(parent: Job? = null): CompletableDeferred = CompletableDeferredImpl(parent)
/**
* Creates an already _completed_ [CompletableDeferred] with a given [value].
*/
@Suppress("FunctionName")
public fun CompletableDeferred(value: T): CompletableDeferred = CompletableDeferredImpl(null).apply { complete(value) }
/**
* Concrete implementation of [CompletableDeferred].
*/
@OptIn(InternalForInheritanceCoroutinesApi::class)
@Suppress("UNCHECKED_CAST")
private class CompletableDeferredImpl(
parent: Job?
) : JobSupport(true), CompletableDeferred {
init { initParentJob(parent) }
override val onCancelComplete get() = true
override fun getCompleted(): T = getCompletedInternal() as T
override suspend fun await(): T = awaitInternal() as T
override val onAwait: SelectClause1 get() = onAwaitInternal as SelectClause1
override fun complete(value: T): Boolean =
makeCompleting(value)
override fun completeExceptionally(exception: Throwable): Boolean =
makeCompleting(CompletedExceptionally(exception))
}