CoroutineContext and ContinuationInterceptor (instead of dispatcher)

This commit is contained in:
Roman Elizarov
2017-01-13 21:01:57 +03:00
committed by Denis Zharkov
parent f611e39a69
commit 8d6a913cee
22 changed files with 507 additions and 148 deletions
@@ -34,6 +34,8 @@ class AsyncGeneratorIterator<T>: AsyncIterator<T>, AsyncGenerator<T>, Continuati
var computesNext = false
var computeContinuation: Continuation<*>? = null
override val context = EmptyContext
suspend fun computeHasNext(): Boolean = suspendCoroutineOrReturn { c ->
computesNext = false
computeContinuation = c
@@ -9,6 +9,8 @@ fun builder(c: suspend () -> Unit) {
var exception: Throwable? = null
c.createCoroutine(object : Continuation<Unit> {
override val context = EmptyContext
override fun resume(data: Unit) {
}
@@ -24,6 +24,8 @@ class Controller {
fun builder(c: suspend Controller.() -> Unit): String {
val controller = Controller()
c.startCoroutine(controller, object : Continuation<Unit> {
override val context = EmptyContext
override fun resume(data: Unit) {
}
@@ -17,6 +17,8 @@ class Controller {
fun builder(c: suspend Controller.() -> Unit): String {
val controller = Controller()
c.startCoroutine(controller, object : Continuation<Unit> {
override val context = EmptyContext
override fun resume(data: Unit) {}
override fun resumeWithException(exception: Throwable) {
+2 -2
View File
@@ -23,7 +23,7 @@ class Controller {
fun test(c: suspend Controller.() -> Unit): String {
val controller = Controller()
c.startCoroutine(controller, EmptyContinuation, object: ContinuationDispatcher {
c.startCoroutine(controller, EmptyContinuation(object: ContinuationDispatcher() {
private fun dispatchResume(block: () -> Unit) {
val id = controller.resumeIndex++
controller.log += "before $id;"
@@ -44,7 +44,7 @@ fun test(c: suspend Controller.() -> Unit): String {
}
return true
}
})
}))
return controller.log
}
+2
View File
@@ -39,6 +39,8 @@ class GeneratedSequence<out T>(private val block: suspend Generator<T>.() -> Uni
class GeneratedIterator<T>(block: suspend Generator<T>.() -> Unit) : AbstractIterator<T>(), Generator<T> {
private var nextStep: Continuation<Unit> = block.createCoroutine(this, object : Continuation<Unit> {
override val context = EmptyContext
override fun resume(data: Unit) {
done()
}
@@ -15,6 +15,7 @@ var result = ""
fun builder(c: suspend () -> Unit) {
c.startCoroutine(object : Continuation<Unit> {
override val context = EmptyContext
override fun resume(value: Unit) {
}
override fun resumeWithException(exception: Throwable) {
@@ -12,6 +12,8 @@ fun builder(c: suspend () -> Int): Int {
var res = 0
c.createCoroutine(object : Continuation<Int> {
override val context = EmptyContext
override fun resume(data: Int) {
res = data
}
@@ -23,7 +23,7 @@ class Controller {
fun test(c: suspend Controller.() -> Unit): String {
val controller = Controller()
c.startCoroutine(controller, EmptyContinuation, object: ContinuationDispatcher {
c.startCoroutine(controller, EmptyContinuation(object: ContinuationDispatcher() {
private fun dispatchResume(block: () -> Unit) {
val id = controller.resumeIndex++
controller.log += "before $id;"
@@ -44,7 +44,7 @@ fun test(c: suspend Controller.() -> Unit): String {
}
return true
}
})
}))
return controller.log
}
@@ -11,6 +11,8 @@ suspend fun suspendHere(): String = suspendCoroutineOrReturn { x ->
fun builder(c: suspend () -> Unit) {
var wasResumeCalled = false
c.startCoroutine(object : Continuation<Unit> {
override val context = EmptyContext
override fun resume(value: Unit) {
wasResumeCalled = true
}
@@ -11,6 +11,8 @@ suspend fun suspendHere(): String = suspendCoroutineOrReturn { x ->
fun builder(c: suspend () -> Unit) {
var wasResumeCalled = false
c.startCoroutine(object : Continuation<Unit> {
override val context = EmptyContext
override fun resume(value: Unit) {
wasResumeCalled = true
}
@@ -649,6 +649,7 @@ public class KotlinTestUtils {
"CoroutineUtil.kt",
"import kotlin.coroutines.*\n" +
"fun <T> handleResultContinuation(x: (T) -> Unit): Continuation<T> = object: Continuation<T> {\n" +
" override val context = EmptyContext\n" +
" override fun resumeWithException(exception: Throwable) {\n" +
" throw exception\n" +
" }\n" +
@@ -657,6 +658,7 @@ public class KotlinTestUtils {
"}\n" +
"\n" +
"fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = object: Continuation<Any?> {\n" +
" override val context = EmptyContext\n" +
" override fun resumeWithException(exception: Throwable) {\n" +
" x(exception)\n" +
" }\n" +
@@ -664,11 +666,44 @@ public class KotlinTestUtils {
" override fun resume(data: Any?) { }\n" +
"}\n" +
"\n" +
"object EmptyContinuation : Continuation<Any?> {\n" +
"object EmptyContext : CoroutineContext {\n" +
" override fun <E : CoroutineContextElement> get(key: CoroutineContextKey<E>): E? = null\n" +
" override fun <R> fold(initial: R, operation: (R, CoroutineContextElement) -> R): R = initial\n" +
" override fun plus(context: CoroutineContext): CoroutineContext = context\n" +
" override fun minusKey(key: CoroutineContextKey<*>): CoroutineContext = this\n" +
"}\n" +
"\n" +
"open class EmptyContinuation(override val context: CoroutineContext = EmptyContext) : Continuation<Any?> {\n" +
" companion object : EmptyContinuation()\n" +
" override fun resume(data: Any?) {}\n" +
" override fun resumeWithException(exception: Throwable) { throw exception }\n" +
"}\n" +
"\n" +
"abstract class ContinuationDispatcher : ContinuationInterceptor {\n" +
" override val contextKey: CoroutineContextKey<*> = ContinuationInterceptor\n" +
" abstract fun <T> dispatchResume(value: T, continuation: Continuation<T>): Boolean\n" +
" abstract fun dispatchResumeWithException(exception: Throwable, continuation: Continuation<*>): Boolean\n" +
" override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> = DispatchedContinuation(this, continuation)\n" +
" override operator fun <E : CoroutineContextElement> get(key: CoroutineContextKey<E>): E? = if (this.contextKey == key) this as E else null\n" +
" override fun <R> fold(initial: R, operation: (R, CoroutineContextElement) -> R): R = operation(initial, this)\n" +
" override operator fun plus(context: CoroutineContext): CoroutineContext = this\n" +
" override fun minusKey(key: CoroutineContextKey<*>): CoroutineContext = if (this.contextKey == key) EmptyContext else this\n" +
"}\n" +
"\n" +
"private class DispatchedContinuation<T>(\n" +
" val dispatcher: ContinuationDispatcher,\n" +
" val continuation: Continuation<T>\n" +
"): Continuation<T> {\n" +
" override val context: CoroutineContext = continuation.context\n" +
"\n" +
" override fun resume(value: T) {\n" +
" if (!dispatcher.dispatchResume(value, continuation))\n" +
" continuation.resume(value)\n" +
" }\n" +
"\n" +
" override fun resumeWithException(exception: Throwable) {\n" +
" throw exception\n" +
" if (!dispatcher.dispatchResumeWithException(exception, continuation))\n" +
" continuation.resumeWithException(exception)\n" +
" }\n" +
"}",
directives