Last active
July 19, 2023 13:03
-
-
Save nomisRev/952c619fa40c7c0041974992a6ad1e06 to your computer and use it in GitHub Desktop.
A Kotlin DSL for AutoCloseable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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