Compare commits

...

3 Commits
v0.2 ... master

9 changed files with 66 additions and 25 deletions

View File

@ -31,7 +31,7 @@ xomrk {
defineAllMultiplatformTargets()
jvmToolchain(8)
jvmToolchain(11)
jvm {
withJava()

View File

@ -3,3 +3,4 @@ kotlin.mpp.applyDefaultHierarchyTemplate=false
kotlin.native.enableKlibsCrossCompilation=true
# compileOnly dependencies from commonMain still throw warning
kotlin.suppressGradlePluginWarnings=IncorrectCompileOnlyDependencyWarning
kotlin.js.stdlib.dom.api.included=false

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -29,4 +29,30 @@ 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) {
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 {
@JvmField
val _isNativeCompareAndExchangeExists = run {
val a = AtomicLong()
try {
a.compareAndExchange(0, 0)
return@run true
} catch (_: NoSuchMethodError) {
return@run false
}
}
}
}

View File

@ -23,4 +23,13 @@ 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 {
val a = this._atomicfu
return _Misc._compareAndExchange(
get = a::value::get,
cas = a::compareAndSet,
expected = expected, newValue = newValue
)
}
}