'close' method moved to separate class; autoClosed scope
This commit is contained in:
parent
d5ed25cb54
commit
140b463ce8
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,4 +6,5 @@ build/
|
|||||||
*.jar
|
*.jar
|
||||||
/out/
|
/out/
|
||||||
/gradlew*
|
/gradlew*
|
||||||
.kotlin/
|
.kotlin/
|
||||||
|
/kotlin-js-store
|
||||||
@ -1,90 +1,29 @@
|
|||||||
@file:OptIn(ExperimentalContracts::class)
|
|
||||||
|
|
||||||
package ru.landrafhomyak.utility.reference_counter
|
package ru.landrafhomyak.utility.reference_counter
|
||||||
|
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
import kotlin.jvm.JvmStatic
|
||||||
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
|
||||||
|
|
||||||
public class CloseableReferenceCounter {
|
public class CloseableReferenceCounter : MayBeClosedReferenceCounter {
|
||||||
private val _value: _AtomicLong
|
public constructor(errMessageClosed: String) : super(errMessageClosed)
|
||||||
private val _errMessageClosed: String
|
|
||||||
|
|
||||||
public constructor(errMessageClosed: String) {
|
|
||||||
_Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed")
|
|
||||||
this._errMessageClosed = errMessageClosed
|
|
||||||
this._value = _AtomicLong(0L)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmName("throwClosed")
|
|
||||||
public fun throwClosed() {
|
|
||||||
throw IllegalStateException(this._errMessageClosed)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmName("incref")
|
|
||||||
public fun incref() {
|
|
||||||
this._value.update { o ->
|
|
||||||
if (o < 0) this.throwClosed()
|
|
||||||
return@update o + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmName("tryIncref\$kt")
|
|
||||||
public inline fun <R> tryIncref(block: () -> R): R {
|
|
||||||
contract {
|
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
|
||||||
}
|
|
||||||
this.incref()
|
|
||||||
return safeAutoClose2(onError = this::decref, action = block)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmName("assertNotClosed")
|
|
||||||
public fun assertNotClosed() {
|
|
||||||
if (this._value.get() < 0) this.throwClosed()
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmName("decref")
|
|
||||||
public fun decref() {
|
|
||||||
this._value.update(Long::dec)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmName("tryDecref\$kt")
|
|
||||||
public inline fun <R> tryDecref(block: () -> R): R {
|
|
||||||
contract {
|
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
|
||||||
}
|
|
||||||
this.assertNotClosed()
|
|
||||||
return safeAutoClose2(onSuccess = this::decref, action = block)
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:JvmName("isClosed")
|
|
||||||
public val isClosed: Boolean get() = this._value.get() < 0
|
|
||||||
|
|
||||||
|
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||||
@JvmName("close")
|
@JvmName("close")
|
||||||
public fun close(errExistRefs: String) {
|
public override fun close(errExistRefs: String) {
|
||||||
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
|
super.close(errExistRefs)
|
||||||
val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE)
|
}
|
||||||
when {
|
|
||||||
state > 0 -> throw IllegalStateException(errExistRefs)
|
public companion object {
|
||||||
state < 0 -> this.throwClosed()
|
@JvmStatic
|
||||||
|
@JvmName("autoClosed")
|
||||||
|
public fun <R> autoClosed(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R {
|
||||||
|
_Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed")
|
||||||
|
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
|
||||||
|
_Platform.jvm_assertNotNull(scope, "param: scope")
|
||||||
|
|
||||||
|
val refcnt = CloseableReferenceCounter(errMessageClosed)
|
||||||
|
val ret = scope(refcnt)
|
||||||
|
refcnt.close(errExistRefs)
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("withRef\$kt")
|
|
||||||
public inline fun <R> withRef(protected: () -> R): R {
|
|
||||||
this.incref()
|
|
||||||
return safeAutoClose1(finally = this::decref, action = protected)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
val refcntCached = this._value.get()
|
|
||||||
@Suppress("LiftReturnOrAssignment")
|
|
||||||
if (refcntCached < 0)
|
|
||||||
return "<ref counter [closed]>"
|
|
||||||
else
|
|
||||||
return "<ref counter [${refcntCached}]>"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
@file:OptIn(ExperimentalContracts::class)
|
||||||
|
|
||||||
|
package ru.landrafhomyak.utility.reference_counter
|
||||||
|
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
import kotlin.jvm.JvmName
|
||||||
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
|
|
||||||
|
public sealed class MayBeClosedReferenceCounter {
|
||||||
|
private val _value: _AtomicLong
|
||||||
|
private val _errMessageClosed: String
|
||||||
|
|
||||||
|
protected constructor(errMessageClosed: String) {
|
||||||
|
_Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed")
|
||||||
|
this._errMessageClosed = errMessageClosed
|
||||||
|
this._value = _AtomicLong(0L)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("throwClosed")
|
||||||
|
public fun throwClosed() {
|
||||||
|
throw IllegalStateException(this._errMessageClosed)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("incref")
|
||||||
|
public fun incref() {
|
||||||
|
this._value.update { o ->
|
||||||
|
if (o < 0) this.throwClosed()
|
||||||
|
return@update o + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("tryIncref\$kt")
|
||||||
|
public inline fun <R> tryIncref(block: () -> R): R {
|
||||||
|
contract {
|
||||||
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
this.incref()
|
||||||
|
return safeAutoClose2(onError = this::decref, action = block)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("assertNotClosed")
|
||||||
|
public fun assertNotClosed() {
|
||||||
|
if (this._value.get() < 0) this.throwClosed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("decref")
|
||||||
|
public fun decref() {
|
||||||
|
this._value.update(Long::dec)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("tryDecref\$kt")
|
||||||
|
public inline fun <R> tryDecref(block: () -> R): R {
|
||||||
|
contract {
|
||||||
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
this.assertNotClosed()
|
||||||
|
return safeAutoClose2(onSuccess = this::decref, action = block)
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:JvmName("isClosed")
|
||||||
|
public val isClosed: Boolean get() = this._value.get() < 0
|
||||||
|
|
||||||
|
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||||
|
@JvmName("close")
|
||||||
|
protected open fun close(errExistRefs: String) {
|
||||||
|
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
|
||||||
|
val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE)
|
||||||
|
when {
|
||||||
|
state > 0 -> throw IllegalStateException(errExistRefs)
|
||||||
|
state < 0 -> this.throwClosed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("withRef\$kt")
|
||||||
|
public inline fun <R> withRef(protected: () -> R): R {
|
||||||
|
this.incref()
|
||||||
|
return safeAutoClose1(finally = this::decref, action = protected)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val refcntCached = this._value.get()
|
||||||
|
@Suppress("LiftReturnOrAssignment")
|
||||||
|
if (refcntCached < 0)
|
||||||
|
return "<ref counter [closed]>"
|
||||||
|
else
|
||||||
|
return "<ref counter [${refcntCached}]>"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user