From d4db1907d9e673b29a7a5d66c8491a5756064ea5 Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Fri, 22 Aug 2025 02:47:45 +0300 Subject: [PATCH] Unified all classes to common interface --- .../closeable_state/ChildCloseableState.kt | 72 ++++++++ .../utility/closeable_state/CloseableState.kt | 27 +++ .../ErrorOnConcurrentAccessState.kt | 70 ++++++++ .../ManualStateManipulation.kt | 7 + .../OwnedErrorOnConcurrentAccesState.kt | 30 ++++ .../closeable_state/OwnedUsagesCounter.kt | 26 +++ .../utility/closeable_state/UsagesCounter.kt | 61 +++++++ .../closeable_state/children_scopes.kt | 40 +++++ .../internal/AtomicLong.kt} | 4 +- .../internal/AtomicReference.kt | 15 ++ .../utility/closeable_state/internal/Misc.kt | 16 ++ .../utility/closeable_state/usage_scopes.kt | 40 +++++ .../ChildReferenceCounter.kt | 19 -- .../CloseableReferenceCounter.kt | 35 ---- .../CloseableReferenceCounter_Debug.kt | 164 ------------------ .../MayBeClosedReferenceCounter.kt | 145 ---------------- .../utility/reference_counter/_Misc.kt | 17 -- .../utility/reference_counter/_Platform.kt | 9 - .../CloseableReferenceCounter.kt | 37 ---- .../CloseableReferenceCounter_Debug.kt | 114 ------------ .../MayBeClosedReferenceCounter.kt | 108 ------------ .../WrapperReferenceCounter.kt | 20 --- .../internal/AtomicLong.kt} | 12 +- .../internal/AtomicReference.kt | 58 +++++++ .../utility/reference_counter/_Platform.kt | 17 -- .../tests/KotlinStdlibDependencyTest.kt | 81 +++++++++ .../tests/KotlinStdlibDependencyTest.kt | 130 -------------- .../internal/AtomicLong.kt} | 12 +- .../internal/AtomicReference.kt | 35 ++++ .../utility/reference_counter/_Platform.kt | 10 -- 30 files changed, 592 insertions(+), 839 deletions(-) create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ChildCloseableState.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/CloseableState.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ErrorOnConcurrentAccessState.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ManualStateManipulation.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/OwnedErrorOnConcurrentAccesState.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/OwnedUsagesCounter.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/UsagesCounter.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/children_scopes.kt rename src/commonMain/kotlin/ru/landgrafhomyak/utility/{reference_counter/_AtomicLong.kt => closeable_state/internal/AtomicLong.kt} (74%) create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/Misc.kt create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/usage_scopes.kt delete mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/ChildReferenceCounter.kt delete mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt delete mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/CloseableReferenceCounter_Debug.kt delete mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt delete mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Misc.kt delete mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt delete mode 100644 src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt delete mode 100644 src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter_Debug.kt delete mode 100644 src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt delete mode 100644 src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/WrapperReferenceCounter.kt rename src/jvmMain/kotlin/ru/landgrafhomyak/utility/{reference_counter/_AtomicLong.kt => closeable_state/internal/AtomicLong.kt} (82%) create mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt delete mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt create mode 100644 src/jvmTest/kotlin/ru/landgrafhomyak/utility/closeable_state/tests/KotlinStdlibDependencyTest.kt delete mode 100644 src/jvmTest/kotlin/ru/landgrafhomyak/utility/reference_counter/tests/KotlinStdlibDependencyTest.kt rename src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/{reference_counter/_AtomicLong.kt => closeable_state/internal/AtomicLong.kt} (74%) create mode 100644 src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt delete mode 100644 src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ChildCloseableState.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ChildCloseableState.kt new file mode 100644 index 0000000..1e9b666 --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ChildCloseableState.kt @@ -0,0 +1,72 @@ +package ru.landgrafhomyak.utility.closeable_state + +import kotlin.jvm.JvmField + + +public sealed class ChildCloseableState : CloseableState { + @JvmField + protected val _parent: CloseableState + + @JvmField + protected val _state: T + + protected constructor(parent: CloseableState, state: T) { + this._parent = parent + this._state = state + } + + override fun throwClosed(): Nothing = + this._state.throwClosed() + + override fun throwInUse(): Nothing = + this._state.throwInUse() + + override fun assertNotClosed(): Unit = + this._state.assertNotClosed() + + override val isClosed: Boolean + get() = this._state.isClosed + + @ManualStateManipulation + override fun startUsage(): Unit = + this._state.startUsage() + + @ManualStateManipulation + override fun finishUsage(): Unit = + this._state.finishUsage() + + @ManualStateManipulation + override fun close() { + this._parent.tryFinishUsage { + this._state.finishUsage() + } + } + + abstract override fun toString(): String + + public class AllowsConcurrency : ChildCloseableState, CloseableState.AllowsConcurrency { + public constructor(parent: CloseableState, state: CloseableState.AllowsConcurrency) : super(parent, state) + + override fun toString(): String { + when { + this._state is OwnedUsagesCounter || this._state::class === UsagesCounter::class -> { + val base = this._state.toString() + return base.substring(0, base.length - 1) + " (child of ${this._parent})>" + } + + else -> return "" + } + } + } + + public class ExternallySynchronized : ChildCloseableState, CloseableState.ExternallySynchronized { + public constructor(parent: CloseableState, state: CloseableState.ExternallySynchronized) : super(parent, state) + + override val isInUse: Boolean + get() = this._state.isInUse + + override fun toString(): String { + TODO("Not yet implemented") + } + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/CloseableState.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/CloseableState.kt new file mode 100644 index 0000000..151614e --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/CloseableState.kt @@ -0,0 +1,27 @@ +package ru.landgrafhomyak.utility.closeable_state + +public interface CloseableState : AutoCloseable { + public fun throwClosed(): Nothing + public fun throwInUse(): Nothing + + public fun assertNotClosed() + + public val isClosed: Boolean + + @ManualStateManipulation + public fun startUsage() + + @ManualStateManipulation + public fun finishUsage() + + @ManualStateManipulation + public override fun close() + + public interface AllowsConcurrency : CloseableState { + + } + + public interface ExternallySynchronized : CloseableState { + public val isInUse: Boolean + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ErrorOnConcurrentAccessState.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ErrorOnConcurrentAccessState.kt new file mode 100644 index 0000000..ce54506 --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ErrorOnConcurrentAccessState.kt @@ -0,0 +1,70 @@ +package ru.landgrafhomyak.utility.closeable_state + +import ru.landgrafhomyak.utility.closeable_state.internal.AtomicReference + +public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchronized { + private enum class State { + OPEN, IN_USE, CLOSED + } + + private val _state = AtomicReference(State.OPEN) + + + final override val isInUse: Boolean + get() = this._state.get() === State.IN_USE + + open override fun throwClosed(): Nothing { + throw IllegalStateException("Object is closed") + } + + open override fun throwInUse(): Nothing { + throw IllegalStateException("Failed close object because it is in use") + } + + public open fun throwConcurrent(): Nothing { + throw IllegalStateException("Object is in use by another thread") + } + + final override fun assertNotClosed() { + if (this._state.get() === State.CLOSED) + this.throwClosed() + } + + final override val isClosed: Boolean + get() = this._state.get() === State.CLOSED + + @ManualStateManipulation + final override fun startUsage() { + when (this._state.compareAndExchange(State.OPEN, State.IN_USE)) { + State.OPEN -> {} + State.IN_USE -> this.throwConcurrent() + State.CLOSED -> this.throwClosed() + } + } + + @ManualStateManipulation + override fun finishUsage() { + when (this._state.compareAndExchange(State.IN_USE, State.OPEN)) { + State.OPEN -> throw IllegalStateException("Can't finish usage because not it not started") + State.IN_USE -> {} + State.CLOSED -> this.throwClosed() + } + } + + @ManualStateManipulation + override fun close() { + when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) { + State.OPEN -> {} + State.IN_USE -> this.throwConcurrent() + State.CLOSED -> this.throwClosed() + } + } + + + override fun toString(): String = + when (this._state.get()) { + State.OPEN -> "" + State.IN_USE -> "" + State.CLOSED -> "" + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ManualStateManipulation.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ManualStateManipulation.kt new file mode 100644 index 0000000..5a3e0ba --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ManualStateManipulation.kt @@ -0,0 +1,7 @@ +package ru.landgrafhomyak.utility.closeable_state + +@RequiresOptIn( + message = "Manual state control is unsafe, are you sure to do this", + level = RequiresOptIn.Level.ERROR +) +public annotation class ManualStateManipulation diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/OwnedErrorOnConcurrentAccesState.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/OwnedErrorOnConcurrentAccesState.kt new file mode 100644 index 0000000..d982d97 --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/OwnedErrorOnConcurrentAccesState.kt @@ -0,0 +1,30 @@ +@file:OptIn(ExperimentalContracts::class) + +package ru.landgrafhomyak.utility.closeable_state + +import kotlin.contracts.ExperimentalContracts + +public class OwnedErrorOnConcurrentAccesState : ErrorOnConcurrentAccessState { + public val _owner: Any + + public constructor(owner: Any) : super() { + this._owner = owner + } + + override fun throwClosed(): Nothing { + throw IllegalStateException("Object is closed: ${this._owner}") + } + + override fun throwInUse(): Nothing { + throw IllegalStateException("Failed close object because it is in use: ${this._owner}") + } + + override fun throwConcurrent(): Nothing { + throw IllegalStateException("Object is in use by another thread: ${this._owner}") + } + + override fun toString(): String { + val base = super.toString() + return base.substring(0, base.length - 1) + " of ${this._owner}>" + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/OwnedUsagesCounter.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/OwnedUsagesCounter.kt new file mode 100644 index 0000000..ad66a2a --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/OwnedUsagesCounter.kt @@ -0,0 +1,26 @@ +@file:OptIn(ExperimentalContracts::class) + +package ru.landgrafhomyak.utility.closeable_state + +import kotlin.contracts.ExperimentalContracts + +public class OwnedUsagesCounter : UsagesCounter { + public val _owner: Any + + public constructor(owner: Any) : super() { + this._owner = owner + } + + override fun throwClosed(): Nothing { + throw IllegalStateException("Object is closed: ${this._owner}") + } + + override fun throwInUse(): Nothing { + throw IllegalStateException("Failed close object because it is in use: ${this._owner}") + } + + override fun toString(): String { + val base = super.toString() + return base.substring(0, base.length - 1) + " of ${this._owner}>" + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/UsagesCounter.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/UsagesCounter.kt new file mode 100644 index 0000000..8fd0c1f --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/UsagesCounter.kt @@ -0,0 +1,61 @@ +@file:OptIn(ExperimentalContracts::class) + +package ru.landgrafhomyak.utility.closeable_state + +import kotlin.contracts.ExperimentalContracts +import ru.landgrafhomyak.utility.closeable_state.internal.AtomicLong +import ru.landgrafhomyak.utility.closeable_state.internal.Misc + +public open class UsagesCounter : CloseableState.AllowsConcurrency { + private val _value: AtomicLong = AtomicLong(0L) + + public constructor() + + public fun getCurrentUsagesCount(): Long = this._value.get() + + public open override fun throwClosed(): Nothing { + throw IllegalStateException("Object is closed") + } + + public open override fun throwInUse(): Nothing { + throw IllegalStateException("Failed close object because it is in use") + } + + + public final override val isClosed: Boolean get() = this._value.get() < 0 + + public final override fun assertNotClosed() { + if (this._value.get() < 0) this.throwClosed() + } + + @ManualStateManipulation + public final override fun startUsage() { + this._value.update { o -> + if (o < 0) this.throwClosed() + return@update o + 1 + } + } + + @ManualStateManipulation + public final override fun finishUsage() { + this._value.update(Long::dec) + } + + @ManualStateManipulation + public final override fun close() { + val state = this._value.compareAndExchange(0, Misc.CLOSED_STATE_VALUE) + when { + state > 0 -> this.throwInUse() + state < 0 -> this.throwClosed() + } + } + + override fun toString(): String { + val cached = this._value.get() + @Suppress("LiftReturnOrAssignment") + if (cached < 0) + return "" + else + return "" + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/children_scopes.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/children_scopes.kt new file mode 100644 index 0000000..d713473 --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/children_scopes.kt @@ -0,0 +1,40 @@ +@file:JvmName("ChildrenScopesKt") + +package ru.landgrafhomyak.utility.closeable_state + +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.jvm.JvmName +import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 + +@OptIn(ManualStateManipulation::class) +public inline fun CloseableState.childAC( + constructor: () -> CloseableState.AllowsConcurrency = ::UsagesCounter, + scope: (CloseableState.AllowsConcurrency) -> R, +): R { + contract { + callsInPlace(constructor, InvocationKind.EXACTLY_ONCE) + callsInPlace(scope, InvocationKind.EXACTLY_ONCE) + } + val childState = this.tryStartUsage { ChildCloseableState.AllowsConcurrency(this, constructor()) } + return safeAutoClose1( + action = { scope(childState) }, + finally = childState::close + ) +} + +@OptIn(ManualStateManipulation::class) +public inline fun CloseableState.childES( + constructor: () -> CloseableState.ExternallySynchronized = ::ErrorOnConcurrentAccessState, + scope: (CloseableState.ExternallySynchronized) -> R, +): R { + contract { + callsInPlace(constructor, InvocationKind.EXACTLY_ONCE) + callsInPlace(scope, InvocationKind.EXACTLY_ONCE) + } + val childState = this.tryStartUsage { ChildCloseableState.ExternallySynchronized(this, constructor()) } + return safeAutoClose1( + action = { scope(childState) }, + finally = childState::close + ) +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt similarity index 74% rename from src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt rename to src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt index 2acbfed..2f7f031 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt @@ -1,6 +1,6 @@ -package ru.landgrafhomyak.utility.reference_counter +package ru.landgrafhomyak.utility.closeable_state.internal -internal expect class _AtomicLong { +internal expect class AtomicLong { constructor(initial: Long) fun get(): Long diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt new file mode 100644 index 0000000..106b1ce --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt @@ -0,0 +1,15 @@ +package ru.landgrafhomyak.utility.closeable_state.internal + +internal expect class AtomicReference { + constructor(initial: T) + + fun get(): T + + inline fun update(operator: (T) -> T) + + inline fun getAndUpdate(operator: (T) -> T): T + + fun compareAndSet(expected: T, newValue: T): Boolean + + fun compareAndExchange(expected: T, newValue: T): T +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/Misc.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/Misc.kt new file mode 100644 index 0000000..9c1337a --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/Misc.kt @@ -0,0 +1,16 @@ +package ru.landgrafhomyak.utility.closeable_state.internal + +import kotlin.jvm.JvmStatic + +internal object Misc { + @JvmStatic + internal inline fun _compareAndExchange(get: () -> T, cas: (T, T) -> Boolean, expected: T, newValue: T): T { + while (true) { + val old = get() + if (old != expected) return old + if (cas(old, newValue)) return old + } + } + + internal const val CLOSED_STATE_VALUE = -0x4000_0000_0000_0000L +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/usage_scopes.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/usage_scopes.kt new file mode 100644 index 0000000..e80656d --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/usage_scopes.kt @@ -0,0 +1,40 @@ +@file:JvmName("UsageScopesKt") + +package ru.landgrafhomyak.utility.closeable_state + +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 + +@OptIn(ManualStateManipulation::class) +@JvmName("use\$kt") +public inline fun CloseableState.use(block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + this.startUsage() + return safeAutoClose1(action = block, finally = this::finishUsage) +} + + +@ManualStateManipulation +@JvmName("tryStartUsage\$kt") +public inline fun CloseableState.tryStartUsage(block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + this.startUsage() + return safeAutoClose2(action = block, onError = this::finishUsage) +} + +@ManualStateManipulation +@JvmName("tryFinishUsage\$kt") +public inline fun CloseableState.tryFinishUsage(block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + this.assertNotClosed() + return safeAutoClose2(action = block, onSuccess = this::finishUsage) +} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/ChildReferenceCounter.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/ChildReferenceCounter.kt deleted file mode 100644 index 2510773..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/ChildReferenceCounter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package ru.landgrafhomyak.utility.reference_counter - -import kotlin.jvm.JvmName - -public class ChildReferenceCounter : MayBeClosedReferenceCounter { - private val _parent: MayBeClosedReferenceCounter - - internal constructor(parent: MayBeClosedReferenceCounter, errMessageClosed: String) : super(errMessageClosed) { - this._parent = parent - } - - @Suppress("INAPPLICABLE_JVM_NAME") - @JvmName("close") - public override fun close(errExistRefs: String) { - this._parent.tryDecref { - super.close(errExistRefs) - } - } -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt deleted file mode 100644 index 41b37a6..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt +++ /dev/null @@ -1,35 +0,0 @@ -package ru.landgrafhomyak.utility.reference_counter - -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic - -public class CloseableReferenceCounter : MayBeClosedReferenceCounter { - public constructor(errMessageClosed: String) : super(errMessageClosed) - - @Suppress("INAPPLICABLE_JVM_NAME") - @JvmName("close") - public override fun close(errExistRefs: String) { - super.close(errExistRefs) - } - - public companion object { - @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND") - @JvmStatic - @JvmName("autoClosed") - public fun autoClosed(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { - contract { - callsInPlace(scope, InvocationKind.EXACTLY_ONCE) - } - _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 - } - } -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/CloseableReferenceCounter_Debug.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/CloseableReferenceCounter_Debug.kt deleted file mode 100644 index 6753728..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/CloseableReferenceCounter_Debug.kt +++ /dev/null @@ -1,164 +0,0 @@ -@file:OptIn(ExperimentalContracts::class) - -package ru.landgrafhomyak.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 - -@CloseableReferenceCounter_Debug.RequiresExplicitDebug -public class CloseableReferenceCounter_Debug { - public fun interface Observer { - public fun observeState(instance: CloseableReferenceCounter_Debug, actions: String) - } - - @RequiresOptIn(level = RequiresOptIn.Level.WARNING) - @Retention(AnnotationRetention.BINARY) - public annotation class RequiresExplicitDebug - - private val _dbgName: String - private val _errMessage: String - private val _logger: Observer? - private val _value: _AtomicLong - private val _id: Long - - public constructor(dbgName: String, errMessage: String, logger: Observer? = null) { - _Platform.jvm_assertNotNull(dbgName, "param: dbgName") - _Platform.jvm_assertNotNull(errMessage, "param: errMessage") - - this._dbgName = dbgName - this._errMessage = dbgName - this._logger = logger - this._value = _AtomicLong(0L) - @Suppress("RemoveRedundantQualifierName") - this._id = CloseableReferenceCounter_Debug._nextId.getAndUpdate(Long::inc) - } - - - @Suppress("NOTHING_TO_INLINE") - private inline fun _throwErrors(valueToCheck: Long) { - when { - valueToCheck >= 0 || valueToCheck == _Misc.CLOSED_STATE_VALUE -> {} - valueToCheck < _Misc.CLOSED_STATE_VALUE -> throw RuntimeException("Too many references") - valueToCheck > _Misc.CLOSED_STATE_VALUE -> throw RuntimeException(".decref called more times than .incref") - } - } - - @RequiresExplicitDebug - @JvmName("throwErrors") - public fun throwErrors() { - this._throwErrors(this._value.get()) - } - - @JvmName("throwClosed") - public fun throwClosed() { - throw IllegalStateException(this._errMessage) - } - - @JvmName("incref") - public fun incref() { - this._value.update { o -> - if (o < 0) { - this._throwErrors(o) - this.throwClosed() - this._throwErrors(o + 1) - } - return@update o + 1 - } - this._logger?.observeState(this, "incref") - } - - @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 { o -> - if (o < 0) { - this._throwErrors(o) - this.throwClosed() - this._throwErrors(o - 1) - } - return@update o - 1 - } - this._logger?.observeState(this, "decref") - } - - @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() { - val state = this._value.get() - this._throwErrors(state) - return state < 0; - } - - @JvmName("close") - public fun close(errExistRefs: String) { - _Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") - val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE) - this._throwErrors(state) - when { - state > 0 -> throw IllegalStateException(errExistRefs) - state < 0 -> this.throwClosed() - } - this._logger?.observeState(this, "closed") - } - - @JvmName("withRef\$kt") - public inline fun withRef(protected: () -> R): R { - contract { - callsInPlace(protected, InvocationKind.EXACTLY_ONCE) - } - this.incref() - return safeAutoClose1(finally = this::decref, action = protected) - } - - override fun toString(): String { - val refcntCached = this._value.get() - val stateRepr: String - @Suppress("LiftReturnOrAssignment") - when { - refcntCached >= 0 -> stateRepr = refcntCached.toString() - refcntCached == _Misc.CLOSED_STATE_VALUE -> stateRepr = "closed" - refcntCached < _Misc.CLOSED_STATE_VALUE -> stateRepr = "overflow" - refcntCached > _Misc.CLOSED_STATE_VALUE -> stateRepr = "underflow" - else -> throw Error("Unreachable") - } - return "" - } - - public companion object { - private val _nextId = _AtomicLong(0L) - } - - public object ObserveToStdout : Observer { - override fun observeState(instance: CloseableReferenceCounter_Debug, actions: String) { - _Platform.jvm_assertNotNull(instance, "param: instance") - _Platform.jvm_assertNotNull(actions, "param: actions") - print("${instance} ${actions}\n") - } - } -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt deleted file mode 100644 index 466a669..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt +++ /dev/null @@ -1,145 +0,0 @@ -@file:OptIn(ExperimentalContracts::class) - -package ru.landgrafhomyak.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 { - contract { - callsInPlace(protected, InvocationKind.EXACTLY_ONCE) - } - 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 "" - } - - @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND") - @JvmName("child") - public fun child(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { - contract { - callsInPlace(scope, InvocationKind.EXACTLY_ONCE) - } - - _Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed") - _Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") - _Platform.jvm_assertNotNull(scope, "param: scope") - - this.withRef { - return CloseableReferenceCounter.autoClosed( - errMessageClosed = errMessageClosed, - errExistRefs = errExistRefs, - scope = scope - ) - } - } - - @JvmName("newChild") - public fun newChild(errMessageClosed: String): ChildReferenceCounter { - _Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed") - - this.tryIncref { - return ChildReferenceCounter(this, errMessageClosed) - } - } - - @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND") - @JvmName("child_inheritErrMessage") - public fun child_inheritErrMessage(errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { - contract { - callsInPlace(scope, InvocationKind.EXACTLY_ONCE) - } - - _Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") - _Platform.jvm_assertNotNull(scope, "param: scope") - - return this.child( - errMessageClosed = this._errMessageClosed, - errExistRefs = errExistRefs, - scope = scope - ) - } - - @JvmName("newChild_inheritErrMessage") - public fun newChild_inheritErrMessage(): ChildReferenceCounter { - return this.newChild(this._errMessageClosed) - } -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Misc.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Misc.kt deleted file mode 100644 index 4801381..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Misc.kt +++ /dev/null @@ -1,17 +0,0 @@ -package ru.landgrafhomyak.utility.reference_counter - -import kotlin.jvm.JvmStatic - -@Suppress("ClassName") -internal object _Misc { - @JvmStatic - internal inline fun _compareAndExchange(get: () -> Long, cas: (Long, Long) -> Boolean, expected: Long, newValue: Long): Long { - while (true) { - val old = get() - if (old != expected) return old - if (cas(old, newValue)) return old - } - } - - internal const val CLOSED_STATE_VALUE = -0x4000_0000_0000_0000L -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt deleted file mode 100644 index 6518cec..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt +++ /dev/null @@ -1,9 +0,0 @@ -package ru.landgrafhomyak.utility.reference_counter - -import kotlin.jvm.JvmStatic - -@PublishedApi -internal expect object _Platform { - @PublishedApi - internal inline fun jvm_assertNotNull(x: Any?, name: String) -} \ 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 deleted file mode 100644 index 0ce2894..0000000 --- a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter.kt +++ /dev/null @@ -1,37 +0,0 @@ -package ru.landrafhomyak.utility.reference_counter - -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic -import ru.landgrafhomyak.utility.reference_counter._Platform -import ru.landgrafhomyak.utility.reference_counter.CloseableReferenceCounter as moved_CloseableReferenceCounter - -@Suppress("DEPRECATION_ERROR") -@Deprecated( - message = "Class moved to another package", - level = DeprecationLevel.ERROR -) -public class CloseableReferenceCounter : MayBeClosedReferenceCounter { - public constructor(errMessageClosed: String) : super(moved_CloseableReferenceCounter(errMessageClosed)) - - @Suppress("INAPPLICABLE_JVM_NAME", "NON_FINAL_MEMBER_IN_FINAL_CLASS") - @JvmName("close") - public open fun close(errExistRefs: String) { - (this._moved as moved_CloseableReferenceCounter).close(errExistRefs) - } - - public companion object { - @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND") - @JvmStatic - @JvmName("autoClosed") - public fun autoClosed(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { - contract { - callsInPlace(scope, InvocationKind.EXACTLY_ONCE) - } - _Platform.jvm_assertNotNull(scope, "param: scope") - - return moved_CloseableReferenceCounter.autoClosed(errMessageClosed, errExistRefs, WrapperReferenceCounter.wrapperLambda(scope)) - } - } -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter_Debug.kt b/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter_Debug.kt deleted file mode 100644 index 551b45e..0000000 --- a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/CloseableReferenceCounter_Debug.kt +++ /dev/null @@ -1,114 +0,0 @@ -@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.JvmField -import kotlin.jvm.JvmName -import ru.landgrafhomyak.utility.reference_counter.CloseableReferenceCounter_Debug as moved_CloseableReferenceCounter_Debug - -@Suppress("DEPRECATION_ERROR") -@Deprecated( - message = "Class moved to another package", - level = DeprecationLevel.ERROR -) -@OptIn(moved_CloseableReferenceCounter_Debug.RequiresExplicitDebug::class) -@CloseableReferenceCounter_Debug.RequiresExplicitDebug -public class CloseableReferenceCounter_Debug { - public fun interface Observer { - public fun observeState(instance: CloseableReferenceCounter_Debug, actions: String) - } - - private class ObserverAdapter(private val old: Observer) : moved_CloseableReferenceCounter_Debug.Observer { - lateinit var wrapper: CloseableReferenceCounter_Debug - override fun observeState(instance: moved_CloseableReferenceCounter_Debug, actions: String) { - this.old.observeState(this.wrapper, actions) - } - } - - @RequiresOptIn(level = RequiresOptIn.Level.WARNING) - @Retention(AnnotationRetention.BINARY) - public annotation class RequiresExplicitDebug - - @PublishedApi - @JvmField - internal val _moved: moved_CloseableReferenceCounter_Debug - - public constructor(dbgName: String, errMessage: String, logger: Observer? = null) { - val obs = logger?.let(::ObserverAdapter) - this._moved = moved_CloseableReferenceCounter_Debug(dbgName, errMessage, obs) - obs?.wrapper = this - } - - @RequiresExplicitDebug - @JvmName("throwErrors") - public fun throwErrors() { - this._moved.throwErrors() - } - - @JvmName("throwClosed") - public fun throwClosed() { - this._moved.throwClosed() - } - - @JvmName("incref") - public fun incref() { - this._moved.incref() - } - - @JvmName("tryIncref\$kt") - public inline fun tryIncref(block: () -> R): R { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - return this._moved.tryIncref(block) - } - - @JvmName("assertNotClosed") - public fun assertNotClosed() { - this._moved.assertNotClosed() - } - - @JvmName("decref") - public fun decref() { - this._moved.decref() - } - - @JvmName("tryDecref\$kt") - public inline fun tryDecref(block: () -> R): R { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - return this._moved.tryDecref(block) - } - - @get:JvmName("isClosed") - public val isClosed: Boolean - get() = this._moved.isClosed - - @JvmName("close") - public fun close(errExistRefs: String) { - this._moved.close(errExistRefs) - } - - @JvmName("withRef\$kt") - public inline fun withRef(protected: () -> R): R { - contract { - callsInPlace(protected, InvocationKind.EXACTLY_ONCE) - } - return this._moved.withRef(protected) - } - - override fun toString(): String { - val orig = this._moved.toString() - return orig.substring(0, orig.length - 1) + " !deprecated class used!>" - } - - public object ObserveToStdout : Observer { - override fun observeState(instance: CloseableReferenceCounter_Debug, actions: String) { - moved_CloseableReferenceCounter_Debug.ObserveToStdout.observeState(instance._moved, actions) - } - } -} \ 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 deleted file mode 100644 index 28f6a00..0000000 --- a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/MayBeClosedReferenceCounter.kt +++ /dev/null @@ -1,108 +0,0 @@ -@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.JvmField -import kotlin.jvm.JvmName -import ru.landgrafhomyak.utility.reference_counter._Platform -import ru.landgrafhomyak.utility.reference_counter.MayBeClosedReferenceCounter as moved_MayBeClosedReferenceCounter - -@Deprecated( - message = "Class moved to another package", - /*replaceWith = ReplaceWith( - imports = ["ru.landgrafhomyak.utility.reference_counter.MayBeClosedReferenceCounter"], - expression = "MayBeClosedReferenceCounter" - ),*/ - level = DeprecationLevel.ERROR -) -public sealed class MayBeClosedReferenceCounter { - @PublishedApi - @JvmField - internal val _moved: moved_MayBeClosedReferenceCounter - - protected constructor(moved: moved_MayBeClosedReferenceCounter) { - this._moved = moved - } - - @JvmName("throwClosed") - public fun throwClosed() { - this._moved.throwClosed() - } - - @JvmName("incref") - public fun incref() { - this._moved.incref() - } - - @JvmName("tryIncref\$kt") - public inline fun tryIncref(block: () -> R): R { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - return this._moved.tryIncref(block) - } - - @JvmName("assertNotClosed") - public fun assertNotClosed() { - this._moved.assertNotClosed() - } - - @JvmName("decref") - public fun decref() { - this._moved.decref() - } - - @JvmName("tryDecref\$kt") - public inline fun tryDecref(block: () -> R): R { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - return this._moved.tryDecref(block) - } - - @get:JvmName("isClosed") - public val isClosed: Boolean get() = - this._moved.isClosed - - @JvmName("withRef\$kt") - public inline fun withRef(protected: () -> R): R { - contract { - callsInPlace(protected, InvocationKind.EXACTLY_ONCE) - } - return this._moved.withRef(protected) - } - - override fun toString(): String { - val orig = this._moved.toString() - return orig.substring(0, orig.length - 1) + " !deprecated class used!>" - } - - @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND", "DEPRECATION_ERROR") - @JvmName("child") - public fun child(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { - contract { - callsInPlace(scope, InvocationKind.EXACTLY_ONCE) - } - - _Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed") - _Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") - _Platform.jvm_assertNotNull(scope, "param: scope") - - return this._moved.child(errMessageClosed, errExistRefs, WrapperReferenceCounter.wrapperLambda(scope)) - } - - @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND", "DEPRECATION_ERROR") - @JvmName("child_inheritErrMessage") - public fun child_inheritErrMessage(errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { - contract { - callsInPlace(scope, InvocationKind.EXACTLY_ONCE) - } - - _Platform.jvm_assertNotNull(scope, "param: scope") - - return this._moved.child_inheritErrMessage(errExistRefs, WrapperReferenceCounter.wrapperLambda(scope)) - } -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/WrapperReferenceCounter.kt b/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/WrapperReferenceCounter.kt deleted file mode 100644 index 0f1d204..0000000 --- a/src/commonMain/kotlin/ru/landrafhomyak/utility/reference_counter/WrapperReferenceCounter.kt +++ /dev/null @@ -1,20 +0,0 @@ -package ru.landrafhomyak.utility.reference_counter - -import kotlin.jvm.JvmStatic -import ru.landgrafhomyak.utility.reference_counter.MayBeClosedReferenceCounter as moved_MayBeClosedReferenceCounter - -@Suppress("DEPRECATION_ERROR") -@Deprecated( - message = "Utility class for deprecated refcounters", - level = DeprecationLevel.ERROR -) -internal class WrapperReferenceCounter : MayBeClosedReferenceCounter { - constructor(refcnt: moved_MayBeClosedReferenceCounter) : super(refcnt) - - companion object { - @JvmStatic - fun wrapperLambda(old: (MayBeClosedReferenceCounter) -> R): (moved_MayBeClosedReferenceCounter) -> R { - return w@{ moved -> return@w old(WrapperReferenceCounter(moved)) } - } - } -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt similarity index 82% rename from src/jvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt rename to src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt index 38765c6..7f0af9a 100644 --- a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt @@ -1,8 +1,8 @@ -package ru.landgrafhomyak.utility.reference_counter +package ru.landgrafhomyak.utility.closeable_state.internal import java.util.concurrent.atomic.AtomicLong -internal actual /*value*/ class _AtomicLong { +internal actual /*value*/ class AtomicLong { private val _native: AtomicLong actual constructor(initial: Long) { @@ -31,11 +31,11 @@ internal actual /*value*/ class _AtomicLong { this._native.compareAndSet(expected, newValue) actual fun compareAndExchange(expected: Long, newValue: Long): Long { - if (_Linkage._isNativeCompareAndExchangeExists) { + if (_Linkage.isNativeCompareAndExchangeExists) { return this._native.compareAndExchange(expected, newValue) } else { val a = this._native - return _Misc._compareAndExchange( + return Misc._compareAndExchange( get = a::get, cas = a::compareAndSet, expected = expected, newValue = newValue @@ -44,8 +44,8 @@ internal actual /*value*/ class _AtomicLong { } private object _Linkage { - @JvmField - val _isNativeCompareAndExchangeExists = run { + @JvmStatic + val isNativeCompareAndExchangeExists = run { val a = AtomicLong() try { a.compareAndExchange(0, 0) diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt new file mode 100644 index 0000000..7fb3463 --- /dev/null +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt @@ -0,0 +1,58 @@ +package ru.landgrafhomyak.utility.closeable_state.internal + +import java.util.concurrent.atomic.AtomicReference as jAtomicReference + +internal actual /*value*/ class AtomicReference { + private val _native: jAtomicReference + + actual constructor(initial: T) { + this._native = jAtomicReference(initial) + } + + actual fun get() = this._native.get() + + actual inline fun update(operator: (T) -> T) { + while (true) { + val cur = this._native.get() + val upd = operator(cur) + if (this._native.compareAndSet(cur, upd)) return + } + } + + actual inline fun getAndUpdate(operator: (T) -> T): T { + while (true) { + val cur = this._native.get() + val upd = operator(cur) + if (this._native.compareAndSet(cur, upd)) return cur + } + } + + actual fun compareAndSet(expected: T, newValue: T): Boolean = + this._native.compareAndSet(expected, newValue) + + actual fun compareAndExchange(expected: T, newValue: T): T { + if (_Linkage.isNativeCompareAndExchangeExists) { + return this._native.compareAndExchange(expected, newValue) + } else { + val a = this._native + return Misc._compareAndExchange( + get = a::get, + cas = a::compareAndSet, + expected = expected, newValue = newValue + ) + } + } + + private object _Linkage { + @JvmStatic + val isNativeCompareAndExchangeExists = run { + val a = jAtomicReference(null) + try { + a.compareAndExchange(null, null) + return@run true + } catch (_: NoSuchMethodError) { + return@run false + } + } + } +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt deleted file mode 100644 index e8e15bd..0000000 --- a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt +++ /dev/null @@ -1,17 +0,0 @@ -package ru.landgrafhomyak.utility.reference_counter - -import java.util.Objects -import kotlin.contracts.contract - -@PublishedApi -internal actual object _Platform { - @Suppress("NOTHING_TO_INLINE") - @JvmStatic - @PublishedApi - internal actual inline fun jvm_assertNotNull(x: Any?, name: String) { - contract { - returns().implies(x != null) - } - Objects.requireNonNull(x, name) - } -} \ No newline at end of file diff --git a/src/jvmTest/kotlin/ru/landgrafhomyak/utility/closeable_state/tests/KotlinStdlibDependencyTest.kt b/src/jvmTest/kotlin/ru/landgrafhomyak/utility/closeable_state/tests/KotlinStdlibDependencyTest.kt new file mode 100644 index 0000000..78e115c --- /dev/null +++ b/src/jvmTest/kotlin/ru/landgrafhomyak/utility/closeable_state/tests/KotlinStdlibDependencyTest.kt @@ -0,0 +1,81 @@ +package ru.landgrafhomyak.utility.closeable_state.tests + +import org.testng.annotations.Test +import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 +import ru.landgrafhomyak.utility.closeable_state.ManualStateManipulation +import ru.landgrafhomyak.utility.closeable_state.UsagesCounter +import ru.landgrafhomyak.utility.closeable_state.use + +@Test +class KotlinStdlibDependencyTest { + @Test + fun testNoKotlinStdlib() { + try { + if (KotlinVersion.CURRENT.major != -1) + throw AssertionError("Kotlin stdlib still in runtime classpath") + } catch (_: LinkageError) { + } + } + + private class CustomTestException : RuntimeException() + + private object CustomUnit + + private fun throw7throwFn() { + safeAutoClose1(finally = { throw CustomTestException() }, action = { throw CustomTestException() }) + } + + @Suppress("NOTHING_TO_INLINE") + private inline fun throw7throwIn() { + safeAutoClose1(finally = { throw CustomTestException() }, action = { throw CustomTestException() }) + } + + @OptIn(ManualStateManipulation::class) + @Test(dependsOnMethods = ["testNoKotlinStdlib"]) + fun testIncrefDecrefClose() { + try { + val refcnt = UsagesCounter() + refcnt.startUsage() + refcnt.finishUsage() + refcnt.startUsage() + refcnt.startUsage() + refcnt.finishUsage() + refcnt.finishUsage() + refcnt.close() + } catch (le: LinkageError) { + throw AssertionError("CloseableReferenceCounter still has dependency on kotlin stdlib", le) + } + } + + @OptIn(ManualStateManipulation::class) + @Test(dependsOnMethods = ["testNoKotlinStdlib", "testIncrefDecrefClose"]) + fun testWithRef() { + try { + val refcnt = UsagesCounter() + refcnt.use { + return@use CustomUnit + } + refcnt.use w1@{ + return@w1 refcnt.use w2@{ + return@w2 CustomUnit + } + } + refcnt.close() + } catch (le: LinkageError) { + throw AssertionError("CloseableReferenceCounter still has dependency on kotlin stdlib", le) + } + } + + @Test(dependsOnMethods = ["testNoKotlinStdlib", "testIncrefDecrefClose", "testWithRef"]) + fun testWithRef_Err() { + try { + val refcnt = UsagesCounter() + refcnt.use { + throw CustomTestException() + } + } catch (_: CustomTestException) { + } catch (le: LinkageError) { + throw AssertionError("CloseableReferenceCounter still has dependency on kotlin stdlib", le) + } + } +} \ No newline at end of file diff --git a/src/jvmTest/kotlin/ru/landgrafhomyak/utility/reference_counter/tests/KotlinStdlibDependencyTest.kt b/src/jvmTest/kotlin/ru/landgrafhomyak/utility/reference_counter/tests/KotlinStdlibDependencyTest.kt deleted file mode 100644 index 02cc221..0000000 --- a/src/jvmTest/kotlin/ru/landgrafhomyak/utility/reference_counter/tests/KotlinStdlibDependencyTest.kt +++ /dev/null @@ -1,130 +0,0 @@ -package ru.landgrafhomyak.utility.reference_counter.tests - -import java.lang.AssertionError -import org.testng.annotations.Test -import org.testng.asserts.Assertion -import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 -import ru.landgrafhomyak.utility.reference_counter.CloseableReferenceCounter -import ru.landgrafhomyak.utility.reference_counter.CloseableReferenceCounter_Debug - -@Test -class KotlinStdlibDependencyTest { - @Test - fun testNoKotlinStdlib() { - try { - if (KotlinVersion.CURRENT.major != -1) - throw AssertionError("Kotlin stdlib still in runtime classpath") - } catch (_: LinkageError) { - } - } - - private class CustomTestException : RuntimeException() - - private object CustomUnit - - private fun throw7throwFn() { - safeAutoClose1(finally = { throw CustomTestException() }, action = { throw CustomTestException() }) - } - - @Suppress("NOTHING_TO_INLINE") - private inline fun throw7throwIn() { - safeAutoClose1(finally = { throw CustomTestException() }, action = { throw CustomTestException() }) - } - - @Test(dependsOnMethods = ["testNoKotlinStdlib"]) - fun testIncrefDecrefClose() { - try { - val refcnt = CloseableReferenceCounter("") - refcnt.incref() - refcnt.decref() - refcnt.incref() - refcnt.incref() - refcnt.decref() - refcnt.decref() - refcnt.close("") - } catch (le: LinkageError) { - throw AssertionError("CloseableReferenceCounter still has dependency on kotlin stdlib", le) - } - } - - @OptIn(CloseableReferenceCounter_Debug.RequiresExplicitDebug::class) - @Test(dependsOnMethods = ["testNoKotlinStdlib"]) - fun testIncrefDecrefClose_Debug() { - try { - val refcnt = CloseableReferenceCounter_Debug("", "") - refcnt.incref() - refcnt.decref() - refcnt.incref() - refcnt.incref() - refcnt.decref() - refcnt.decref() - refcnt.close("") - } catch (le: LinkageError) { - throw AssertionError("CloseableReferenceCounter_Debug still has dependency on kotlin stdlib", le) - } - } - - @Test(dependsOnMethods = ["testNoKotlinStdlib", "testIncrefDecrefClose"]) - fun testWithRef() { - try { - val refcnt = CloseableReferenceCounter("") - refcnt.withRef { - return@withRef CustomUnit - } - refcnt.withRef w1@{ - return@w1 refcnt.withRef w2@{ - return@w2 CustomUnit - } - } - refcnt.close("") - } catch (le: LinkageError) { - throw AssertionError("CloseableReferenceCounter still has dependency on kotlin stdlib", le) - } - } - - @OptIn(CloseableReferenceCounter_Debug.RequiresExplicitDebug::class) - @Test(dependsOnMethods = ["testNoKotlinStdlib", "testIncrefDecrefClose_Debug"]) - fun testWithRef_Debug() { - try { - val refcnt = CloseableReferenceCounter_Debug("", "") - refcnt.withRef { - return@withRef CustomUnit - } - refcnt.withRef w1@{ - return@w1 refcnt.withRef w2@{ - return@w2 CustomUnit - } - } - refcnt.close("") - } catch (le: LinkageError) { - throw AssertionError("CloseableReferenceCounter_Debug still has dependency on kotlin stdlib", le) - } - } - - @Test(dependsOnMethods = ["testNoKotlinStdlib", "testIncrefDecrefClose", "testWithRef"]) - fun testWithRef_Err() { - try { - val refcnt = CloseableReferenceCounter("") - refcnt.withRef { - throw CustomTestException() - } - } catch (_: CustomTestException) { - } catch (le: LinkageError) { - throw AssertionError("CloseableReferenceCounter still has dependency on kotlin stdlib", le) - } - } - - @OptIn(CloseableReferenceCounter_Debug.RequiresExplicitDebug::class) - @Test(dependsOnMethods = ["testNoKotlinStdlib", "testIncrefDecrefClose_Debug", "testWithRef_Debug"]) - fun testWithRef_ErrDebug() { - try { - val refcnt = CloseableReferenceCounter_Debug("", "") - refcnt.withRef { - throw CustomTestException() - } - } catch (_: CustomTestException) { - } catch (le: LinkageError) { - throw AssertionError("CloseableReferenceCounter_Debug still has dependency on kotlin stdlib", le) - } - } -} \ No newline at end of file diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt similarity index 74% rename from src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt rename to src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt index 861ec30..fc0a092 100644 --- a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_AtomicLong.kt +++ b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt @@ -1,15 +1,15 @@ -package ru.landgrafhomyak.utility.reference_counter +package ru.landgrafhomyak.utility.closeable_state.internal -import kotlinx.atomicfu.AtomicLong +import kotlinx.atomicfu.AtomicLong as kAtomicLing import kotlinx.atomicfu.atomic import kotlinx.atomicfu.getAndUpdate import kotlinx.atomicfu.update -internal actual class _AtomicLong { - val _atomicfu: AtomicLong +internal actual class AtomicLong { + val _atomicfu: kAtomicLing actual constructor(initial: Long) { - this._atomicfu = atomic(0L) + this._atomicfu = atomic(initial) } actual fun get() = @@ -26,7 +26,7 @@ internal actual class _AtomicLong { actual fun compareAndExchange(expected: Long, newValue: Long): Long { val a = this._atomicfu - return _Misc._compareAndExchange( + return Misc._compareAndExchange( get = a::value::get, cas = a::compareAndSet, expected = expected, newValue = newValue diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt new file mode 100644 index 0000000..da92532 --- /dev/null +++ b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt @@ -0,0 +1,35 @@ +package ru.landgrafhomyak.utility.closeable_state.internal + +import kotlinx.atomicfu.AtomicRef as kAtomicRef +import kotlinx.atomicfu.atomic +import kotlinx.atomicfu.getAndUpdate +import kotlinx.atomicfu.update + +internal actual class AtomicReference { + val _atomicfu: kAtomicRef + + actual constructor(initial: T) { + this._atomicfu = atomic(initial) + } + + actual fun get() = + this._atomicfu.value + + actual inline fun update(operator: (T) -> T) = + this._atomicfu.update(operator) + + actual inline fun getAndUpdate(operator: (T) -> T) = + this._atomicfu.getAndUpdate(operator) + + actual fun compareAndSet(expected: T, newValue: T): Boolean = + this._atomicfu.compareAndSet(expected, newValue) + + actual fun compareAndExchange(expected: T, newValue: T): T { + val a = this._atomicfu + return Misc._compareAndExchange( + get = a::value::get, + cas = a::compareAndSet, + expected = expected, newValue = newValue + ) + } +} \ No newline at end of file diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt deleted file mode 100644 index 308bc97..0000000 --- a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/reference_counter/_Platform.kt +++ /dev/null @@ -1,10 +0,0 @@ -package ru.landgrafhomyak.utility.reference_counter - - -@PublishedApi -internal actual object _Platform { - @Suppress("NOTHING_TO_INLINE") - @PublishedApi - internal actual inline fun jvm_assertNotNull(x: Any?, name: String) { - } -} \ No newline at end of file