ErrorOnConcurrentAccessState expect class, java8 -> java9 and minor fixes

This commit is contained in:
Andrew Golovashevich 2025-08-24 01:36:49 +03:00
parent 98d76569cc
commit ad87bb7904
8 changed files with 94 additions and 39 deletions

View File

@ -37,12 +37,12 @@ xomrk {
compilations.configureEach {
compileJavaTaskProvider?.configure {
targetCompatibility = "1.8"
sourceCompatibility = "1.8"
targetCompatibility = "9"
sourceCompatibility = "9"
}
compileTaskProvider.configure {
compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
jvmTarget = JvmTarget.JVM_9
freeCompilerArgs.addAll(
"-Xno-call-assertions",
"-Xno-param-assertions",

View File

@ -0,0 +1,29 @@
package ru.landgrafhomyak.utility.closeable_state_1
public expect open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchronized {
public constructor()
public final override val isInUse: Boolean
protected open fun throwClosed(): Nothing
protected open fun throwInUse(): Nothing
protected open fun throwConcurrent(): Nothing
public final override fun assertNotClosed()
public final override val isClosed: Boolean
@ManualStateManipulation
public final override fun startUsage()
@ManualStateManipulation
public final override fun finishUsage()
@ManualStateManipulation
public final override fun close()
@Suppress("RedundantModalityModifier")
public open override fun toString(): String
}

View File

@ -25,5 +25,6 @@ public expect open class UsagesCounter : CloseableState.AllowsConcurrency {
@ManualStateManipulation
public final override fun close()
@Suppress("RedundantModalityModifier")
public open override fun toString(): String
}

View File

@ -2,9 +2,10 @@ package ru.landgrafhomyak.utility.closeable_state_1;
import java.util.concurrent.atomic.AtomicReference;
public class jErrorOnConcurrentAccessState
public /* open */ class jErrorOnConcurrentAccessState
extends jErrorOnConcurrentAccessState$Errors
implements CloseableState.ExternallySynchronized {
private enum State {
OPEN, IN_USE, CLOSED
}
@ -16,23 +17,23 @@ public class jErrorOnConcurrentAccessState
}
@Override
public boolean isInUse() {
public final boolean isInUse() {
return this._currentState.get() == State.IN_USE;
}
@Override
public boolean isClosed() {
public final boolean isClosed() {
return this._currentState.get() == State.CLOSED;
}
@Override
public void assertNotClosed() {
public final void assertNotClosed() {
if (this.isClosed())
this.throwClosed();
}
@Override
public void startUsage() {
public final void startUsage() {
switch (this._currentState.compareAndExchange(State.OPEN, State.IN_USE)) {
case IN_USE:
this.throwConcurrent();
@ -44,7 +45,7 @@ public class jErrorOnConcurrentAccessState
}
@Override
public void finishUsage() {
public final 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");
@ -55,7 +56,7 @@ public class jErrorOnConcurrentAccessState
}
@Override
public void close() {
public final void close() {
switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) {
case CLOSED:
this.throwClosed();
@ -64,4 +65,17 @@ public class jErrorOnConcurrentAccessState
case OPEN:
}
}
@Override
public String toString() {
switch (this._currentState.get()) {
case CLOSED:
return "<closeable error-on-concurrent-access state [free]>";
case IN_USE:
return "<closeable error-on-concurrent-access state [in use]>";
case OPEN:
return "<closeable error-on-concurrent-access state [close]>";
}
throw new RuntimeException("Unreachable");
}
}

View File

@ -4,63 +4,72 @@ import ru.landgrafhomyak.utility.closeable_state_1.internal.Misc;
import java.util.concurrent.atomic.AtomicLong;
public class jUsagesCounter extends jUsagesCounter$Errors implements CloseableState.AllowsConcurrency {
private final AtomicLong _referencesCounter;
public /* open */ class jUsagesCounter extends jUsagesCounter$Errors implements CloseableState.AllowsConcurrency {
private final AtomicLong _currentUsagesCount;
public jUsagesCounter() {
this._referencesCounter = new AtomicLong(0);
this._currentUsagesCount = new AtomicLong(0);
}
@Override
public boolean isClosed() {
return this._referencesCounter.get() < 0;
public final boolean isClosed() {
return this._currentUsagesCount.get() < 0;
}
@Override
public void assertNotClosed() {
if (this._referencesCounter.get() < 0)
public final void assertNotClosed() {
if (this._currentUsagesCount.get() < 0)
this.throwClosed();
}
@Override
public void startUsage() {
public final void startUsage() {
while (true) {
final long cur = this._referencesCounter.get();
final long cur = this._currentUsagesCount.get();
if (cur < 0) {
this.throwClosed();
return;
}
if (this._referencesCounter.compareAndSet(cur, cur + 1))
if (this._currentUsagesCount.compareAndSet(cur, cur + 1))
return;
}
}
@Override
public void finishUsage() {
public final void finishUsage() {
while (true) {
final long cur = this._referencesCounter.get();
final long cur = this._currentUsagesCount.get();
if (cur < 0) {
this.throwClosed();
return;
}
if (this._referencesCounter.compareAndSet(cur, cur - 1))
if (this._currentUsagesCount.compareAndSet(cur, cur - 1))
return;
}
}
@Override
public void close() {
public final void close() {
long currentReferencesCount;
while (true) {
currentReferencesCount = this._referencesCounter.get();
currentReferencesCount = this._currentUsagesCount.get();
if (currentReferencesCount != 0) break;
if (this._referencesCounter.compareAndSet(currentReferencesCount, Misc.CLOSED_STATE_VALUE))
if (this._currentUsagesCount.compareAndSet(currentReferencesCount, Misc.CLOSED_STATE_VALUE))
break;
}
if (currentReferencesCount > 0) this.throwInUse();
if (currentReferencesCount < 0) this.throwClosed();
}
@Override
public String toString() {
final long cached = this._currentUsagesCount.get();
if (cached < 0)
return "<closeable usages counter [closed]>";
else
return "<closeable usages counter [" + cached + "]>";
}
}

View File

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

View File

@ -4,39 +4,38 @@ import ru.landgrafhomyak.utility.closeable_state_1.internal.compareAndExchange
import ru.landgrafhomyak.utility.closeable_state_1.internal.get
import ru.landgrafhomyak.utility.closeable_state_1.internal.newAtomicRef
public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchronized {
public actual open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchronized {
private enum class State {
OPEN, IN_USE, CLOSED
}
private val _state = newAtomicRef(State.OPEN)
public final override val isInUse: Boolean
public actual final override val isInUse: Boolean
get() = this._state.get() === State.IN_USE
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")
}
protected open fun throwConcurrent(): Nothing {
protected actual open fun throwConcurrent(): Nothing {
throw IllegalStateException("Object is in use by another thread")
}
public final override fun assertNotClosed() {
public actual final override fun assertNotClosed() {
if (this._state.get() === State.CLOSED)
this.throwClosed()
}
public final override val isClosed: Boolean
public actual final override val isClosed: Boolean
get() = this._state.get() === State.CLOSED
@ManualStateManipulation
public final override fun startUsage() {
public actual final override fun startUsage() {
when (this._state.compareAndExchange(State.OPEN, State.IN_USE)) {
State.OPEN -> {}
State.IN_USE -> this.throwConcurrent()
@ -45,7 +44,7 @@ public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchr
}
@ManualStateManipulation
public final override fun finishUsage() {
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")
State.IN_USE -> {}
@ -54,7 +53,7 @@ public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchr
}
@ManualStateManipulation
public final override fun close() {
public actual final override fun close() {
when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) {
State.OPEN -> {}
State.IN_USE -> this.throwInUse()
@ -63,7 +62,8 @@ public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchr
}
public open override fun toString(): String =
@Suppress("RedundantModalityModifier")
public actual open override fun toString(): String =
when (this._state.get()) {
State.OPEN -> "<closeable error-on-concurrent-access state [free]>"
State.IN_USE -> "<closeable error-on-concurrent-access state [in use]>"

View File

@ -54,6 +54,7 @@ public actual open class UsagesCounter : CloseableState.AllowsConcurrency {
}
}
@Suppress("RedundantModalityModifier")
public actual open override fun toString(): String {
val cached = this._value.get()
@Suppress("LiftReturnOrAssignment")