diff --git a/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/jvm/internal/RunSuspend.kt b/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/jvm/internal/RunSuspend.kt new file mode 100644 index 00000000000..a2ff089cada --- /dev/null +++ b/libraries/stdlib/coroutines/jvm/src/kotlin/coroutines/jvm/internal/RunSuspend.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package kotlin.coroutines.jvm.internal + +import kotlin.coroutines.Continuation +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext +import kotlin.coroutines.startCoroutine + +/** + * Wrapper for `suspend fun main` and `@Test suspend fun testXXX` functions. + */ +@SinceKotlin("1.3") +internal fun runSuspend(block: suspend () -> Unit) { + val run = RunSuspend() + block.startCoroutine(run) + run.await() +} + +private class RunSuspend : Continuation { + override val context: CoroutineContext + get() = EmptyCoroutineContext + + var result: SuccessOrFailure? = null + + override fun resumeWith(result: SuccessOrFailure) = synchronized(this) { + this.result = result + (this as Object).notifyAll() + } + + fun await() = synchronized(this) { + while (true) { + when (val result = this.result) { + null -> (this as Object).wait() + else -> { + result.getOrThrow() // throw up failure + return + } + } + } + } +}