Support failed channels (closed for cause), buildChannel coroutine builder
diff --git a/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt b/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
index 1b1adad..18af647 100644
--- a/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
+++ b/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CancellableContinuation.kt
@@ -29,7 +29,14 @@
fun tryResume(value: T): Any?
/**
- * Completes the execution of [tryResume] on its non-null result.
+ * Tries to resume this continuation with a given exception and returns non-null object token if it was successful,
+ * or `null` otherwise (it was already resumed or cancelled). When non-null object was returned,
+ * [completeResume] must be invoked with it.
+ */
+ fun tryResumeWithException(exception: Throwable): Any?
+
+ /**
+ * Completes the execution of [tryResume] or [tryResumeWithException] on its non-null result.
*/
fun completeResume(token: Any)
@@ -117,6 +124,16 @@
}
}
+ override fun tryResumeWithException(exception: Throwable): Any? {
+ while (true) { // lock-free loop on state
+ val state = getState() // atomic read
+ when (state) {
+ is Active -> if (tryUpdateState(state, Failed(exception))) return state
+ else -> return null // cannot resume -- not active anymore
+ }
+ }
+ }
+
override fun completeResume(token: Any) {
completeUpdateState(token, getState())
}