Roman Elizarov | a7db8ec | 2017-12-21 22:45:12 +0300 | [diff] [blame] | 1 | /* |
Roman Elizarov | 1f74a2d | 2018-06-29 19:19:45 +0300 | [diff] [blame^] | 2 | * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. |
Roman Elizarov | a7db8ec | 2017-12-21 22:45:12 +0300 | [diff] [blame] | 3 | */ |
| 4 | |
Roman Elizarov | e1c0b65 | 2017-12-01 14:02:57 +0300 | [diff] [blame] | 5 | package kotlinx.coroutines.experimental |
| 6 | |
Roman Elizarov | aa461cf | 2018-04-11 13:20:29 +0300 | [diff] [blame] | 7 | import kotlinx.coroutines.experimental.internal.* |
| 8 | |
Roman Elizarov | e1c0b65 | 2017-12-01 14:02:57 +0300 | [diff] [blame] | 9 | /** |
Vsevolod Tolstopyatov | f3a5013 | 2018-04-16 19:41:20 +0300 | [diff] [blame] | 10 | * Handler for [Job.invokeOnCompletion] and [CancellableContinuation.invokeOnCancellation]. |
Roman Elizarov | e1c0b65 | 2017-12-01 14:02:57 +0300 | [diff] [blame] | 11 | * |
| 12 | * Installed handler should not throw any exceptions. If it does, they will get caught, |
| 13 | * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code. |
| 14 | * |
Roman Elizarov | e89cd68 | 2018-04-25 13:03:40 +0300 | [diff] [blame] | 15 | * The meaning of `cause` that is passed to the handler: |
| 16 | * * Cause is `null` when job has completed normally. |
| 17 | * * Cause is an instance of [CancellationException] when job was cancelled _normally_. |
| 18 | * **It should not be treated as an error**. In particular, it should not be reported to error logs. |
| 19 | * * Otherwise, the job had _failed_. |
| 20 | * |
Roman Elizarov | e1c0b65 | 2017-12-01 14:02:57 +0300 | [diff] [blame] | 21 | * **Note**: This type is a part of internal machinery that supports parent-child hierarchies |
| 22 | * and allows for implementation of suspending functions that wait on the Job's state. |
| 23 | * This type should not be used in general application code. |
| 24 | * Implementations of `CompletionHandler` must be fast and _lock-free_. |
| 25 | */ |
| 26 | public typealias CompletionHandler = (cause: Throwable?) -> Unit |
Roman Elizarov | aa461cf | 2018-04-11 13:20:29 +0300 | [diff] [blame] | 27 | |
| 28 | // We want class that extends LockFreeLinkedListNode & CompletionHandler but we cannot do it on Kotlin/JS, |
| 29 | // so this expect class provides us with the corresponding abstraction in a platform-agnostic way. |
Roman Elizarov | dbd9e1c | 2018-04-28 15:14:18 +0300 | [diff] [blame] | 30 | internal expect abstract class CompletionHandlerBase() : LockFreeLinkedListNode { |
Roman Elizarov | aa461cf | 2018-04-11 13:20:29 +0300 | [diff] [blame] | 31 | abstract fun invoke(cause: Throwable?) |
| 32 | } |
| 33 | |
Roman Elizarov | dbd9e1c | 2018-04-28 15:14:18 +0300 | [diff] [blame] | 34 | internal expect val CompletionHandlerBase.asHandler: CompletionHandler |
| 35 | |
| 36 | // More compact version of CompletionHandlerBase for CancellableContinuation with same workaround for JS |
| 37 | internal expect abstract class CancelHandlerBase() { |
Vsevolod Tolstopyatov | f3a5013 | 2018-04-16 19:41:20 +0300 | [diff] [blame] | 38 | abstract fun invoke(cause: Throwable?) |
| 39 | } |
| 40 | |
Roman Elizarov | dbd9e1c | 2018-04-28 15:14:18 +0300 | [diff] [blame] | 41 | internal expect val CancelHandlerBase.asHandler: CompletionHandler |
| 42 | |
Roman Elizarov | aa461cf | 2018-04-11 13:20:29 +0300 | [diff] [blame] | 43 | // :KLUDGE: We have to invoke a handler in platform-specific way via `invokeIt` extension, |
| 44 | // because we play type tricks on Kotlin/JS and handler is not necessarily a function there |
| 45 | internal expect fun CompletionHandler.invokeIt(cause: Throwable?) |