// WITH_RUNTIME // FULL_JDK import java.util.concurrent.CompletableFuture fun foo(): CompletableFuture = CompletableFuture.supplyAsync { "foo" } fun bar(v: String): CompletableFuture = CompletableFuture.supplyAsync { "bar with $v" } fun exception(v: String): CompletableFuture = CompletableFuture.supplyAsync { throw RuntimeException(v) } fun foobar(x: String, y: String) = x + y fun box(): String { var result = "" fun log(x: String) { synchronized(result) { if (result.isNotEmpty()) result += "\n" result += x } } val future = async { log("start") val x = await(foo()) log("got '$x'") val y = foobar("123 ", await(bar(x))) log("got '$y' after '$x'") y } future.whenComplete { value, t -> log("completed with '$value'") } future.join() java.lang.Thread.sleep(1000) val readResult = synchronized(result) { result } val expectedResult = """ |start |got 'foo' |got '123 bar with foo' after 'foo' |completed with '123 bar with foo'""".trimMargin().trim('\n', ' ') if (expectedResult != readResult) return readResult return "OK" } // LIBRARY CODE fun async(coroutine c: FutureController.() -> Continuation): CompletableFuture { val controller = FutureController() c(controller).resume(Unit) return controller.future } class FutureController { val future = CompletableFuture() suspend fun await(f: CompletableFuture, machine: Continuation) { f.whenComplete { value, throwable -> if (throwable == null) machine.resume(value) else machine.resumeWithException(throwable) } } operator fun handleResult(value: T, c: Continuation) { future.complete(value) } fun handleException(t: Throwable, c: Continuation) { future.completeExceptionally(t) } }