From 6ea651ce6d67fcb2fcc6a192c05808ed266da398 Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Fri, 3 Oct 2025 19:49:01 +0300 Subject: [PATCH] SpinLockSynchronizedState --- build.gradle.kts | 2 +- .../SpinLockSynchronizedState.java | 106 ++++++++++++++++++ .../OwnedSpinLockSynchronizedState.kt | 37 ++++++ .../SpinLockSynchronizedState$Errors.kt | 11 ++ 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/SpinLockSynchronizedState.java create mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/OwnedSpinLockSynchronizedState.kt create mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/SpinLockSynchronizedState$Errors.kt diff --git a/build.gradle.kts b/build.gradle.kts index a5fed5c..6ae5067 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ buildscript { } group = "ru.landgrafhomyak.utility" -version = "1.3" +version = "1.4" repositories { mavenCentral() diff --git a/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/SpinLockSynchronizedState.java b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/SpinLockSynchronizedState.java new file mode 100644 index 0000000..f5b263b --- /dev/null +++ b/src/jvmMain/java/ru/landgrafhomyak/utility/closeable_state_1/SpinLockSynchronizedState.java @@ -0,0 +1,106 @@ +package ru.landgrafhomyak.utility.closeable_state_1; + +import java.util.concurrent.atomic.AtomicReference; + +public /* open */ class SpinLockSynchronizedState + extends SpinLockSynchronizedState$Errors + implements CloseableState.ExternallySynchronized { + + private enum State { + OPEN, IN_USE, CLOSED + } + + private final AtomicReference _currentState; + + public SpinLockSynchronizedState() { + this._currentState = new AtomicReference<>(State.OPEN); + } + + @Override + public final boolean isInUse() { + return this._currentState.get() == State.IN_USE; + } + + @Override + public final boolean isClosed() { + return this._currentState.get() == State.CLOSED; + } + + @Override + public final void assertNotClosed() { + if (this.isClosed()) + this.throwClosed(); + } + + @ManualStateManipulation + @Override + public final void startUsage() { + if (this.startUsageIfNotClosed()) + this.throwClosed(); + } + + @ManualStateManipulation + @Override + public final boolean startUsageIfNotClosed() { + while (true) { + switch (this._currentState.compareAndExchange(State.OPEN, State.IN_USE)) { + case IN_USE: + Thread.onSpinWait(); + continue; + case CLOSED: + return true; + case OPEN: + return false; + } + } + } + + private void _finishUsage(State nextState) { + switch (this._currentState.compareAndExchange(State.IN_USE, nextState)) { + case OPEN: + throw new IllegalStateException("Can't finish usage because it isn't started"); + case CLOSED: + this.throwClosed(); + case IN_USE: + } + } + + + @ManualStateManipulation + @Override + public final void finishUsage() { + this._finishUsage(State.OPEN); + } + + @ManualStateManipulation + @Override + public void finishUsage(boolean close) { + this._finishUsage(close ? State.CLOSED : State.OPEN); + } + + @Destructor + @ManualStateManipulation + @Override + public final void close() { + switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) { + case CLOSED: + this.throwClosed(); + case IN_USE: + this.throwInUse(); + case OPEN: + } + } + + @Override + public String toString() { + switch (this._currentState.get()) { + case CLOSED: + return ""; + case IN_USE: + return ""; + case OPEN: + return ""; + } + throw new RuntimeException("Unreachable"); + } +} diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/OwnedSpinLockSynchronizedState.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/OwnedSpinLockSynchronizedState.kt new file mode 100644 index 0000000..7324eb2 --- /dev/null +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/OwnedSpinLockSynchronizedState.kt @@ -0,0 +1,37 @@ +@file:OptIn(ExperimentalContracts::class) + +package ru.landgrafhomyak.utility.closeable_state_1 + +import kotlin.contracts.ExperimentalContracts + +public class OwnedSpinLockSynchronizedState : SpinLockSynchronizedState { + private var _owner: Any? + + public constructor() : super() { + this._owner = null + } + + public constructor(owner: Any) : super() { + this._owner = owner + } + + public var owner: Any + get() = this._owner ?: throw IllegalStateException("Owner not set yet") + set(value) { + if (this._owner != null) throw IllegalStateException("Owner already initialized") + this._owner = value + } + + override fun throwClosed(): Nothing { + throw IllegalStateException("Object is closed: ${this._owner}") + } + + override fun throwInUse(): Nothing { + throw IllegalStateException("Failed close object because it is in use: ${this._owner}") + } + + override fun toString(): String { + val base = super.toString() + return base.substring(0, base.length - 1) + " of ${this._owner}>" + } +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/SpinLockSynchronizedState$Errors.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/SpinLockSynchronizedState$Errors.kt new file mode 100644 index 0000000..0e415e8 --- /dev/null +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state_1/SpinLockSynchronizedState$Errors.kt @@ -0,0 +1,11 @@ +package ru.landgrafhomyak.utility.closeable_state_1 + +internal abstract class `SpinLockSynchronizedState$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") + } +} \ No newline at end of file