Inlined atomics (no wrapper class anymore)

This commit is contained in:
Andrew Golovashevich 2025-08-22 05:35:40 +03:00
parent d4db1907d9
commit 860ffa98e0
12 changed files with 177 additions and 219 deletions

View File

@ -1,13 +1,15 @@
package ru.landgrafhomyak.utility.closeable_state 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 { public open class ErrorOnConcurrentAccessState : CloseableState.ExternallySynchronized {
private enum class State { private enum class State {
OPEN, IN_USE, CLOSED OPEN, IN_USE, CLOSED
} }
private val _state = AtomicReference(State.OPEN) private val _state = newAtomicRef(State.OPEN)
final override val isInUse: Boolean final override val isInUse: Boolean

View File

@ -5,9 +5,13 @@ package ru.landgrafhomyak.utility.closeable_state
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import ru.landgrafhomyak.utility.closeable_state.internal.AtomicLong import ru.landgrafhomyak.utility.closeable_state.internal.AtomicLong
import ru.landgrafhomyak.utility.closeable_state.internal.Misc 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 { public open class UsagesCounter : CloseableState.AllowsConcurrency {
private val _value: AtomicLong = AtomicLong(0L) private val _value: AtomicLong = newAtomicLong(0L)
public constructor() public constructor()

View File

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

View File

@ -1,15 +0,0 @@
package ru.landgrafhomyak.utility.closeable_state.internal
internal expect class AtomicReference<T> {
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
}

View File

@ -12,5 +12,14 @@ internal object Misc {
} }
} }
@JvmStatic
internal inline fun <T> _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 internal const val CLOSED_STATE_VALUE = -0x4000_0000_0000_0000L
} }

View File

@ -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<T>
internal expect inline fun newAtomicLong(initial: Long): AtomicLong
internal expect inline fun <T> newAtomicRef(initial: T): AtomicReference<T>
internal expect inline fun AtomicLong.get(): Long
internal expect inline fun <T> AtomicReference<T>.get(): T
internal expect inline fun AtomicLong.update(operator: (Long) -> Long)
internal expect inline fun <T> AtomicReference<T>.update(operator: (T) -> T)
internal expect inline fun AtomicLong.getAndUpdate(operator: (Long) -> Long): Long
internal expect inline fun <T> AtomicReference<T>.getAndUpdate(operator: (T) -> T): T
internal expect inline fun AtomicLong.compareAndSet(expected: Long, newValue: Long): Boolean
internal expect inline fun <T> AtomicReference<T>.compareAndSet(expected: T, newValue: T): Boolean
internal expect inline fun AtomicLong.compareAndExchange(expected: Long, newValue: Long): Long
internal expect inline fun <T> AtomicReference<T>.compareAndExchange(expected: T, newValue: T): T

View File

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

View File

@ -1,58 +0,0 @@
package ru.landgrafhomyak.utility.closeable_state.internal
import java.util.concurrent.atomic.AtomicReference as jAtomicReference
internal actual /*value*/ class AtomicReference<T> {
private val _native: jAtomicReference<T>
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
}
}
}
}

View File

@ -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<T> = jAtomicReference<T>
internal actual inline fun newAtomicLong(initial: Long): AtomicLong =
jAtomicLong(initial)
internal actual inline fun <T> newAtomicRef(initial: T): AtomicReference<T> =
jAtomicReference(initial)
internal actual inline fun AtomicLong.get(): Long =
(this as jAtomicLong).get()
internal actual inline fun <T> AtomicReference<T>.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 <T> AtomicReference<T>.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 <T> AtomicReference<T>.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 <T> AtomicReference<T>.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 <T> AtomicReference<T>.`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 <T> AtomicReference<T>.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<Nothing?>()
try {
a.compareAndExchange(null, null)
return@run true
} catch (_: NoSuchMethodError) {
return@run false
}
}

View File

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

View File

@ -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<T> {
val _atomicfu: kAtomicRef<T>
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
)
}
}

View File

@ -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<T> = kotlinx.atomicfu.AtomicRef<T>