diff --git a/build.gradle.kts b/build.gradle.kts index cc60afa..ef708cc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -82,6 +82,7 @@ xomrk { jvmTest { dependencies { + implementation(kotlinStdlibDependency) implementation("org.testng:testng:7.5.1") } } diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ChildCloseableState.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ChildCloseableState.kt index 9954050..2b071f5 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ChildCloseableState.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ChildCloseableState.kt @@ -25,6 +25,10 @@ public sealed class ChildCloseableState : CloseableState { override fun startUsage(): Unit = this._state.startUsage() + @ManualStateManipulation + override fun startUsageIfNotClosed(): Boolean = + this._state.startUsageIfNotClosed() + @ManualStateManipulation override fun finishUsage(): Unit = this._state.finishUsage() diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableState.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableState.kt index cc4be3a..74bf782 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableState.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableState.kt @@ -8,6 +8,13 @@ public interface CloseableState { @ManualStateManipulation public fun startUsage() + /** + * Tries to start usage and returns `false` if entered or `true` if closed. + * Doesn't prevent from throwing error if this state forbids concurrent access. + */ + @ManualStateManipulation + public fun startUsageIfNotClosed(): Boolean + @ManualStateManipulation public fun finishUsage() diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableStateCloseableWrapper.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableStateCloseableWrapper.kt index 73e6f14..8fa1062 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableStateCloseableWrapper.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableStateCloseableWrapper.kt @@ -13,6 +13,9 @@ public expect class CloseableStateCloseableWrapper : CloseableState.ExternallySy @ManualStateManipulation override fun startUsage() + @ManualStateManipulation + override fun startUsageIfNotClosed(): Boolean + @ManualStateManipulation override fun finishUsage() diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt index ddb5edb..2609685 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt @@ -18,6 +18,9 @@ public expect open class ErrorOnConcurrentAccessState : CloseableState.Externall @ManualStateManipulation public final override fun startUsage() + @ManualStateManipulation + public final override fun startUsageIfNotClosed(): Boolean + @ManualStateManipulation public final override fun finishUsage() diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt index 6cb2f4f..d4b1e1d 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt @@ -19,6 +19,9 @@ public expect open class UsagesCounter : CloseableState.AllowsConcurrency { @ManualStateManipulation public final override fun startUsage() + @ManualStateManipulation + public final override fun startUsageIfNotClosed(): Boolean + @ManualStateManipulation public final override fun finishUsage() diff --git a/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jCloseableStateCloseableWrapper.java b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jCloseableStateCloseableWrapper.java index f6d6c02..d82f621 100644 --- a/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jCloseableStateCloseableWrapper.java +++ b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jCloseableStateCloseableWrapper.java @@ -31,6 +31,7 @@ public final class jCloseableStateCloseableWrapper this._self.assertNotClosed(); } + @ManualStateManipulation @Override public void startUsage() { this._self.startUsage(); @@ -46,12 +47,35 @@ public final class jCloseableStateCloseableWrapper } } + @ManualStateManipulation + @Override + public boolean startUsageIfNotClosed() { + if (this._self.startUsageIfNotClosed()) + return true; + try { + if (this._parent.startUsageIfNotClosed()) { + this._self.finishUsage(); + return true; + } + } catch (Throwable e1) { + try { + this._self.finishUsage(); + } catch (Throwable e2) { + e1.addSuppressed(e2); + } + throw e1; + } + return false; + } + + @ManualStateManipulation @Override public void finishUsage() { this._parent.finishUsage(); this._self.finishUsage(); } + @ManualStateManipulation @Override public void finishUsage(boolean close) { this._parent.finishUsage(); @@ -59,6 +83,7 @@ public final class jCloseableStateCloseableWrapper } @Destructor + @ManualStateManipulation @Override public void close() { this._self.close(); @@ -68,4 +93,5 @@ public final class jCloseableStateCloseableWrapper public String toString() { return ""; } + } diff --git a/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jErrorOnConcurrentAccessState.java b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jErrorOnConcurrentAccessState.java index 57da347..17f9161 100644 --- a/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jErrorOnConcurrentAccessState.java +++ b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jErrorOnConcurrentAccessState.java @@ -32,16 +32,25 @@ public /* open */ class jErrorOnConcurrentAccessState this.throwClosed(); } + @ManualStateManipulation @Override public final void startUsage() { + if (this.startUsageIfNotClosed()) + this.throwClosed(); + } + + @ManualStateManipulation + @Override + public final boolean startUsageIfNotClosed() { switch (this._currentState.compareAndExchange(State.OPEN, State.IN_USE)) { case IN_USE: this.throwConcurrent(); case CLOSED: - this.throwClosed(); + return true; case OPEN: - break; + return false; } + throw new RuntimeException("Unreachable"); } private void _finishUsage(State nextState) { @@ -55,17 +64,20 @@ public /* open */ class jErrorOnConcurrentAccessState } + @ManualStateManipulation @Override public final void finishUsage() { this._finishUsage(State.OPEN); } + @ManualStateManipulation @Override public void finishUsage(boolean close) { this._finishUsage(close ? State.CLOSED : State.OPEN); } @Destructor + @ManualStateManipulation @Override public final void close() { switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) { diff --git a/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jUsagesCounter.java b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jUsagesCounter.java index 0be54c7..913940c 100644 --- a/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jUsagesCounter.java +++ b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jUsagesCounter.java @@ -22,20 +22,28 @@ public /* open */ class jUsagesCounter this.throwClosed(); } + @ManualStateManipulation @Override public final void startUsage() { + if (this.startUsageIfNotClosed()) + this.throwClosed(); + } + + @ManualStateManipulation + @Override + public final boolean startUsageIfNotClosed() { while (true) { final long cur = this._currentUsagesCount.get(); if (cur < 0) { - this.throwClosed(); - return; + return true; } if (this._currentUsagesCount.compareAndSet(cur, cur + 1)) - return; + return false; } } + @ManualStateManipulation @Override public final void finishUsage() { while (true) { @@ -51,6 +59,7 @@ public /* open */ class jUsagesCounter } @Destructor + @ManualStateManipulation @Override public final void close() { long currentReferencesCount; diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableStateCloseableWrapper.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableStateCloseableWrapper.kt index d6494a4..7c22bdb 100644 --- a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableStateCloseableWrapper.kt +++ b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/CloseableStateCloseableWrapper.kt @@ -36,6 +36,26 @@ public actual class CloseableStateCloseableWrapper : CloseableState.ExternallySy } } + @ManualStateManipulation + actual override fun startUsageIfNotClosed(): Boolean { + if (this._self.startUsageIfNotClosed()) + return true + try { + if (this._parent.startUsageIfNotClosed()) { + this._self.finishUsage() + return true + } + } catch (e1: Throwable) { + try { + this._self.finishUsage() + } catch (e2: Throwable) { + e1.addSuppressed(e2) + } + throw e1 + } + return false; + } + @ManualStateManipulation actual override fun finishUsage() { this._parent.finishUsage() diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt index 0834fc9..a42b3a3 100644 --- a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt +++ b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt @@ -35,10 +35,16 @@ public actual open class ErrorOnConcurrentAccessState : CloseableState.Externall @ManualStateManipulation public actual final override fun startUsage() { + if (this.startUsageIfNotClosed()) + this.throwClosed() + } + + @ManualStateManipulation + public actual final override fun startUsageIfNotClosed(): Boolean { when (this._state.compareAndExchange(State.OPEN, State.IN_USE)) { - State.OPEN -> {} + State.OPEN -> return false; State.IN_USE -> this.throwConcurrent() - State.CLOSED -> this.throwClosed() + State.CLOSED -> return true } } diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt index 648ded7..832c784 100644 --- a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt +++ b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt @@ -38,6 +38,15 @@ public actual open class UsagesCounter : CloseableState.AllowsConcurrency { } } + @ManualStateManipulation + public actual final override fun startUsageIfNotClosed(): Boolean { + this._value.update { o -> + if (o < 0) return true + return@update o + 1 + } + return false + } + @ManualStateManipulation public actual final override fun finishUsage() { this._value.update(Long::dec)