Skip to content

Instantly share code, notes, and snippets.

@nomisRev
Last active July 19, 2023 13:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nomisRev/952c619fa40c7c0041974992a6ad1e06 to your computer and use it in GitHub Desktop.
Save nomisRev/952c619fa40c7c0041974992a6ad1e06 to your computer and use it in GitHub Desktop.
A Kotlin DSL for AutoCloseable
import arrow.atomic.Atomic
import arrow.atomic.update
/**
* AutoClose offers DSL style API for creating parent-child relationships of AutoCloseable dependencies
*/
interface AutoClose : AutoCloseable {
fun <A : AutoCloseable> autoClose(autoCloseable: A): A
}
/** DSL method to use AutoClose */
fun <A> autoClose(block: AutoClose.() -> A): A =
AutoClose().use(block)
/**
* Constructor for AutoClose to be use for interface delegation of already scoped classes.
*/
fun AutoClose(): AutoClose =
object : AutoClose {
private val finalizers: Atomic<List<() -> Unit>> = Atomic(emptyList())
fun <A : AutoCloseable> autoClose(autoCloseable: A): A {
finalizers.update { prev -> prev + autoCloseable::close }
return autoCloseable
}
fun close() {
finalizers.get().fold<() -> Unit, Throwable?>(null) { acc, function ->
acc.add(runCatching { function.invoke() }.exceptionOrNull())
}?.let { throw it }
}
}
private fun Throwable?.add(other: Throwable?): Throwable? =
this?.apply {
other?.let { addSuppressed(it) }
} ?: other
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment