Kooma is a Kotlin library for structured concurrency with virtual threads, inspired by coroutines.
It wraps Java's StructuredTaskScope with a kotlinx coroutine-style API, making concurrent code simpler and more expressive.
Add the following dependency to your build.gradle.kts file:
dependencies {
implementation("io.github.bgmsound:kooma:${version}")
}fun main() {
taskScope {
val a = async { sleep(300); "Hello" }
val b = async { sleep(300); "World" }
println("${a.await()} ${b.await()}") // "Hello World"
}
}All tasks inside a scope run on virtual threads concurrently. The scope blocks until every subtask completes — or cancels all remaining tasks if any one of them throws.
taskScope
Blocks until all subtasks complete. Any exception is propagated to the entire scope and cancels remaining tasks.
fun main() {
val elapsed = measureTimeMillis {
taskScope {
val a = async { sleep(500); 1 }
val b = async { sleep(500); 2 }
println(a.await() + b.await()) // 3
}
}
println("Elapsed: ${elapsed}ms") // ~500ms, not ~1000ms
}supervisorTaskScope
Each subtask runs independently. Failures are isolated and surfaced only when calling await() on the failed task.
fun main() {
supervisorTaskScope {
val risky = async {
sleep(100)
throw RuntimeException("oops")
}
val safe = async {
sleep(300)
42
}
runCatching { risky.await() }.onFailure { println("caught: ${it.message}") }
println(safe.await()) // 42
}
}asyncTaskScope / asyncSupervisorTaskScope
Runs the entire scope on a new virtual thread and returns a Deferred<T> immediately, without blocking the caller.
Useful when you want to isolate a scope from its parent or kick off background work.
fun main() {
val deferred = asyncTaskScope {
val a = async { sleep(500); "A" }
val b = async { sleep(500); "B" }
a.await() + b.await()
}
println("doing other work...")
println(deferred.await()) // "AB"
}async returns a Deferred<T>, which can be awaited individually or converted to a CompletableFuture<T> via asCompletableFuture().
This makes it easy to bridge into existing CompletableFuture-based code.
fun main() {
taskScope {
val a = async { sleep(300); "Hello" }
val b = async { sleep(300); "World" }
val future = b.asCompletableFuture()
.thenApply { it.uppercase() }
println(a.await()) // "Hello"
println(future.get()) // "WORLD"
}
}If the Deferred is already complete when asCompletableFuture() is called, it returns an already-completed CompletableFuture.
Otherwise, the CompletableFuture completes at the same time the Deferred does.
[click to see more sample code]
kooma is Open Source software released under the Apache 2.0 license.