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())
     }