1 /*
2  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines
6 
7 import kotlin.coroutines.*
8 import kotlin.coroutines.intrinsics.*
9 
10 @PublishedApi internal const val MODE_ATOMIC_DEFAULT = 0 // schedule non-cancellable dispatch for suspendCoroutine
11 @PublishedApi internal const val MODE_CANCELLABLE = 1    // schedule cancellable dispatch for suspendCancellableCoroutine
12 @PublishedApi internal const val MODE_DIRECT = 2         // when the context is right just invoke the delegate continuation direct
13 @PublishedApi internal const val MODE_UNDISPATCHED = 3   // when the thread is right, but need to mark it with current coroutine
14 @PublishedApi internal const val MODE_IGNORE = 4         // don't do anything
15 
16 internal val Int.isCancellableMode get() = this == MODE_CANCELLABLE
17 internal val Int.isDispatchedMode get() = this == MODE_ATOMIC_DEFAULT || this == MODE_CANCELLABLE
18 
19 internal fun <T> Continuation<T>.resumeMode(value: T, mode: Int) {
20     when (mode) {
21         MODE_ATOMIC_DEFAULT -> resume(value)
22         MODE_CANCELLABLE -> resumeCancellable(value)
23         MODE_DIRECT -> resumeDirect(value)
24         MODE_UNDISPATCHED -> (this as DispatchedContinuation).resumeUndispatched(value)
25         MODE_IGNORE -> {}
26         else -> error("Invalid mode $mode")
27     }
28 }
29 
30 internal fun <T> Continuation<T>.resumeWithExceptionMode(exception: Throwable, mode: Int) {
31     when (mode) {
32         MODE_ATOMIC_DEFAULT -> resumeWithException(exception)
33         MODE_CANCELLABLE -> resumeCancellableWithException(exception)
34         MODE_DIRECT -> resumeDirectWithException(exception)
35         MODE_UNDISPATCHED -> (this as DispatchedContinuation).resumeUndispatchedWithException(exception)
36         MODE_IGNORE -> {}
37         else -> error("Invalid mode $mode")
38     }
39 }
40 
41 internal fun <T> Continuation<T>.resumeUninterceptedMode(value: T, mode: Int) {
42     when (mode) {
43         MODE_ATOMIC_DEFAULT -> intercepted().resume(value)
44         MODE_CANCELLABLE -> intercepted().resumeCancellable(value)
45         MODE_DIRECT -> resume(value)
46         MODE_UNDISPATCHED -> withCoroutineContext(context, null) { resume(value) }
47         MODE_IGNORE -> {}
48         else -> error("Invalid mode $mode")
49     }
50 }
51 
52 internal fun <T> Continuation<T>.resumeUninterceptedWithExceptionMode(exception: Throwable, mode: Int) {
53     when (mode) {
54         MODE_ATOMIC_DEFAULT -> intercepted().resumeWithException(exception)
55         MODE_CANCELLABLE -> intercepted().resumeCancellableWithException(exception)
56         MODE_DIRECT -> resumeWithException(exception)
57         MODE_UNDISPATCHED -> withCoroutineContext(context, null) { resumeWithException(exception) }
58         MODE_IGNORE -> {}
59         else -> error("Invalid mode $mode")
60     }
61 }
62