UsagesCounter expect class and ErrorOnConcurrentAccessState java implementation

This commit is contained in:
Andrew Golovashevich 2025-08-24 01:25:10 +03:00
parent c30c585f76
commit 98d76569cc
7 changed files with 125 additions and 13 deletions

View File

@ -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
}

View File

@ -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<State> _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:
}
}
}

View File

@ -0,0 +1,3 @@
package ru.landgrafhomyak.utility.closeable_state_1
public actual typealias UsagesCounter = jUsagesCounter

View File

@ -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")
}
}

View File

@ -1,7 +1,5 @@
package ru.landgrafhomyak.utility.closeable_state_1 package ru.landgrafhomyak.utility.closeable_state_1
import kotlin.IllegalStateException
internal abstract class `jUsagesCounter$Errors` { internal abstract class `jUsagesCounter$Errors` {
protected open fun throwClosed(): Nothing { protected open fun throwClosed(): Nothing {
throw IllegalStateException("Object is closed") throw IllegalStateException("Object is closed")

View File

@ -57,7 +57,7 @@ public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchr
public final override fun close() { public final override fun close() {
when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) { when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) {
State.OPEN -> {} State.OPEN -> {}
State.IN_USE -> this.throwConcurrent() State.IN_USE -> this.throwInUse()
State.CLOSED -> this.throwClosed() State.CLOSED -> this.throwClosed()
} }
} }

View File

@ -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.newAtomicLong
import ru.landgrafhomyak.utility.closeable_state_1.internal.update 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) private val _value: AtomicLong = newAtomicLong(0L)
public constructor() public actual constructor()
public fun getCurrentUsagesCount(): Long = this._value.get() public fun getCurrentUsagesCount(): Long = this._value.get()
protected open fun throwClosed(): Nothing { protected actual open fun throwClosed(): Nothing {
throw IllegalStateException("Object is closed") 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") 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() if (this._value.get() < 0) this.throwClosed()
} }
@ManualStateManipulation @ManualStateManipulation
public final override fun startUsage() { public actual final override fun startUsage() {
this._value.update { o -> this._value.update { o ->
if (o < 0) this.throwClosed() if (o < 0) this.throwClosed()
return@update o + 1 return@update o + 1
@ -41,12 +41,12 @@ public open class UsagesCounter : CloseableState.AllowsConcurrency {
} }
@ManualStateManipulation @ManualStateManipulation
public final override fun finishUsage() { public actual final override fun finishUsage() {
this._value.update(Long::dec) this._value.update(Long::dec)
} }
@ManualStateManipulation @ManualStateManipulation
public final override fun close() { public actual final override fun close() {
val state = this._value.compareAndExchange(0, Misc.CLOSED_STATE_VALUE) val state = this._value.compareAndExchange(0, Misc.CLOSED_STATE_VALUE)
when { when {
state > 0 -> this.throwInUse() 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() val cached = this._value.get()
@Suppress("LiftReturnOrAssignment") @Suppress("LiftReturnOrAssignment")
if (cached < 0) if (cached < 0)