From 140b463ce896f9de227e79d5a1dcb9da7758734f Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Wed, 13 Aug 2025 14:23:56 +0300 Subject: [PATCH] 'close' method moved to separate class; `autoClosed` scope --- .gitignore | 3 +- .../CloseableReferenceCounter.kt | 101 ++++-------------- .../MayBeClosedReferenceCounter.kt | 91 ++++++++++++++++ 3 files changed, 113 insertions(+), 82 deletions(-) create mode 100644 src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt diff --git a/.gitignore b/.gitignore index f2e4e0d..116ea92 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ build/ *.jar /out/ /gradlew* -.kotlin/ \ No newline at end of file +.kotlin/ +/kotlin-js-store \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt b/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt index cd0bc3b..ebc959b 100644 --- a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt +++ b/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt @@ -1,90 +1,29 @@ -@file:OptIn(ExperimentalContracts::class) - package ru.landrafhomyak.utility.reference_counter -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract import kotlin.jvm.JvmName -import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 -import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2 +import kotlin.jvm.JvmStatic -public class CloseableReferenceCounter { - private val _value: _AtomicLong - private val _errMessageClosed: String - - public constructor(errMessageClosed: String) { - _Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed") - this._errMessageClosed = errMessageClosed - this._value = _AtomicLong(0L) - } - - @JvmName("throwClosed") - public fun throwClosed() { - throw IllegalStateException(this._errMessageClosed) - } - - @JvmName("incref") - public fun incref() { - this._value.update { o -> - if (o < 0) this.throwClosed() - return@update o + 1 - } - } - - @JvmName("tryIncref\$kt") - public inline fun tryIncref(block: () -> R): R { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - this.incref() - return safeAutoClose2(onError = this::decref, action = block) - } - - @JvmName("assertNotClosed") - public fun assertNotClosed() { - if (this._value.get() < 0) this.throwClosed() - } - - @JvmName("decref") - public fun decref() { - this._value.update(Long::dec) - } - - @JvmName("tryDecref\$kt") - public inline fun tryDecref(block: () -> R): R { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - this.assertNotClosed() - return safeAutoClose2(onSuccess = this::decref, action = block) - } - - @get:JvmName("isClosed") - public val isClosed: Boolean get() = this._value.get() < 0 +public class CloseableReferenceCounter : MayBeClosedReferenceCounter { + public constructor(errMessageClosed: String) : super(errMessageClosed) + @Suppress("INAPPLICABLE_JVM_NAME") @JvmName("close") - public fun close(errExistRefs: String) { - _Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") - val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE) - when { - state > 0 -> throw IllegalStateException(errExistRefs) - state < 0 -> this.throwClosed() + public override fun close(errExistRefs: String) { + super.close(errExistRefs) + } + + public companion object { + @JvmStatic + @JvmName("autoClosed") + public fun autoClosed(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { + _Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed") + _Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") + _Platform.jvm_assertNotNull(scope, "param: scope") + + val refcnt = CloseableReferenceCounter(errMessageClosed) + val ret = scope(refcnt) + refcnt.close(errExistRefs) + return ret } } - - @JvmName("withRef\$kt") - public inline fun withRef(protected: () -> R): R { - this.incref() - return safeAutoClose1(finally = this::decref, action = protected) - } - - override fun toString(): String { - val refcntCached = this._value.get() - @Suppress("LiftReturnOrAssignment") - if (refcntCached < 0) - return "" - else - return "" - } } \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt b/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt new file mode 100644 index 0000000..01a5526 --- /dev/null +++ b/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt @@ -0,0 +1,91 @@ +@file:OptIn(ExperimentalContracts::class) + +package ru.landrafhomyak.utility.reference_counter + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.jvm.JvmName +import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 +import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2 + +public sealed class MayBeClosedReferenceCounter { + private val _value: _AtomicLong + private val _errMessageClosed: String + + protected constructor(errMessageClosed: String) { + _Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed") + this._errMessageClosed = errMessageClosed + this._value = _AtomicLong(0L) + } + + @JvmName("throwClosed") + public fun throwClosed() { + throw IllegalStateException(this._errMessageClosed) + } + + @JvmName("incref") + public fun incref() { + this._value.update { o -> + if (o < 0) this.throwClosed() + return@update o + 1 + } + } + + @JvmName("tryIncref\$kt") + public inline fun tryIncref(block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + this.incref() + return safeAutoClose2(onError = this::decref, action = block) + } + + @JvmName("assertNotClosed") + public fun assertNotClosed() { + if (this._value.get() < 0) this.throwClosed() + } + + @JvmName("decref") + public fun decref() { + this._value.update(Long::dec) + } + + @JvmName("tryDecref\$kt") + public inline fun tryDecref(block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + this.assertNotClosed() + return safeAutoClose2(onSuccess = this::decref, action = block) + } + + @get:JvmName("isClosed") + public val isClosed: Boolean get() = this._value.get() < 0 + + @Suppress("INAPPLICABLE_JVM_NAME") + @JvmName("close") + protected open fun close(errExistRefs: String) { + _Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") + val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE) + when { + state > 0 -> throw IllegalStateException(errExistRefs) + state < 0 -> this.throwClosed() + } + } + + @JvmName("withRef\$kt") + public inline fun withRef(protected: () -> R): R { + this.incref() + return safeAutoClose1(finally = this::decref, action = protected) + } + + override fun toString(): String { + val refcntCached = this._value.get() + @Suppress("LiftReturnOrAssignment") + if (refcntCached < 0) + return "" + else + return "" + } +} \ No newline at end of file