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 { compilations.configureEach {
compileJavaTaskProvider?.configure { compileJavaTaskProvider?.configure {
targetCompatibility = "1.8" targetCompatibility = "9"
sourceCompatibility = "1.8" sourceCompatibility = "9"
} }
compileTaskProvider.configure { compileTaskProvider.configure {
compilerOptions { compilerOptions {
jvmTarget = JvmTarget.JVM_1_8 jvmTarget = JvmTarget.JVM_9
freeCompilerArgs.addAll( freeCompilerArgs.addAll(
"-Xno-call-assertions", "-Xno-call-assertions",
"-Xno-param-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 @ManualStateManipulation
public final override fun close() public final override fun close()
@Suppress("RedundantModalityModifier")
public open override fun toString(): String 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; import java.util.concurrent.atomic.AtomicReference;
public class jErrorOnConcurrentAccessState public /* open */ class jErrorOnConcurrentAccessState
extends jErrorOnConcurrentAccessState$Errors extends jErrorOnConcurrentAccessState$Errors
implements CloseableState.ExternallySynchronized { implements CloseableState.ExternallySynchronized {
private enum State { private enum State {
OPEN, IN_USE, CLOSED OPEN, IN_USE, CLOSED
} }
@ -16,23 +17,23 @@ public class jErrorOnConcurrentAccessState
} }
@Override @Override
public boolean isInUse() { public final boolean isInUse() {
return this._currentState.get() == State.IN_USE; return this._currentState.get() == State.IN_USE;
} }
@Override @Override
public boolean isClosed() { public final boolean isClosed() {
return this._currentState.get() == State.CLOSED; return this._currentState.get() == State.CLOSED;
} }
@Override @Override
public void assertNotClosed() { public final void assertNotClosed() {
if (this.isClosed()) if (this.isClosed())
this.throwClosed(); this.throwClosed();
} }
@Override @Override
public void startUsage() { public final void startUsage() {
switch (this._currentState.compareAndExchange(State.OPEN, State.IN_USE)) { switch (this._currentState.compareAndExchange(State.OPEN, State.IN_USE)) {
case IN_USE: case IN_USE:
this.throwConcurrent(); this.throwConcurrent();
@ -44,7 +45,7 @@ public class jErrorOnConcurrentAccessState
} }
@Override @Override
public void finishUsage() { public final void finishUsage() {
switch (this._currentState.compareAndExchange(State.IN_USE, State.OPEN)) { switch (this._currentState.compareAndExchange(State.IN_USE, State.OPEN)) {
case OPEN: case OPEN:
throw new IllegalStateException("Can't finish usage because not it not started"); throw new IllegalStateException("Can't finish usage because not it not started");
@ -55,7 +56,7 @@ public class jErrorOnConcurrentAccessState
} }
@Override @Override
public void close() { public final void close() {
switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) { switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) {
case CLOSED: case CLOSED:
this.throwClosed(); this.throwClosed();
@ -64,4 +65,17 @@ public class jErrorOnConcurrentAccessState
case OPEN: 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; import java.util.concurrent.atomic.AtomicLong;
public class jUsagesCounter extends jUsagesCounter$Errors implements CloseableState.AllowsConcurrency { public /* open */ class jUsagesCounter extends jUsagesCounter$Errors implements CloseableState.AllowsConcurrency {
private final AtomicLong _referencesCounter; private final AtomicLong _currentUsagesCount;
public jUsagesCounter() { public jUsagesCounter() {
this._referencesCounter = new AtomicLong(0); this._currentUsagesCount = new AtomicLong(0);
} }
@Override @Override
public boolean isClosed() { public final boolean isClosed() {
return this._referencesCounter.get() < 0; return this._currentUsagesCount.get() < 0;
} }
@Override @Override
public void assertNotClosed() { public final void assertNotClosed() {
if (this._referencesCounter.get() < 0) if (this._currentUsagesCount.get() < 0)
this.throwClosed(); this.throwClosed();
} }
@Override @Override
public void startUsage() { public final void startUsage() {
while (true) { while (true) {
final long cur = this._referencesCounter.get(); final long cur = this._currentUsagesCount.get();
if (cur < 0) { if (cur < 0) {
this.throwClosed(); this.throwClosed();
return; return;
} }
if (this._referencesCounter.compareAndSet(cur, cur + 1)) if (this._currentUsagesCount.compareAndSet(cur, cur + 1))
return; return;
} }
} }
@Override @Override
public void finishUsage() { public final void finishUsage() {
while (true) { while (true) {
final long cur = this._referencesCounter.get(); final long cur = this._currentUsagesCount.get();
if (cur < 0) { if (cur < 0) {
this.throwClosed(); this.throwClosed();
return; return;
} }
if (this._referencesCounter.compareAndSet(cur, cur - 1)) if (this._currentUsagesCount.compareAndSet(cur, cur - 1))
return; return;
} }
} }
@Override @Override
public void close() { public final void close() {
long currentReferencesCount; long currentReferencesCount;
while (true) { while (true) {
currentReferencesCount = this._referencesCounter.get(); currentReferencesCount = this._currentUsagesCount.get();
if (currentReferencesCount != 0) break; if (currentReferencesCount != 0) break;
if (this._referencesCounter.compareAndSet(currentReferencesCount, Misc.CLOSED_STATE_VALUE)) if (this._currentUsagesCount.compareAndSet(currentReferencesCount, Misc.CLOSED_STATE_VALUE))
break; break;
} }
if (currentReferencesCount > 0) this.throwInUse(); if (currentReferencesCount > 0) this.throwInUse();
if (currentReferencesCount < 0) this.throwClosed(); 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 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.get
import ru.landgrafhomyak.utility.closeable_state_1.internal.newAtomicRef 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 { private enum class State {
OPEN, IN_USE, CLOSED OPEN, IN_USE, CLOSED
} }
private val _state = newAtomicRef(State.OPEN) private val _state = newAtomicRef(State.OPEN)
public actual final override val isInUse: Boolean
public final override val isInUse: Boolean
get() = this._state.get() === State.IN_USE get() = this._state.get() === State.IN_USE
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")
} }
protected open fun throwConcurrent(): Nothing { protected actual open fun throwConcurrent(): Nothing {
throw IllegalStateException("Object is in use by another thread") 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) if (this._state.get() === State.CLOSED)
this.throwClosed() this.throwClosed()
} }
public final override val isClosed: Boolean public actual final override val isClosed: Boolean
get() = this._state.get() === State.CLOSED get() = this._state.get() === State.CLOSED
@ManualStateManipulation @ManualStateManipulation
public final override fun startUsage() { public actual final override fun startUsage() {
when (this._state.compareAndExchange(State.OPEN, State.IN_USE)) { when (this._state.compareAndExchange(State.OPEN, State.IN_USE)) {
State.OPEN -> {} State.OPEN -> {}
State.IN_USE -> this.throwConcurrent() State.IN_USE -> this.throwConcurrent()
@ -45,7 +44,7 @@ public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchr
} }
@ManualStateManipulation @ManualStateManipulation
public final override fun finishUsage() { public actual final override fun finishUsage() {
when (this._state.compareAndExchange(State.IN_USE, State.OPEN)) { when (this._state.compareAndExchange(State.IN_USE, State.OPEN)) {
State.OPEN -> throw IllegalStateException("Can't finish usage because not it not started") State.OPEN -> throw IllegalStateException("Can't finish usage because not it not started")
State.IN_USE -> {} State.IN_USE -> {}
@ -54,7 +53,7 @@ public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchr
} }
@ManualStateManipulation @ManualStateManipulation
public final override fun close() { public actual 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.throwInUse() 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()) { when (this._state.get()) {
State.OPEN -> "<closeable error-on-concurrent-access state [free]>" State.OPEN -> "<closeable error-on-concurrent-access state [free]>"
State.IN_USE -> "<closeable error-on-concurrent-access state [in use]>" 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 { public actual open override fun toString(): String {
val cached = this._value.get() val cached = this._value.get()
@Suppress("LiftReturnOrAssignment") @Suppress("LiftReturnOrAssignment")