Skip to content

Commit c581454

Browse files
committed
Deferred.getCompleted() and an efficient implementation of Deferred.toCompletableFuture() extension
1 parent 3754f95 commit c581454

File tree

5 files changed

+23
-8
lines changed

5 files changed

+23
-8
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private class StandaloneCoroutine(
5959
val parentContext: CoroutineContext
6060
) : JobContinuation<Unit>(parentContext) {
6161
override fun afterCompletion(state: Any?, closeException: Throwable?) {
62-
if (closeException != null) handleCoroutineException(context, closeException)
62+
super.afterCompletion(state, closeException) // handle closeException
6363
// note the use of the parent context below!
6464
if (state is CompletedExceptionally) handleCoroutineException(parentContext, state.exception)
6565
}
@@ -69,7 +69,7 @@ private class BlockingCoroutine<T>(parentContext: CoroutineContext) : JobContinu
6969
val blockedThread: Thread = Thread.currentThread()
7070

7171
override fun afterCompletion(state: Any?, closeException: Throwable?) {
72-
if (closeException != null) handleCoroutineException(context, closeException)
72+
super.afterCompletion(state, closeException) // handle closeException
7373
LockSupport.unpark(blockedThread)
7474
}
7575

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
@@ -47,7 +47,7 @@ internal class SafeCancellableContinuation<in T>(
4747

4848
@Suppress("UNCHECKED_CAST")
4949
override fun afterCompletion(state: Any?, closeException: Throwable?) {
50-
if (closeException != null) handleCoroutineException(context, closeException)
50+
super.afterCompletion(state, closeException) // handle closeException
5151
if (suspendedThread === Thread.currentThread()) {
5252
// cancelled during suspendCancellableCoroutine in its thread
5353
suspendedThread = null

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,17 @@ public interface Deferred<out T> : Job {
1212
* Awaits for completion of this value without blocking a thread and resumes when deferred computation is complete.
1313
* This suspending function is cancellable.
1414
* If the [Job] of the current coroutine is completed while this suspending function is waiting, this function
15-
* immediately resumes with [CancellationException] .
15+
* immediately resumes with [CancellationException].
1616
*/
1717
public suspend fun await(): T
18+
19+
/**
20+
* Returns *completed* result or throws [IllegalStateException] if this deferred value is still [isActive].
21+
* It throws the corresponding exception if this deferred has completed exceptionally.
22+
* This function is designed to be used from [onCompletion] handlers, when there is an absolute certainty that
23+
* the value is already complete.
24+
*/
25+
public fun getCompleted(): T
1826
}
1927

2028
/**
@@ -54,7 +62,11 @@ private class DeferredCoroutine<T>(
5462
})
5563
}
5664

57-
override fun afterCompletion(state: Any?, closeException: Throwable?) {
58-
if (closeException != null) handleCoroutineException(context, closeException)
65+
@Suppress("UNCHECKED_CAST")
66+
override fun getCompleted(): T {
67+
val state = getState()
68+
check(state !is Active) { "This deferred value is still active" }
69+
if (state is CompletedExceptionally) throw state.exception
70+
return state as T
5971
}
6072
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,8 @@ internal open class JobContinuation<in T>(
3535
}
3636
}
3737
}
38+
39+
override fun afterCompletion(state: Any?, closeException: Throwable?) {
40+
if (closeException != null) handleCoroutineException(context, closeException)
41+
}
3842
}

kotlinx-coroutines-jdk8/src/main/kotlin/kotlinx/coroutines/experimental/future/Future.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,8 @@ public fun <T> Deferred<T>.toCompletableFuture(): CompletableFuture<T> {
3535
val future = CompletableFuture<T>()
3636
future.whenComplete { _, exception -> cancel(exception) }
3737
onCompletion {
38-
// todo: write better (more efficient) implementation, because we know that await will not suspend
3938
try {
40-
future.complete(runBlocking(Job() + Here) { await() })
39+
future.complete(getCompleted())
4140
} catch (exception: Exception) {
4241
future.completeExceptionally(exception)
4342
}

0 commit comments

Comments
 (0)