[history] Functionality extracted from some class

This commit is contained in:
Andrew Golovashevich 2025-03-18 20:28:40 +03:00
commit be4c578491

View File

@ -0,0 +1,56 @@
package ru.landrafhomyak.utility.reference_counter
import kotlinx.atomicfu.AtomicLong
import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.update
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
internal class CloseableReferenceCounter(private val _errMessage: String) {
private val _value: AtomicLong = atomic(0L)
fun throwClosed() {
throw IllegalStateException(this._errMessage)
}
fun incref() {
this._value.update { o ->
if (o < 0) this.throwClosed()
return@update o + 1
}
}
inline fun <R> tryIncref(block: () -> R): R {
this.incref()
return safeAutoClose2(onError = this::decref, action = block)
}
fun checkNotClosed() {
if (this._value.value < 0) this.throwClosed()
}
fun decref() {
this._value.update(Long::dec)
}
fun close(errExistRefs: String) {
val state = this._value.compareAndExchange(0, -1)
when {
state > 0 -> throw IllegalStateException(errExistRefs)
state < 0 -> this.throwClosed()
}
}
inline fun <R> withRef(protected: () -> R): R {
this.incref()
return safeAutoClose1(finally = this::decref, action = protected)
}
private fun AtomicLong.compareAndExchange(expected: Long, newValue: Long): Long {
while (true) {
val old = this@compareAndExchange.value
if (old != expected) return old
if (this@compareAndExchange.compareAndSet(old, newValue)) return old
}
}
}