Inlined atomics (no wrapper class anymore)
This commit is contained in:
parent
d4db1907d9
commit
860ffa98e0
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
Loading…
Reference in New Issue
Block a user