diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ErrorOnConcurrentAccessState.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ErrorOnConcurrentAccessState.kt index ce54506..10d7e57 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ErrorOnConcurrentAccessState.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/ErrorOnConcurrentAccessState.kt @@ -1,13 +1,15 @@ package ru.landgrafhomyak.utility.closeable_state -import ru.landgrafhomyak.utility.closeable_state.internal.AtomicReference +import ru.landgrafhomyak.utility.closeable_state.internal.compareAndExchange +import ru.landgrafhomyak.utility.closeable_state.internal.get +import ru.landgrafhomyak.utility.closeable_state.internal.newAtomicRef public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchronized { private enum class State { OPEN, IN_USE, CLOSED } - private val _state = AtomicReference(State.OPEN) + private val _state = newAtomicRef(State.OPEN) final override val isInUse: Boolean diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/UsagesCounter.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/UsagesCounter.kt index 8fd0c1f..0b7fb23 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/UsagesCounter.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/UsagesCounter.kt @@ -5,9 +5,13 @@ package ru.landgrafhomyak.utility.closeable_state import kotlin.contracts.ExperimentalContracts import ru.landgrafhomyak.utility.closeable_state.internal.AtomicLong import ru.landgrafhomyak.utility.closeable_state.internal.Misc +import ru.landgrafhomyak.utility.closeable_state.internal.compareAndExchange +import ru.landgrafhomyak.utility.closeable_state.internal.get +import ru.landgrafhomyak.utility.closeable_state.internal.newAtomicLong +import ru.landgrafhomyak.utility.closeable_state.internal.update public open class UsagesCounter : CloseableState.AllowsConcurrency { - private val _value: AtomicLong = AtomicLong(0L) + private val _value: AtomicLong = newAtomicLong(0L) public constructor() diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt deleted file mode 100644 index 2f7f031..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt +++ /dev/null @@ -1,15 +0,0 @@ -package ru.landgrafhomyak.utility.closeable_state.internal - -internal expect class AtomicLong { - constructor(initial: Long) - - fun get(): Long - - inline fun update(operator: (Long) -> Long) - - inline fun getAndUpdate(operator: (Long) -> Long): Long - - fun compareAndSet(expected: Long, newValue: Long): Boolean - - fun compareAndExchange(expected: Long, newValue: Long): Long -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt deleted file mode 100644 index 106b1ce..0000000 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt +++ /dev/null @@ -1,15 +0,0 @@ -package ru.landgrafhomyak.utility.closeable_state.internal - -internal expect class AtomicReference { - constructor(initial: T) - - fun get(): T - - inline fun update(operator: (T) -> T) - - inline fun getAndUpdate(operator: (T) -> T): T - - fun compareAndSet(expected: T, newValue: T): Boolean - - fun compareAndExchange(expected: T, newValue: T): T -} \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/Misc.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/Misc.kt index 9c1337a..8400ad8 100644 --- a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/Misc.kt +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/Misc.kt @@ -12,5 +12,14 @@ internal object Misc { } } + @JvmStatic + internal inline fun _getAndUpdate(get: () -> T, cas: (T, T) -> Boolean, operator: (T) -> T): T { + while (true) { + val cur = get() + val upd = operator(cur) + if (cas(cur, upd)) return cur + } + } + internal const val CLOSED_STATE_VALUE = -0x4000_0000_0000_0000L } \ No newline at end of file diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt new file mode 100644 index 0000000..abb02c6 --- /dev/null +++ b/src/commonMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt @@ -0,0 +1,27 @@ +@file:JvmName("AtomicsKt") + +package ru.landgrafhomyak.utility.closeable_state.internal + +import kotlin.jvm.JvmName + + +internal expect class AtomicLong +internal expect class AtomicReference + +internal expect inline fun newAtomicLong(initial: Long): AtomicLong +internal expect inline fun newAtomicRef(initial: T): AtomicReference + +internal expect inline fun AtomicLong.get(): Long +internal expect inline fun AtomicReference.get(): T + +internal expect inline fun AtomicLong.update(operator: (Long) -> Long) +internal expect inline fun AtomicReference.update(operator: (T) -> T) + +internal expect inline fun AtomicLong.getAndUpdate(operator: (Long) -> Long): Long +internal expect inline fun AtomicReference.getAndUpdate(operator: (T) -> T): T + +internal expect inline fun AtomicLong.compareAndSet(expected: Long, newValue: Long): Boolean +internal expect inline fun AtomicReference.compareAndSet(expected: T, newValue: T): Boolean + +internal expect inline fun AtomicLong.compareAndExchange(expected: Long, newValue: Long): Long +internal expect inline fun AtomicReference.compareAndExchange(expected: T, newValue: T): T \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt deleted file mode 100644 index 7f0af9a..0000000 --- a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt +++ /dev/null @@ -1,58 +0,0 @@ -package ru.landgrafhomyak.utility.closeable_state.internal - -import java.util.concurrent.atomic.AtomicLong - -internal actual /*value*/ class AtomicLong { - private val _native: AtomicLong - - actual constructor(initial: Long) { - this._native = AtomicLong(initial) - } - - actual fun get() = this._native.get() - - actual inline fun update(operator: (Long) -> Long) { - while (true) { - val cur = this._native.get() - val upd = operator(cur) - if (this._native.compareAndSet(cur, upd)) return - } - } - - actual inline fun getAndUpdate(operator: (Long) -> Long): Long { - while (true) { - val cur = this._native.get() - val upd = operator(cur) - if (this._native.compareAndSet(cur, upd)) return cur - } - } - - actual fun compareAndSet(expected: Long, newValue: Long): Boolean = - this._native.compareAndSet(expected, newValue) - - actual fun compareAndExchange(expected: Long, newValue: Long): Long { - if (_Linkage.isNativeCompareAndExchangeExists) { - return this._native.compareAndExchange(expected, newValue) - } else { - val a = this._native - return Misc._compareAndExchange( - get = a::get, - cas = a::compareAndSet, - expected = expected, newValue = newValue - ) - } - } - - private object _Linkage { - @JvmStatic - val isNativeCompareAndExchangeExists = run { - val a = AtomicLong() - try { - a.compareAndExchange(0, 0) - return@run true - } catch (_: NoSuchMethodError) { - return@run false - } - } - } -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt deleted file mode 100644 index 7fb3463..0000000 --- a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt +++ /dev/null @@ -1,58 +0,0 @@ -package ru.landgrafhomyak.utility.closeable_state.internal - -import java.util.concurrent.atomic.AtomicReference as jAtomicReference - -internal actual /*value*/ class AtomicReference { - private val _native: jAtomicReference - - actual constructor(initial: T) { - this._native = jAtomicReference(initial) - } - - actual fun get() = this._native.get() - - actual inline fun update(operator: (T) -> T) { - while (true) { - val cur = this._native.get() - val upd = operator(cur) - if (this._native.compareAndSet(cur, upd)) return - } - } - - actual inline fun getAndUpdate(operator: (T) -> T): T { - while (true) { - val cur = this._native.get() - val upd = operator(cur) - if (this._native.compareAndSet(cur, upd)) return cur - } - } - - actual fun compareAndSet(expected: T, newValue: T): Boolean = - this._native.compareAndSet(expected, newValue) - - actual fun compareAndExchange(expected: T, newValue: T): T { - if (_Linkage.isNativeCompareAndExchangeExists) { - return this._native.compareAndExchange(expected, newValue) - } else { - val a = this._native - return Misc._compareAndExchange( - get = a::get, - cas = a::compareAndSet, - expected = expected, newValue = newValue - ) - } - } - - private object _Linkage { - @JvmStatic - val isNativeCompareAndExchangeExists = run { - val a = jAtomicReference(null) - try { - a.compareAndExchange(null, null) - return@run true - } catch (_: NoSuchMethodError) { - return@run false - } - } - } -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt new file mode 100644 index 0000000..30fe646 --- /dev/null +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt @@ -0,0 +1,124 @@ +@file:Suppress("USELESS_CAST", "NOTHING_TO_INLINE") +@file:JvmName("AtomicsKt") + +package ru.landgrafhomyak.utility.closeable_state.internal + +import java.util.concurrent.atomic.AtomicLong as jAtomicLong +import java.util.concurrent.atomic.AtomicReference as jAtomicReference +import kotlin.jvm.JvmName + + +internal actual typealias AtomicLong = jAtomicLong +internal actual typealias AtomicReference = jAtomicReference + + +internal actual inline fun newAtomicLong(initial: Long): AtomicLong = + jAtomicLong(initial) + +internal actual inline fun newAtomicRef(initial: T): AtomicReference = + jAtomicReference(initial) + + +internal actual inline fun AtomicLong.get(): Long = + (this as jAtomicLong).get() + +internal actual inline fun AtomicReference.get(): T = + (this as jAtomicReference).get() + + +internal actual inline fun AtomicLong.update(operator: (Long) -> Long) { + val a = (this as jAtomicLong) + Misc._getAndUpdate( + get = a::get, + cas = a::compareAndSet, + operator = operator + ) +} + +internal actual inline fun AtomicReference.update(operator: (T) -> T) { + val a = (this as jAtomicReference) + Misc._getAndUpdate( + get = a::get, + cas = a::compareAndSet, + operator = operator + ) +} + +internal actual inline fun AtomicLong.getAndUpdate(operator: (Long) -> Long): Long { + val a = (this as jAtomicLong) + return Misc._getAndUpdate( + get = a::get, + cas = a::compareAndSet, + operator = operator + ) +} + +internal actual inline fun AtomicReference.getAndUpdate(operator: (T) -> T): T { + val a = (this as jAtomicReference) + return Misc._getAndUpdate( + get = a::get, + cas = a::compareAndSet, + operator = operator + ) +} + + +internal actual inline fun AtomicLong.compareAndSet(expected: Long, newValue: Long): Boolean = + (this as jAtomicLong).compareAndSet(expected, newValue) + +internal actual inline fun AtomicReference.compareAndSet(expected: T, newValue: T): Boolean = + (this as jAtomicReference).compareAndSet(expected, newValue) + + +private fun AtomicLong.`compareAndExchange$custom`(expected: Long, newValue: Long): Long { + val a = (this as jAtomicLong) + return Misc._compareAndExchange( + get = a::get, + cas = a::compareAndSet, + expected = expected, newValue = newValue + ) +} + + +private fun AtomicReference.`compareAndExchange$custom`(expected: T, newValue: T): T { + val a = (this as jAtomicReference) + return Misc._compareAndExchange( + get = a::get, + cas = a::compareAndSet, + expected = expected, newValue = newValue + ) +} + +internal actual inline fun AtomicLong.compareAndExchange(expected: Long, newValue: Long): Long { + if (_long_isNativeCompareAndExchangeExists) + return (this as jAtomicLong).compareAndExchange(expected, newValue) + else + return this.`compareAndExchange$custom`(expected, newValue) +} + +internal actual inline fun AtomicReference.compareAndExchange(expected: T, newValue: T): T { + if (_ref_isNativeCompareAndExchangeExists) + return (this as jAtomicReference).compareAndExchange(expected, newValue) + else + return this.`compareAndExchange$custom`(expected, newValue) +} + +private val _long_isNativeCompareAndExchangeExists = run { + val a = jAtomicLong() + try { + a.compareAndExchange(0, 0) + return@run true + } catch (_: NoSuchMethodError) { + return@run false + } +} + +private val _ref_isNativeCompareAndExchangeExists = run { + val a = jAtomicReference() + try { + a.compareAndExchange(null, null) + return@run true + } catch (_: NoSuchMethodError) { + return@run false + } +} \ No newline at end of file diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt deleted file mode 100644 index fc0a092..0000000 --- a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicLong.kt +++ /dev/null @@ -1,35 +0,0 @@ -package ru.landgrafhomyak.utility.closeable_state.internal - -import kotlinx.atomicfu.AtomicLong as kAtomicLing -import kotlinx.atomicfu.atomic -import kotlinx.atomicfu.getAndUpdate -import kotlinx.atomicfu.update - -internal actual class AtomicLong { - val _atomicfu: kAtomicLing - - actual constructor(initial: Long) { - this._atomicfu = atomic(initial) - } - - actual fun get() = - this._atomicfu.value - - actual inline fun update(operator: (Long) -> Long) = - this._atomicfu.update(operator) - - actual inline fun getAndUpdate(operator: (Long) -> Long) = - this._atomicfu.getAndUpdate(operator) - - actual fun compareAndSet(expected: Long, newValue: Long): Boolean = - this._atomicfu.compareAndSet(expected, newValue) - - actual fun compareAndExchange(expected: Long, newValue: Long): Long { - val a = this._atomicfu - return Misc._compareAndExchange( - get = a::value::get, - cas = a::compareAndSet, - expected = expected, newValue = newValue - ) - } -} \ No newline at end of file diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt deleted file mode 100644 index da92532..0000000 --- a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/AtomicReference.kt +++ /dev/null @@ -1,35 +0,0 @@ -package ru.landgrafhomyak.utility.closeable_state.internal - -import kotlinx.atomicfu.AtomicRef as kAtomicRef -import kotlinx.atomicfu.atomic -import kotlinx.atomicfu.getAndUpdate -import kotlinx.atomicfu.update - -internal actual class AtomicReference { - val _atomicfu: kAtomicRef - - actual constructor(initial: T) { - this._atomicfu = atomic(initial) - } - - actual fun get() = - this._atomicfu.value - - actual inline fun update(operator: (T) -> T) = - this._atomicfu.update(operator) - - actual inline fun getAndUpdate(operator: (T) -> T) = - this._atomicfu.getAndUpdate(operator) - - actual fun compareAndSet(expected: T, newValue: T): Boolean = - this._atomicfu.compareAndSet(expected, newValue) - - actual fun compareAndExchange(expected: T, newValue: T): T { - val a = this._atomicfu - return Misc._compareAndExchange( - get = a::value::get, - cas = a::compareAndSet, - expected = expected, newValue = newValue - ) - } -} \ No newline at end of file diff --git a/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt new file mode 100644 index 0000000..fe56975 --- /dev/null +++ b/src/nonJvmMain/kotlin/ru/landgrafhomyak/utility/closeable_state/internal/atomics.kt @@ -0,0 +1,8 @@ +@file:JvmName("AtomicsKt") +package ru.landgrafhomyak.utility.closeable_state.internal + +import kotlin.jvm.JvmName + + +internal actual typealias AtomicLong = kotlinx.atomicfu.AtomicLong +internal actual typealias AtomicReference = kotlinx.atomicfu.AtomicRef \ No newline at end of file