/* * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @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. * * **The `CompletableDeferred` interface is not stable for inheritance in 3rd party libraries**, * as new methods might be added to this interface in the future, but is stable for use. */ 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]. */ @Suppress("UNCHECKED_CAST") private class CompletableDeferredImpl( parent: Job? ) : JobSupport(true), CompletableDeferred, SelectClause1 { init { initParentJobInternal(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() = this override fun registerSelectClause1(select: SelectInstance, block: suspend (T) -> R) = registerSelectClause1Internal(select, block) override fun complete(value: T): Boolean = makeCompleting(value) override fun completeExceptionally(exception: Throwable): Boolean = makeCompleting(CompletedExceptionally(exception)) }