【发布时间】:2017-06-16 14:51:26
【问题描述】:
我实现了自己的async,我无法以正确的方式处理异常。为什么?
val expected = IllegalStateException();
val it = async<Any> {
throw expected;
};
assert.that({ it.get() }, throws(equalTo(expected)));
// ^--- but it throws a IllegalStateException(cause = expected)
源代码
interface Response<in T> {
suspend fun yield(value: T);
}
interface Request<out T> {
fun get(): T;
fun <R> then(mapping: (T) -> R): Request<R>;
}
private val executor: ExecutorService = ForkJoinPool(20);
fun <T> async(block: suspend Response<T>.() -> Unit): Request<T> {
return object : Request<T>, Response<T> {
@Volatile var value: T? = null;
var request: Continuation<Unit>? = block.createCoroutine(this, delegate {}).let {
var task: Future<*>? = executor.submit { it.resume(Unit); };
return@let delegate {
try {
val current = task!!;
task = null;
current.get();
} catch(e: ExecutionException) {
throw e.cause ?: e;
}
};
};
override fun <R> then(mapping: (T) -> R): Request<R> = async<R> {
yield(mapping(get()));
};
override fun get(): T {
return value ?: wait();
}
private fun wait(): T {
val it = request!!;
request = null;
it.resume(Unit);
return value!!;
}
suspend override fun yield(value: T) {
this.value = value;
}
};
}
inline fun <T> delegate(noinline exceptional: (Throwable) -> Unit = { throw it; }, crossinline resume: (T) -> Unit): Continuation<T> {
return object : Continuation<T> {
override val context: CoroutineContext = EmptyCoroutineContext;
override fun resumeWithException(exception: Throwable) {
exceptional(exception);
}
override fun resume(value: T) {
resume(value);
}
}
}
【问题讨论】:
标签: asynchronous kotlin coroutine