Skip to content

Commit 6640b2b

Browse files
committed
Public API for AbstractCoroutine
1 parent 6cdbe04 commit 6640b2b

File tree

23 files changed

+219
-136
lines changed

23 files changed

+219
-136
lines changed

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/AbstractCoroutine.kt

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,107 @@
1616

1717
package kotlinx.coroutines.experimental
1818

19-
import kotlin.coroutines.experimental.Continuation
20-
import kotlin.coroutines.experimental.CoroutineContext
19+
import kotlin.coroutines.experimental.*
2120

2221
/**
23-
* Abstract class for coroutines.
22+
* Abstract base class for implementation of coroutines in coroutine builders.
2423
*
2524
* * Coroutines implement completion [Continuation], [Job], and [CoroutineScope] interfaces.
2625
* * Coroutine stores the result of continuation in the state of the job.
2726
* * Coroutine waits for children coroutines to finish before completing.
2827
* * Coroutines are cancelled through an intermediate _cancelling_ state.
2928
*
30-
* @param active when `true` coroutine is created in _active_ state, when `false` in _new_ state. See [Job] for details.
31-
* @suppress **This is unstable API and it is subject to change.**
29+
* @param parentContext context of the parent coroutine.
30+
* @param active when `true` (by default) coroutine is created in _active_ state, when `false` in _new_ state.
31+
* See [Job] for details.
3232
*/
33+
@Suppress("EXPOSED_SUPER_CLASS")
3334
public abstract class AbstractCoroutine<in T>(
3435
private val parentContext: CoroutineContext,
35-
active: Boolean
36-
) : JobSupport(active), Continuation<T>, CoroutineScope {
36+
active: Boolean = true
37+
) : JobSupport(active), Job, Continuation<T>, CoroutineScope {
3738
@Suppress("LeakingThis")
3839
public final override val context: CoroutineContext = parentContext + this
3940
public final override val coroutineContext: CoroutineContext get() = context
4041

41-
protected open val defaultResumeMode: Int get() = MODE_ATOMIC_DEFAULT
42+
/**
43+
* Initializes parent job from the `parentContext` of this coroutine that was passed to it during construction.
44+
* It shall be invoked at most once after construction after all other initialization.
45+
*
46+
* Invocation of this function may cause this coroutine to become cancelled if parent is already cancelled,
47+
* in which case it synchronously invokes all the corresponding handlers.
48+
*/
49+
public fun initParentJob() {
50+
initParentJobInternal(parentContext[Job])
51+
}
52+
53+
/**
54+
* This function is invoked once when non-active coroutine (constructed with `active` set to `false)
55+
* is [started][start].
56+
*/
57+
protected open fun onStart() {}
58+
59+
internal final override fun onStartInternal() {
60+
onStart()
61+
}
62+
63+
/**
64+
* This function is invoked once when this coroutine is cancelled or is completed,
65+
* similarly to [invokeOnCompletion] with `onCancelling` set to `true`.
66+
*
67+
* @param cause the cause that was passed to [Job.cancel] function or `null` if coroutine was cancelled
68+
* without cause or is completing normally.
69+
*/
70+
protected open fun onCancellation(cause: Throwable?) {}
71+
72+
internal final override fun onCancellationInternal(exceptionally: CompletedExceptionally?) {
73+
onCancellation(exceptionally?.cause)
74+
}
75+
76+
/**
77+
* This function is invoked once when job is completed normally with the specified [value].
78+
*/
79+
protected open fun onCompleted(value: T) {}
80+
81+
/**
82+
* This function is invoked once when job is completed exceptionally with the specified [exception].
83+
*/
84+
protected open fun onCompletedExceptionally(exception: Throwable) {}
85+
86+
/**
87+
* Override for post-completion actions that need to do something with the state.
88+
* @param mode completion mode.
89+
* @suppress **This is unstable API and it is subject to change.**
90+
*/
91+
@Suppress("UNCHECKED_CAST")
92+
internal override fun afterCompletion(state: Any?, mode: Int) {
93+
if (state is CompletedExceptionally)
94+
onCompletedExceptionally(state.exception)
95+
else
96+
onCompleted(state as T)
97+
}
98+
99+
internal open val defaultResumeMode: Int get() = MODE_ATOMIC_DEFAULT
42100

43-
final override fun resume(value: T) {
101+
/**
102+
* Completes execution of this coroutine normally with the specified [value].
103+
*/
104+
public final override fun resume(value: T) {
44105
makeCompletingOnce(value, defaultResumeMode)
45106
}
46107

47-
final override fun resumeWithException(exception: Throwable) {
108+
/**
109+
* Completes execution of this with coroutine exceptionally with the specified [exception].
110+
*/
111+
public final override fun resumeWithException(exception: Throwable) {
48112
makeCompletingOnce(CompletedExceptionally(exception), defaultResumeMode)
49113
}
50114

51-
final override fun handleException(exception: Throwable) {
115+
internal final override fun handleException(exception: Throwable) {
52116
handleCoroutineException(parentContext, exception)
53117
}
54118

55-
override fun nameString(): String {
119+
internal override fun nameString(): String {
56120
val coroutineName = context.coroutineName ?: return super.nameString()
57121
return "\"$coroutineName\":${super.nameString()}"
58122
}

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public actual fun launch(
6262
val coroutine = if (start.isLazy)
6363
LazyStandaloneCoroutine(newContext, block) else
6464
StandaloneCoroutine(newContext, active = true)
65-
coroutine.initParentJob(newContext[Job])
65+
coroutine.initParentJob()
6666
start(block, coroutine, coroutine)
6767
return coroutine
6868
}
@@ -126,7 +126,7 @@ public actual suspend fun <T> withContext(
126126
context = newContext,
127127
delegate = cont,
128128
resumeMode = if (start == CoroutineStart.ATOMIC) MODE_ATOMIC_DEFAULT else MODE_CANCELLABLE)
129-
completion.initParentJob(newContext[Job]) // attach to job
129+
completion.initParentJobInternal(newContext[Job]) // attach to job
130130
start(block, completion)
131131
completion.getResult()
132132
}
@@ -169,7 +169,7 @@ public fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, bl
169169
val eventLoop = if (context[ContinuationInterceptor] == null) BlockingEventLoop(currentThread) else null
170170
val newContext = newCoroutineContext(context + (eventLoop ?: EmptyCoroutineContext))
171171
val coroutine = BlockingCoroutine<T>(newContext, currentThread, privateEventLoop = eventLoop != null)
172-
coroutine.initParentJob(newContext[Job])
172+
coroutine.initParentJob()
173173
block.startCoroutine(coroutine, coroutine)
174174
return coroutine.joinBlocking()
175175
}
@@ -180,9 +180,9 @@ private open class StandaloneCoroutine(
180180
private val parentContext: CoroutineContext,
181181
active: Boolean
182182
) : AbstractCoroutine<Unit>(parentContext, active) {
183-
override fun onCancellation(exceptionally: CompletedExceptionally?) {
183+
override fun onCancellation(cause: Throwable?) {
184184
// note the use of the parent's job context below!
185-
if (exceptionally != null) handleCoroutineException(parentContext, exceptionally.exception)
185+
if (cause != null) handleCoroutineException(parentContext, cause)
186186
}
187187
}
188188

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ internal class CancellableContinuationImpl<in T>(
222222
get() = _context ?: (delegate.context + this).also { _context = it }
223223

224224
override fun initCancellability() {
225-
initParentJob(delegate.context[Job])
225+
initParentJobInternal(delegate.context[Job])
226226
}
227227

228228
override val onCancelMode: Int get() = ON_CANCEL_MAKE_CANCELLED

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CompletableDeferred.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package kotlinx.coroutines.experimental
1818

19-
import kotlinx.coroutines.experimental.selects.SelectClause1
19+
import kotlinx.coroutines.experimental.selects.*
2020

2121
/**
2222
* A [Deferred] that can be completed via public functions
@@ -71,18 +71,17 @@ public actual fun <T> CompletableDeferred(value: T): CompletableDeferred<T> = Co
7171
@Suppress("UNCHECKED_CAST")
7272
private class CompletableDeferredImpl<T>(
7373
parent: Job?
74-
) : JobSupport(true), CompletableDeferred<T> {
75-
init { initParentJob(parent) }
74+
) : JobSupport(true), CompletableDeferred<T>, SelectClause1<T> {
75+
init { initParentJobInternal(parent) }
7676
override val onCancelMode: Int get() = ON_CANCEL_MAKE_COMPLETING
77-
7877
override fun getCompleted(): T = getCompletedInternal() as T
7978
override suspend fun await(): T = awaitInternal() as T
80-
override val onAwait: SelectClause1<T>
81-
get() = this as SelectClause1<T>
79+
override val onAwait: SelectClause1<T> get() = this
80+
override fun <R> registerSelectClause1(select: SelectInstance<R>, block: suspend (T) -> R) =
81+
registerSelectClause1Internal(select, block)
8282

8383
override fun complete(value: T): Boolean =
8484
makeCompleting(value)
85-
8685
override fun completeExceptionally(exception: Throwable): Boolean =
8786
makeCompleting(CompletedExceptionally(exception))
8887
}

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616

1717
package kotlinx.coroutines.experimental
1818

19-
import kotlinx.coroutines.experimental.selects.SelectClause1
20-
import kotlinx.coroutines.experimental.selects.select
19+
import kotlinx.coroutines.experimental.selects.*
2120
import kotlin.coroutines.experimental.ContinuationInterceptor
2221
import kotlin.coroutines.experimental.CoroutineContext
2322

@@ -168,7 +167,7 @@ public actual fun <T> async(
168167
val coroutine = if (start.isLazy)
169168
LazyDeferredCoroutine(newContext, block) else
170169
DeferredCoroutine<T>(newContext, active = true)
171-
coroutine.initParentJob(newContext[Job])
170+
coroutine.initParentJob()
172171
start(block, coroutine, coroutine)
173172
return coroutine
174173
}
@@ -202,11 +201,12 @@ public fun <T> defer(context: CoroutineContext, block: suspend CoroutineScope.()
202201
private open class DeferredCoroutine<T>(
203202
parentContext: CoroutineContext,
204203
active: Boolean
205-
) : AbstractCoroutine<T>(parentContext, active), Deferred<T> {
204+
) : AbstractCoroutine<T>(parentContext, active), Deferred<T>, SelectClause1<T> {
206205
override fun getCompleted(): T = getCompletedInternal() as T
207206
override suspend fun await(): T = awaitInternal() as T
208-
override val onAwait: SelectClause1<T>
209-
get() = this as SelectClause1<T>
207+
override val onAwait: SelectClause1<T> get() = this
208+
override fun <R> registerSelectClause1(select: SelectInstance<R>, block: suspend (T) -> R) =
209+
registerSelectClause1Internal(select, block)
210210
}
211211

212212
private class LazyDeferredCoroutine<T>(

0 commit comments

Comments
 (0)