Skip to content

Commit 361c781

Browse files
committed
CompletableJob support added
Fixes #607
1 parent 23eb49a commit 361c781

File tree

7 files changed

+126
-10
lines changed

7 files changed

+126
-10
lines changed

binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt

+20-2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@ public final class kotlinx/coroutines/CompletableDeferredKt {
117117
public static synthetic fun CompletableDeferred$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableDeferred;
118118
}
119119

120+
public abstract interface class kotlinx/coroutines/CompletableJob : kotlinx/coroutines/Job {
121+
public abstract fun complete ()Z
122+
public abstract fun completeExceptionally (Ljava/lang/Throwable;)Z
123+
}
124+
125+
public final class kotlinx/coroutines/CompletableJob$DefaultImpls {
126+
public static synthetic fun cancel (Lkotlinx/coroutines/CompletableJob;)Z
127+
public static fun fold (Lkotlinx/coroutines/CompletableJob;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
128+
public static fun get (Lkotlinx/coroutines/CompletableJob;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
129+
public static fun minusKey (Lkotlinx/coroutines/CompletableJob;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
130+
public static fun plus (Lkotlinx/coroutines/CompletableJob;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
131+
public static fun plus (Lkotlinx/coroutines/CompletableJob;Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job;
132+
}
133+
120134
public final class kotlinx/coroutines/CompletionHandlerException : java/lang/RuntimeException {
121135
public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
122136
}
@@ -315,7 +329,9 @@ public final class kotlinx/coroutines/Job$Key : kotlin/coroutines/CoroutineConte
315329

316330
public final class kotlinx/coroutines/JobKt {
317331
public static final fun DisposableHandle (Lkotlin/jvm/functions/Function0;)Lkotlinx/coroutines/DisposableHandle;
318-
public static final fun Job (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job;
332+
public static final fun Job (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob;
333+
public static final synthetic fun Job (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job;
334+
public static synthetic fun Job$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
319335
public static synthetic fun Job$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
320336
public static final fun cancel (Lkotlin/coroutines/CoroutineContext;)V
321337
public static final synthetic fun cancel (Lkotlin/coroutines/CoroutineContext;)Z
@@ -422,7 +438,9 @@ public final class kotlinx/coroutines/RunnableKt {
422438
}
423439

424440
public final class kotlinx/coroutines/SupervisorKt {
425-
public static final fun SupervisorJob (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job;
441+
public static final fun SupervisorJob (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob;
442+
public static final synthetic fun SupervisorJob (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job;
443+
public static synthetic fun SupervisorJob$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
426444
public static synthetic fun SupervisorJob$default (Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
427445
public static final fun supervisorScope (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
428446
}

kotlinx-coroutines-core/common/src/CompletableDeferred.kt

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public interface CompletableDeferred<T> : Deferred<T> {
2525
* completed as a result of this invocation and `false` otherwise (if it was already completed).
2626
*
2727
* Repeated invocations of this function have no effect and always produce `false`.
28+
*
29+
* Note, that if this deferred has children, then it transitions into _completing_ state and becomes _complete_
30+
* once all its children are _complete_. See [Job] for details.
2831
*/
2932
public fun complete(value: T): Boolean
3033

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+
/**
8+
* A job that can be completed using [complete()] function.
9+
* It is returned by [Job()][Job] and [SupervisorJob()][SupervisorJob] constructor functions.
10+
*/
11+
public interface CompletableJob : Job {
12+
/**
13+
* Completes this job. The result is `true` if this job was completed as a result of this invocation and
14+
* `false` otherwise (if it was already completed).
15+
*
16+
* Repeated invocations of this function have no effect and always produce `false`.
17+
*
18+
* Note, that if this job has children, then it transitions into _completing_ state and becomes _complete_
19+
* once all its children are _complete_. See [Job] for details.
20+
*/
21+
public fun complete(): Boolean
22+
23+
/**
24+
* Completes this job exceptionally with a given [exception]. The result is `true` if this job was
25+
* completed as a result of this invocation and `false` otherwise (if it was already completed).
26+
*
27+
* Repeated invocations of this function have no effect and always produce `false`.
28+
*/
29+
public fun completeExceptionally(exception: Throwable): Boolean
30+
}

kotlinx-coroutines-core/common/src/Job.kt

+12-1
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,21 @@ public interface Job : CoroutineContext.Element {
348348
* is cancelled when its parent fails or is cancelled. All this job's children are cancelled in this case, too.
349349
* The invocation of [cancel][Job.cancel] with exception (other than [CancellationException]) on this job also cancels parent.
350350
*
351+
* Conceptually, the resulting job works in the same way as the job created by the `launch { body }` invocation
352+
* (see [launch]), but without any code in the body. It is active until cancelled or completed. Invocation of
353+
* [CompletableJob.complete] or [CompletableJob.completeExceptionally] corresponds to the successful or
354+
* failed completion of the body of the coroutine.
355+
*
351356
* @param parent an optional parent job.
352357
*/
353358
@Suppress("FunctionName")
354-
public fun Job(parent: Job? = null): Job = JobImpl(parent)
359+
public fun Job(parent: Job? = null): CompletableJob = JobImpl(parent)
360+
361+
/** @suppress Binary compatibility only */
362+
@Suppress("FunctionName")
363+
@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility")
364+
@JvmName("Job")
365+
public fun Job0(parent: Job? = null): Job = Job(parent)
355366

356367
/**
357368
* A handle to an allocated object that can be disposed to make it eligible for garbage collection.

kotlinx-coroutines-core/common/src/JobSupport.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -1182,11 +1182,14 @@ private class Empty(override val isActive: Boolean) : Incomplete {
11821182
override fun toString(): String = "Empty{${if (isActive) "Active" else "New" }}"
11831183
}
11841184

1185-
internal class JobImpl(parent: Job? = null) : JobSupport(true) {
1185+
internal open class JobImpl(parent: Job?) : JobSupport(true), CompletableJob {
11861186
init { initParentJobInternal(parent) }
11871187
override val cancelsParent: Boolean get() = true
11881188
override val onCancelComplete get() = true
11891189
override val handlesException: Boolean get() = false
1190+
override fun complete() = makeCompleting(Unit)
1191+
override fun completeExceptionally(exception: Throwable): Boolean =
1192+
makeCompleting(CompletedExceptionally(exception))
11901193
}
11911194

11921195
// -------- invokeOnCompletion nodes

kotlinx-coroutines-core/common/src/Supervisor.kt

+8-6
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@ import kotlin.jvm.*
2828
* @param parent an optional parent job.
2929
*/
3030
@Suppress("FunctionName")
31-
public fun SupervisorJob(parent: Job? = null) : Job = SupervisorJobImpl(parent)
31+
public fun SupervisorJob(parent: Job? = null) : CompletableJob = SupervisorJobImpl(parent)
32+
33+
/** @suppress Binary compatibility only */
34+
@Suppress("FunctionName")
35+
@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility")
36+
@JvmName("SupervisorJob")
37+
public fun SupervisorJob0(parent: Job? = null) : Job = SupervisorJob(parent)
3238

3339
/**
3440
* Creates new [CoroutineScope] with [SupervisorJob] and calls the specified suspend block with this scope.
@@ -46,11 +52,7 @@ public suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R):
4652
coroutine.startUndispatchedOrReturn(coroutine, block)
4753
}
4854

49-
private class SupervisorJobImpl(parent: Job?) : JobSupport(true) {
50-
init { initParentJobInternal(parent) }
51-
override val cancelsParent: Boolean get() = true
52-
override val onCancelComplete get() = true
53-
override val handlesException: Boolean get() = false
55+
private class SupervisorJobImpl(parent: Job?) : JobImpl(parent) {
5456
override fun childCancelled(cause: Throwable): Boolean = false
5557
}
5658

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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.test.*
8+
9+
class CompletableJobTest {
10+
@Test
11+
fun testComplete() {
12+
val job = Job()
13+
assertTrue(job.isActive)
14+
assertFalse(job.isCompleted)
15+
assertTrue(job.complete())
16+
assertTrue(job.isCompleted)
17+
assertFalse(job.isActive)
18+
assertFalse(job.isCancelled)
19+
assertFalse(job.complete())
20+
}
21+
22+
@Test
23+
fun testCompleteWithException() {
24+
val job = Job()
25+
assertTrue(job.isActive)
26+
assertFalse(job.isCompleted)
27+
assertTrue(job.completeExceptionally(TestException()))
28+
assertTrue(job.isCompleted)
29+
assertFalse(job.isActive)
30+
assertTrue(job.isCancelled)
31+
assertFalse(job.completeExceptionally(TestException()))
32+
assertFalse(job.complete())
33+
}
34+
35+
@Test
36+
fun testCompleteWithChildren() {
37+
val parent = Job()
38+
val child = Job(parent)
39+
assertTrue(parent.complete())
40+
assertFalse(parent.complete())
41+
assertTrue(parent.isActive)
42+
assertFalse(parent.isCompleted)
43+
assertTrue(child.complete())
44+
assertTrue(child.isCompleted)
45+
assertTrue(parent.isCompleted)
46+
assertFalse(child.isActive)
47+
assertFalse(parent.isActive)
48+
}
49+
}

0 commit comments

Comments
 (0)