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 new file mode 100644 index 0000000..606a4b6 --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/UsagesCounter.kt @@ -0,0 +1,29 @@ +@file:OptIn(ExperimentalContracts::class) + +package ru.landgrafhomyak.utility.closeable_state_1 + +import kotlin.contracts.ExperimentalContracts + +public expect open class UsagesCounter : CloseableState.AllowsConcurrency { + public constructor() + + protected open fun throwClosed(): Nothing + + protected open fun throwInUse(): Nothing + + + public final override val isClosed: Boolean + + public final override fun assertNotClosed() + + @ManualStateManipulation + public final override fun startUsage() + + @ManualStateManipulation + public final override fun finishUsage() + + @ManualStateManipulation + public final override fun close() + + public open override fun toString(): String +} \ No newline at end of file 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 new file mode 100644 index 0000000..0f82a72 --- /dev/null +++ b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/jErrorOnConcurrentAccessState.java @@ -0,0 +1,67 @@ +package ru.landgrafhomyak.utility.closeable_state_1; + +import java.util.concurrent.atomic.AtomicReference; + +public class jErrorOnConcurrentAccessState + extends jErrorOnConcurrentAccessState$Errors + implements CloseableState.ExternallySynchronized { + private enum State { + OPEN, IN_USE, CLOSED + } + + private final AtomicReference _currentState; + + public jErrorOnConcurrentAccessState() { + this._currentState = new AtomicReference<>(); + } + + @Override + public boolean isInUse() { + return this._currentState.get() == State.IN_USE; + } + + @Override + public boolean isClosed() { + return this._currentState.get() == State.CLOSED; + } + + @Override + public void assertNotClosed() { + if (this.isClosed()) + this.throwClosed(); + } + + @Override + public void startUsage() { + switch (this._currentState.compareAndExchange(State.OPEN, State.IN_USE)) { + case IN_USE: + this.throwConcurrent(); + case CLOSED: + this.throwClosed(); + case OPEN: + break; + } + } + + @Override + public void finishUsage() { + switch (this._currentState.compareAndExchange(State.IN_USE, State.OPEN)) { + case OPEN: + throw new IllegalStateException("Can't finish usage because not it not started"); + case CLOSED: + this.throwClosed(); + case IN_USE: + } + } + + @Override + public void close() { + switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) { + case CLOSED: + this.throwClosed(); + case IN_USE: + this.throwInUse(); + case OPEN: + } + } +} diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/actuals.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/actuals.kt new file mode 100644 index 0000000..596ff93 --- /dev/null +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/actuals.kt @@ -0,0 +1,3 @@ +package ru.landgrafhomyak.utility.closeable_state_1 + +public actual typealias UsagesCounter = jUsagesCounter \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/jErrorOnConcurrentAccessState$Errors.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/jErrorOnConcurrentAccessState$Errors.kt new file mode 100644 index 0000000..8b74f91 --- /dev/null +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/jErrorOnConcurrentAccessState$Errors.kt @@ -0,0 +1,15 @@ +package ru.landgrafhomyak.utility.closeable_state_1 + +internal abstract class `jErrorOnConcurrentAccessState$Errors` : CloseableState.ExternallySynchronized { + protected open fun throwClosed(): Nothing { + throw IllegalStateException("Object is closed") + } + + protected open fun throwInUse(): Nothing { + throw IllegalStateException("Failed close object because it is in use") + } + + protected open fun throwConcurrent(): Nothing { + throw IllegalStateException("Object is in use by another thread") + } +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/jUsagesCounter$Errors.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/jUsagesCounter$Errors.kt index cb1bc9c..1e3536e 100644 --- a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/jUsagesCounter$Errors.kt +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/jUsagesCounter$Errors.kt @@ -1,7 +1,5 @@ package ru.landgrafhomyak.utility.closeable_state_1 -import kotlin.IllegalStateException - internal abstract class `jUsagesCounter$Errors` { protected open fun throwClosed(): Nothing { throw IllegalStateException("Object is closed") diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt similarity index 98% rename from src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt rename to src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt index 3ecd9ff..257890c 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt +++ b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/ErrorOnConcurrentAccessState.kt @@ -57,7 +57,7 @@ public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchr public final override fun close() { when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) { State.OPEN -> {} - State.IN_USE -> this.throwConcurrent() + State.IN_USE -> this.throwInUse() State.CLOSED -> this.throwClosed() } } 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 83534ed..cdd5861 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 @@ -10,30 +10,30 @@ import ru.landgrafhomyak.utility.closeable_state_1.internal.get import ru.landgrafhomyak.utility.closeable_state_1.internal.newAtomicLong import ru.landgrafhomyak.utility.closeable_state_1.internal.update -public open class UsagesCounter : CloseableState.AllowsConcurrency { +public actual open class UsagesCounter : CloseableState.AllowsConcurrency { private val _value: AtomicLong = newAtomicLong(0L) - public constructor() + public actual constructor() public fun getCurrentUsagesCount(): Long = this._value.get() - protected open fun throwClosed(): Nothing { + protected actual open fun throwClosed(): Nothing { throw IllegalStateException("Object is closed") } - protected open fun throwInUse(): Nothing { + protected actual open 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 actual final override val isClosed: Boolean get() = this._value.get() < 0 - public final override fun assertNotClosed() { + public actual final override fun assertNotClosed() { if (this._value.get() < 0) this.throwClosed() } @ManualStateManipulation - public final override fun startUsage() { + public actual final override fun startUsage() { this._value.update { o -> if (o < 0) this.throwClosed() return@update o + 1 @@ -41,12 +41,12 @@ public open class UsagesCounter : CloseableState.AllowsConcurrency { } @ManualStateManipulation - public final override fun finishUsage() { + public actual final override fun finishUsage() { this._value.update(Long::dec) } @ManualStateManipulation - public final override fun close() { + public actual final override fun close() { val state = this._value.compareAndExchange(0, Misc.CLOSED_STATE_VALUE) when { state > 0 -> this.throwInUse() @@ -54,7 +54,7 @@ public open class UsagesCounter : CloseableState.AllowsConcurrency { } } - public open override fun toString(): String { + public actual open override fun toString(): String { val cached = this._value.get() @Suppress("LiftReturnOrAssignment") if (cached < 0)