com.kamelia.sprinkler.util.CloseableScope.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils Show documentation
Show all versions of utils Show documentation
Sprinkler@utils | Black Kamelia
The newest version!
@file:HideFromJava("This is a Kotlin only API")
package com.kamelia.sprinkler.util
import com.zwendo.restrikt.annotation.HideFromJava
/**
* A scope for managing the lifecycle of [AutoCloseable]s.
*/
@JvmInline
value class CloseableScope private constructor(private val closeables: ArrayList) {
@PublishedApi
internal constructor() : this(ArrayList())
/**
* Adds a [AutoCloseable] to the scope. When the scope ends, this [AutoCloseable] will be closed.
*
* @param closeable The [AutoCloseable] to add.
* @param T The type of the given [AutoCloseable].
* @return The [AutoCloseable] that was added.
*/
fun using(closeable: T): T = closeable.also(closeables::add)
/**
* Adds a [AutoCloseable] to the scope. When the scope ends, this [AutoCloseable] will be closed.
*
* @receiver The [AutoCloseable] to add.
* @param T The type of the received [AutoCloseable].
* @return The [AutoCloseable] that was added.
*/
fun T.usingSelf(): T = using(this)
@PublishedApi
internal fun closeAll() {
var exception: Throwable? = null
for (i in closeables.lastIndex downTo 0) {
try {
closeables[i].close()
} catch (e: Throwable) {
if (exception == null) {
exception = e
} else {
exception.addSuppressed(e)
}
}
}
exception?.let { throw it }
}
}
/**
* Creates a [CloseableScope] and adds the given [AutoCloseable]s to it.
* Within the scope, one can use the [CloseableScope.using] function to add more [AutoCloseable]s.
* When the scope ends, all registered [AutoCloseable]s will be closed.
*
* ```
* val someCloseable = MyCloseable()
* val ok = closeableScope(someCloseable) {
* val sin = using(System.`in`)
* val f = File("someFile")
* .inputStream().usingSelf()
* .buffered().usingSelf()
*
* // Do stuff with sin and f
*
* true
* }
* ```
*
* @param closeables The initial [AutoCloseable]s to add to the scope.
* @param block The block to execute in the scope.
* @param R The return type of the scope.
* @return The result of the block.
*/
inline fun closeableScope(vararg closeables: AutoCloseable, block: CloseableScope.() -> R): R {
val scope = CloseableScope()
closeables.forEach(scope::using)
try {
return scope.block()
} finally {
scope.closeAll()
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy