Using native 'compareAndExchange' on java if possible
This commit is contained in:
parent
77a72a2a7c
commit
fe6d2c22ef
@ -31,7 +31,7 @@ xomrk {
|
||||
|
||||
defineAllMultiplatformTargets()
|
||||
|
||||
jvmToolchain(8)
|
||||
jvmToolchain(11)
|
||||
jvm {
|
||||
withJava()
|
||||
|
||||
|
@ -66,7 +66,7 @@ public class CloseableReferenceCounter {
|
||||
@JvmName("close")
|
||||
public fun close(errExistRefs: String) {
|
||||
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
|
||||
val state = _CloseableReferenceCounter_LowLevel.compareAndExchange(this._value, 0, _CloseableReferenceCounter_LowLevel.CLOSED_STATE_VALUE)
|
||||
val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE)
|
||||
when {
|
||||
state > 0 -> throw IllegalStateException(errExistRefs)
|
||||
state < 0 -> this.throwClosed()
|
||||
|
@ -41,9 +41,9 @@ public class CloseableReferenceCounter_Debug {
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun _throwErrors(valueToCheck: Long) {
|
||||
when {
|
||||
valueToCheck >= 0 || valueToCheck == _CloseableReferenceCounter_LowLevel.CLOSED_STATE_VALUE -> {}
|
||||
valueToCheck < _CloseableReferenceCounter_LowLevel.CLOSED_STATE_VALUE -> throw RuntimeException("Too many references")
|
||||
valueToCheck > _CloseableReferenceCounter_LowLevel.CLOSED_STATE_VALUE -> throw RuntimeException(".decref called more times than .incref")
|
||||
valueToCheck >= 0 || valueToCheck == _Misc.CLOSED_STATE_VALUE -> {}
|
||||
valueToCheck < _Misc.CLOSED_STATE_VALUE -> throw RuntimeException("Too many references")
|
||||
valueToCheck > _Misc.CLOSED_STATE_VALUE -> throw RuntimeException(".decref called more times than .incref")
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ public class CloseableReferenceCounter_Debug {
|
||||
@JvmName("close")
|
||||
public fun close(errExistRefs: String) {
|
||||
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
|
||||
val state = _CloseableReferenceCounter_LowLevel.compareAndExchange(this._value, 0, _CloseableReferenceCounter_LowLevel.CLOSED_STATE_VALUE)
|
||||
val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE)
|
||||
this._throwErrors(state)
|
||||
when {
|
||||
state > 0 -> throw IllegalStateException(errExistRefs)
|
||||
@ -139,9 +139,9 @@ public class CloseableReferenceCounter_Debug {
|
||||
@Suppress("LiftReturnOrAssignment")
|
||||
when {
|
||||
refcntCached >= 0 -> stateRepr = refcntCached.toString()
|
||||
refcntCached == _CloseableReferenceCounter_LowLevel.CLOSED_STATE_VALUE -> stateRepr = "closed"
|
||||
refcntCached < _CloseableReferenceCounter_LowLevel.CLOSED_STATE_VALUE -> stateRepr = "overflow"
|
||||
refcntCached > _CloseableReferenceCounter_LowLevel.CLOSED_STATE_VALUE -> stateRepr = "underflow"
|
||||
refcntCached == _Misc.CLOSED_STATE_VALUE -> stateRepr = "closed"
|
||||
refcntCached < _Misc.CLOSED_STATE_VALUE -> stateRepr = "overflow"
|
||||
refcntCached > _Misc.CLOSED_STATE_VALUE -> stateRepr = "underflow"
|
||||
else -> throw Error("Unreachable")
|
||||
}
|
||||
return "<ref counter \"${this._dbgName}@${this._id}\" [${stateRepr}]>"
|
||||
|
@ -7,7 +7,9 @@ internal expect class _AtomicLong {
|
||||
|
||||
inline fun update(operator: (Long) -> Long)
|
||||
|
||||
inline fun getAndUpdate(operator: (Long) -> Long):Long
|
||||
inline fun getAndUpdate(operator: (Long) -> Long): Long
|
||||
|
||||
fun compareAndSet(expected: Long, newValue: Long): Boolean
|
||||
|
||||
fun compareAndExchange(expected: Long, newValue: Long): Long
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package ru.landrafhomyak.utility.reference_counter
|
||||
|
||||
@Suppress("ClassName")
|
||||
internal object _CloseableReferenceCounter_LowLevel {
|
||||
internal fun compareAndExchange(atomic: _AtomicLong, expected: Long, newValue: Long): Long {
|
||||
while (true) {
|
||||
val old = atomic.get()
|
||||
if (old != expected) return old
|
||||
if (atomic.compareAndSet(old, newValue)) return old
|
||||
}
|
||||
}
|
||||
|
||||
internal const val CLOSED_STATE_VALUE = -0x4000_0000_0000_0000L
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package ru.landrafhomyak.utility.reference_counter
|
||||
|
||||
import kotlin.jvm.JvmStatic
|
||||
|
||||
@Suppress("ClassName")
|
||||
internal object _Misc {
|
||||
@JvmStatic
|
||||
internal inline fun _compareAndExchange(get: () -> Long, cas: (Long, Long) -> Boolean, expected: Long, newValue: Long): Long {
|
||||
while (true) {
|
||||
val old = get()
|
||||
if (old != expected) return old
|
||||
if (cas(old, newValue)) return old
|
||||
}
|
||||
}
|
||||
|
||||
internal const val CLOSED_STATE_VALUE = -0x4000_0000_0000_0000L
|
||||
}
|
@ -29,4 +29,25 @@ internal actual /*value*/ class _AtomicLong {
|
||||
|
||||
actual fun compareAndSet(expected: Long, newValue: Long): Boolean =
|
||||
this._native.compareAndSet(expected, newValue)
|
||||
|
||||
actual fun compareAndExchange(expected: Long, newValue: Long): Long =
|
||||
if (_Linkage._isNativeCompareAndExchangeExists) this._native.compareAndExchange(expected, newValue)
|
||||
else _Misc._compareAndExchange(
|
||||
get = this._native::get,
|
||||
cas = this._native::compareAndSet,
|
||||
expected = expected, newValue = newValue
|
||||
)
|
||||
|
||||
private object _Linkage {
|
||||
@JvmField
|
||||
val _isNativeCompareAndExchangeExists = run {
|
||||
val a = AtomicLong()
|
||||
try {
|
||||
a.compareAndExchange(0, 0)
|
||||
return@run true
|
||||
} catch (_: NoSuchMethodError) {
|
||||
return@run false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,4 +23,11 @@ internal actual class _AtomicLong {
|
||||
|
||||
actual fun compareAndSet(expected: Long, newValue: Long): Boolean =
|
||||
this._atomicfu.compareAndSet(expected, newValue)
|
||||
|
||||
actual fun compareAndExchange(expected: Long, newValue: Long): Long =
|
||||
_Misc._compareAndExchange(
|
||||
get = this._atomicfu::value::get,
|
||||
cas = this._atomicfu::compareAndSet,
|
||||
expected = expected, newValue = newValue
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user