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 944278e..0c4a878 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 @@ -59,8 +59,20 @@ public sealed class ChildCloseableState : CloseableState { override val isInUse: Boolean get() = this._state.isInUse + @ManualStateManipulation + override fun finishUsage(close: Boolean) { + this._state.finishUsage(close) + } + override fun toString(): String { - TODO("Not yet implemented") + when { + this._state is OwnedErrorOnConcurrentAccessState || this._state::class === ErrorOnConcurrentAccessState::class -> { + val base = this._state.toString() + return base.substring(0, base.length - 1) + " (child of ${this._parent})>" + } + + else -> return "" + } } } } \ No newline at end of file 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 94ac59a..3146172 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 @@ -20,5 +20,8 @@ public interface CloseableState { public interface ExternallySynchronized : CloseableState { public val isInUse: Boolean + + @ManualStateManipulation + public fun finishUsage(close: Boolean) } } \ No newline at end of file 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 3d6e9d2..bf7821b 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 @@ -6,6 +6,7 @@ public class CloseableStateCloseableWrapper( ) : CloseableState.ExternallySynchronized { override val isInUse: Boolean by this._self::isInUse + override val isClosed: Boolean by this._self::isInUse override fun assertNotClosed(): Unit = @@ -25,6 +26,13 @@ public class CloseableStateCloseableWrapper( } } + @ManualStateManipulation + override fun finishUsage(close: Boolean) { + this._self.tryFinishUsageThenClose(close) { + this._parent.finishUsage() + } + } + @ManualStateManipulation override fun close() { this._self.close() 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 e170688..0a86903 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 @@ -21,6 +21,9 @@ public expect open class ErrorOnConcurrentAccessState : CloseableState.Externall @ManualStateManipulation public final override fun finishUsage() + @ManualStateManipulation + public final override fun finishUsage(close: Boolean) + @ManualStateManipulation public final override fun close() diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/children_scopes.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/children_scopes.kt index 14e08c4..2019f1f 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/children_scopes.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/children_scopes.kt @@ -7,23 +7,6 @@ import kotlin.contracts.contract import kotlin.jvm.JvmName import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 - -@OptIn(ManualStateManipulation::class) -public inline fun autoClosed( - constructor: () -> S, - scope: (S) -> R, -): R { - contract { - callsInPlace(constructor, InvocationKind.EXACTLY_ONCE) - callsInPlace(scope, InvocationKind.EXACTLY_ONCE) - } - val state = constructor() - return safeAutoClose1( - action = { scope(state) }, - finally = state::close - ) -} - @OptIn(ManualStateManipulation::class) public inline fun CloseableState.childAC( constructor: () -> CloseableState.AllowsConcurrency = ::UsagesCounter, diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/internal/Misc.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/internal/Misc.kt deleted file mode 100644 index 156f295..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/internal/Misc.kt +++ /dev/null @@ -1,25 +0,0 @@ -package ru.landgrafhomyak.utility.closeable_state_1.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 - } - } - - @JvmStatic - internal inline fun _getAndUpdate(get: () -> T, cas: (T, T) -> Boolean, operator: (T) -> T): T { - while (true) { - val cur = get() - val upd = operator(cur) - if (cas(cur, upd)) return cur - } - } - - 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_1/usage_scopes.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/usage_scopes.kt index 8f629f8..b27b403 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/usage_scopes.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/usage_scopes.kt @@ -9,7 +9,23 @@ 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 autoClosed( + constructor: () -> S, + scope: (S) -> R, +): R { + contract { + callsInPlace(constructor, InvocationKind.EXACTLY_ONCE) + callsInPlace(scope, InvocationKind.EXACTLY_ONCE) + } + val state = constructor() + return safeAutoClose1( + action = { scope(state) }, + finally = state::close + ) +} + +@OptIn(ManualStateManipulation::class) +@JvmName("withUse\$kt") public inline fun CloseableState.withUse(block: () -> R): R { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) @@ -37,4 +53,43 @@ public inline fun CloseableState.tryFinishUsage(block: () -> R): R { } this.assertNotClosed() return safeAutoClose2(action = block, onSuccess = this::finishUsage) -} \ No newline at end of file +} + +@OptIn(ManualStateManipulation::class) +@JvmName("withUseThenClose\$kt") +public inline fun CloseableState.ExternallySynchronized.withUseThenClose(block: () -> Boolean) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + this.startUsage() + var needClose = false + return safeAutoClose1( + action = { needClose = block() }, + finally = { this.finishUsage(needClose) } + ) +} + + +@ManualStateManipulation +@JvmName("tryFinishUsageThenClose\$kt") +public inline fun CloseableState.ExternallySynchronized.tryFinishUsageThenClose(close: Boolean, block: () -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + this.assertNotClosed() + return safeAutoClose2(action = block, onSuccess = { this.finishUsage(close) }) +} + +@ManualStateManipulation +@JvmName("tryFinishUsageThenClose\$kt") +public inline fun CloseableState.ExternallySynchronized.tryFinishUsageThenClose(block: () -> Boolean) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + this.assertNotClosed() + var needClose = false + return safeAutoClose2( + action = { needClose = block() }, + onSuccess = { this.finishUsage(needClose) } + ) +} 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 1faa414..432eeb5 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 @@ -44,17 +44,27 @@ public /* open */ class jErrorOnConcurrentAccessState } } - @Override - public final void finishUsage() { - switch (this._currentState.compareAndExchange(State.IN_USE, State.OPEN)) { + private void _finishUsage(State nextState) { + switch (this._currentState.compareAndExchange(State.IN_USE, nextState)) { case OPEN: - throw new IllegalStateException("Can't finish usage because not it not started"); + throw new IllegalStateException("Can't finish usage because it isn't started"); case CLOSED: this.throwClosed(); case IN_USE: } } + + @Override + public final void finishUsage() { + this._finishUsage(State.OPEN); + } + + @Override + public void finishUsage(boolean close) { + this._finishUsage(close ? State.CLOSED : State.OPEN); + } + @Override public final void close() { switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) { 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 9c5bb04..ff9e2a1 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 @@ -43,14 +43,22 @@ public actual open class ErrorOnConcurrentAccessState : CloseableState.Externall } @ManualStateManipulation - public actual final 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") + private fun _finishUsage(nextState: State) { + when (this._state.compareAndExchange(State.IN_USE, nextState)) { + State.OPEN -> throw IllegalStateException("Can't finish usage because it isn't started") State.IN_USE -> {} State.CLOSED -> this.throwClosed() } } + @ManualStateManipulation + public actual final override fun finishUsage(): Unit = + this._finishUsage(State.OPEN) + + @ManualStateManipulation + public actual final override fun finishUsage(close: Boolean): Unit = + this._finishUsage(if (close) State.CLOSED else State.OPEN) + @ManualStateManipulation public actual final override fun close() { when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) {