1 package kotlinx.coroutines 2 3 /** 4 * Handler for [Job.invokeOnCompletion] and [CancellableContinuation.invokeOnCancellation]. 5 * 6 * The meaning of `cause` that is passed to the handler is: 7 * - It is `null` if the job has completed normally or the continuation was cancelled without a `cause`. 8 * - It is an instance of [CancellationException] if the job or the continuation was cancelled _normally_. 9 * **It should not be treated as an error**. In particular, it should not be reported to error logs. 10 * - Otherwise, the job or the continuation had _failed_. 11 * 12 * A function used for this should not throw any exceptions. 13 * If it does, they will get caught, wrapped into [CompletionHandlerException], and then either 14 * - passed to [handleCoroutineException] for [CancellableContinuation.invokeOnCancellation] 15 * and, for [Job] instances that are coroutines, [Job.invokeOnCompletion], or 16 * - for [Job] instances that are not coroutines, simply thrown, potentially crashing unrelated code. 17 * 18 * Functions used for this must be fast, non-blocking, and thread-safe. 19 * This handler can be invoked concurrently with the surrounding code. 20 * There is no guarantee on the execution context in which the function is invoked. 21 * 22 * **Note**: This type is a part of internal machinery that supports parent-child hierarchies 23 * and allows for implementation of suspending functions that wait on the Job's state. 24 * This type should not be used in general application code. 25 */ 26 // TODO: deprecate. This doesn't seem better than a simple function type. 27 public typealias CompletionHandler = (cause: Throwable?) -> Unit 28 29 /** 30 * Essentially the same as just a function from `Throwable?` to `Unit`. 31 * The only thing implementors can do is call [invoke]. 32 * The reason this abstraction exists is to allow providing a readable [toString] in the list of completion handlers 33 * as seen from the debugger. 34 * Use [UserSupplied] to create an instance from a lambda. 35 * We can't avoid defining a separate type, because on JS, you can't inherit from a function type. 36 * 37 * @see CancelHandler for a very similar interface, but used for handling cancellation and not completion. 38 */ 39 internal interface InternalCompletionHandler { 40 /** 41 * Signals completion. 42 * 43 * This function: 44 * - Does not throw any exceptions. 45 * For [Job] instances that are coroutines, exceptions thrown by this function will be caught, wrapped into 46 * [CompletionHandlerException], and passed to [handleCoroutineException], but for those that are not coroutines, 47 * they will just be rethrown, potentially crashing unrelated code. 48 * - Is fast, non-blocking, and thread-safe. 49 * - Can be invoked concurrently with the surrounding code. 50 * - Can be invoked from any context. 51 * 52 * The meaning of `cause` that is passed to the handler is: 53 * - It is `null` if the job has completed normally. 54 * - It is an instance of [CancellationException] if the job was cancelled _normally_. 55 * **It should not be treated as an error**. In particular, it should not be reported to error logs. 56 * - Otherwise, the job had _failed_. 57 */ invokenull58 fun invoke(cause: Throwable?) 59 60 /** 61 * A lambda passed from outside the coroutine machinery. 62 * 63 * See the requirements for [InternalCompletionHandler.invoke] when implementing this function. 64 */ 65 class UserSupplied(private val handler: (cause: Throwable?) -> Unit) : InternalCompletionHandler { 66 /** @suppress */ 67 override fun invoke(cause: Throwable?) { handler(cause) } 68 69 override fun toString() = "InternalCompletionHandler.UserSupplied[${handler.classSimpleName}@$hexAddress]" 70 } 71 } 72