Skip to content

Commit 4cf9dd2

Browse files
committed
CompletableDeferred constructor with parent Job added
1 parent 447b88a commit 4cf9dd2

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,30 @@ public interface CompletableDeferred<T> : Deferred<T> {
7171

7272
/**
7373
* Creates a [CompletableDeferred] in an _active_ state.
74+
* It is optionally a child of a [parent] job.
7475
*/
75-
public fun <T> CompletableDeferred(): CompletableDeferred<T> = CompletableDeferredImpl()
76+
@Suppress("FunctionName")
77+
public fun <T> CompletableDeferred(parent: Job? = null): CompletableDeferred<T> = CompletableDeferredImpl(parent)
78+
79+
/** @suppress **Deprecated:** Binary compatibility only */
80+
@Deprecated(message = "Binary compatibility only", level = DeprecationLevel.HIDDEN)
81+
@Suppress("FunctionName")
82+
public fun <T> CompletableDeferred(): CompletableDeferred<T> = CompletableDeferredImpl(null)
7683

7784
/**
7885
* Creates an already _completed_ [CompletableDeferred] with a given [value].
7986
*/
80-
public fun <T> CompletableDeferred(value: T): CompletableDeferred<T> = CompletableDeferredImpl<T>().apply { complete(value) }
87+
@Suppress("FunctionName")
88+
public fun <T> CompletableDeferred(value: T): CompletableDeferred<T> = CompletableDeferredImpl<T>(null).apply { complete(value) }
8189

8290
/**
8391
* Concrete implementation of [CompletableDeferred].
8492
*/
8593
@Suppress("UNCHECKED_CAST")
86-
private class CompletableDeferredImpl<T> : JobSupport(true), CompletableDeferred<T> {
94+
private class CompletableDeferredImpl<T>(
95+
parent: Job?
96+
) : JobSupport(true), CompletableDeferred<T> {
97+
init { initParentJob(parent) }
8798
override fun getCompleted(): T = getCompletedInternal() as T
8899
suspend override fun await(): T = awaitInternal() as T
89100
override val onAwait: SelectClause1<T>

core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/CompletableDeferredTest.kt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ class CompletableDeferredTest : TestBase() {
2727
@Test
2828
fun testFresh() {
2929
val c = CompletableDeferred<String>()
30+
checkFresh(c)
31+
}
32+
33+
private fun checkFresh(c: CompletableDeferred<String>) {
3034
assertThat(c.isActive, IsEqual(true))
3135
assertThat(c.isCancelled, IsEqual(false))
3236
assertThat(c.isCompleted, IsEqual(false))
@@ -112,6 +116,50 @@ class CompletableDeferredTest : TestBase() {
112116
assertThat(c.getCompletionExceptionOrNull(), IsInstanceOf(TestException::class.java))
113117
}
114118

119+
@Test
120+
fun testParentCancelsChild() {
121+
val parent = Job()
122+
val c = CompletableDeferred<String>(parent)
123+
checkFresh(c)
124+
parent.cancel()
125+
assertThat(parent.isActive, IsEqual(false))
126+
assertThat(parent.isCancelled, IsEqual(true))
127+
checkCancel(c)
128+
}
129+
130+
@Test
131+
fun testParentActiveOnChildCompletion() {
132+
val parent = Job()
133+
val c = CompletableDeferred<String>(parent)
134+
checkFresh(c)
135+
assertThat(parent.isActive, IsEqual(true))
136+
assertThat(c.complete("OK"), IsEqual(true))
137+
checkCompleteOk(c)
138+
assertThat(parent.isActive, IsEqual(true))
139+
}
140+
141+
@Test
142+
fun testParentActiveOnChildException() {
143+
val parent = Job()
144+
val c = CompletableDeferred<String>(parent)
145+
checkFresh(c)
146+
assertThat(parent.isActive, IsEqual(true))
147+
assertThat(c.completeExceptionally(TestException()), IsEqual(true))
148+
checkCompleteTestException(c)
149+
assertThat(parent.isActive, IsEqual(true))
150+
}
151+
152+
@Test
153+
fun testParentActiveOnChildCancellation() {
154+
val parent = Job()
155+
val c = CompletableDeferred<String>(parent)
156+
checkFresh(c)
157+
assertThat(parent.isActive, IsEqual(true))
158+
assertThat(c.cancel(), IsEqual(true))
159+
checkCancel(c)
160+
assertThat(parent.isActive, IsEqual(true))
161+
}
162+
115163
@Test
116164
fun testAwait() = runBlocking {
117165
expect(1)

0 commit comments

Comments
 (0)