Compare commits

...

3 Commits
v0.4 ... master

17 changed files with 474 additions and 159 deletions

View File

@ -15,7 +15,7 @@ buildscript {
} }
group = "ru.landgrafhomyak.utility" group = "ru.landgrafhomyak.utility"
version = "0.4" version = "0.5"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -0,0 +1,19 @@
package ru.landgrafhomyak.utility.reference_counter
import kotlin.jvm.JvmName
public class ChildReferenceCounter : MayBeClosedReferenceCounter {
private val _parent: MayBeClosedReferenceCounter
internal constructor(parent: MayBeClosedReferenceCounter, errMessageClosed: String) : super(errMessageClosed) {
this._parent = parent
}
@Suppress("INAPPLICABLE_JVM_NAME")
@JvmName("close")
public override fun close(errExistRefs: String) {
this._parent.tryDecref {
super.close(errExistRefs)
}
}
}

View File

@ -0,0 +1,35 @@
package ru.landgrafhomyak.utility.reference_counter
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic
public class CloseableReferenceCounter : MayBeClosedReferenceCounter {
public constructor(errMessageClosed: String) : super(errMessageClosed)
@Suppress("INAPPLICABLE_JVM_NAME")
@JvmName("close")
public override fun close(errExistRefs: String) {
super.close(errExistRefs)
}
public companion object {
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
@JvmStatic
@JvmName("autoClosed")
public fun <R> autoClosed(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R {
contract {
callsInPlace(scope, InvocationKind.EXACTLY_ONCE)
}
_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
}
}
}

View File

@ -0,0 +1,164 @@
@file:OptIn(ExperimentalContracts::class)
package ru.landgrafhomyak.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
@CloseableReferenceCounter_Debug.RequiresExplicitDebug
public class CloseableReferenceCounter_Debug {
public fun interface Observer {
public fun observeState(instance: CloseableReferenceCounter_Debug, actions: String)
}
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY)
public annotation class RequiresExplicitDebug
private val _dbgName: String
private val _errMessage: String
private val _logger: Observer?
private val _value: _AtomicLong
private val _id: Long
public constructor(dbgName: String, errMessage: String, logger: Observer? = null) {
_Platform.jvm_assertNotNull(dbgName, "param: dbgName")
_Platform.jvm_assertNotNull(errMessage, "param: errMessage")
this._dbgName = dbgName
this._errMessage = dbgName
this._logger = logger
this._value = _AtomicLong(0L)
@Suppress("RemoveRedundantQualifierName")
this._id = CloseableReferenceCounter_Debug._nextId.getAndUpdate(Long::inc)
}
@Suppress("NOTHING_TO_INLINE")
private inline fun _throwErrors(valueToCheck: Long) {
when {
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")
}
}
@RequiresExplicitDebug
@JvmName("throwErrors")
public fun throwErrors() {
this._throwErrors(this._value.get())
}
@JvmName("throwClosed")
public fun throwClosed() {
throw IllegalStateException(this._errMessage)
}
@JvmName("incref")
public fun incref() {
this._value.update { o ->
if (o < 0) {
this._throwErrors(o)
this.throwClosed()
this._throwErrors(o + 1)
}
return@update o + 1
}
this._logger?.observeState(this, "incref")
}
@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 { o ->
if (o < 0) {
this._throwErrors(o)
this.throwClosed()
this._throwErrors(o - 1)
}
return@update o - 1
}
this._logger?.observeState(this, "decref")
}
@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() {
val state = this._value.get()
this._throwErrors(state)
return state < 0;
}
@JvmName("close")
public fun close(errExistRefs: String) {
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE)
this._throwErrors(state)
when {
state > 0 -> throw IllegalStateException(errExistRefs)
state < 0 -> this.throwClosed()
}
this._logger?.observeState(this, "closed")
}
@JvmName("withRef\$kt")
public inline fun <R> withRef(protected: () -> R): R {
contract {
callsInPlace(protected, InvocationKind.EXACTLY_ONCE)
}
this.incref()
return safeAutoClose1(finally = this::decref, action = protected)
}
override fun toString(): String {
val refcntCached = this._value.get()
val stateRepr: String
@Suppress("LiftReturnOrAssignment")
when {
refcntCached >= 0 -> stateRepr = refcntCached.toString()
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}]>"
}
public companion object {
private val _nextId = _AtomicLong(0L)
}
public object ObserveToStdout : Observer {
override fun observeState(instance: CloseableReferenceCounter_Debug, actions: String) {
_Platform.jvm_assertNotNull(instance, "param: instance")
_Platform.jvm_assertNotNull(actions, "param: actions")
print("${instance} ${actions}\n")
}
}
}

View File

@ -0,0 +1,145 @@
@file:OptIn(ExperimentalContracts::class)
package ru.landgrafhomyak.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 {
contract {
callsInPlace(protected, InvocationKind.EXACTLY_ONCE)
}
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}]>"
}
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
@JvmName("child")
public fun <R> child(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R {
contract {
callsInPlace(scope, InvocationKind.EXACTLY_ONCE)
}
_Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed")
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
_Platform.jvm_assertNotNull(scope, "param: scope")
this.withRef {
return CloseableReferenceCounter.autoClosed(
errMessageClosed = errMessageClosed,
errExistRefs = errExistRefs,
scope = scope
)
}
}
@JvmName("newChild")
public fun newChild(errMessageClosed: String): ChildReferenceCounter {
_Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed")
this.tryIncref {
return ChildReferenceCounter(this, errMessageClosed)
}
}
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
@JvmName("child_inheritErrMessage")
public fun <R> child_inheritErrMessage(errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R {
contract {
callsInPlace(scope, InvocationKind.EXACTLY_ONCE)
}
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
_Platform.jvm_assertNotNull(scope, "param: scope")
return this.child(
errMessageClosed = this._errMessageClosed,
errExistRefs = errExistRefs,
scope = scope
)
}
@JvmName("newChild_inheritErrMessage")
public fun newChild_inheritErrMessage(): ChildReferenceCounter {
return this.newChild(this._errMessageClosed)
}
}

View File

@ -1,4 +1,4 @@
package ru.landrafhomyak.utility.reference_counter package ru.landgrafhomyak.utility.reference_counter
internal expect class _AtomicLong { internal expect class _AtomicLong {
constructor(initial: Long) constructor(initial: Long)

View File

@ -1,4 +1,4 @@
package ru.landrafhomyak.utility.reference_counter package ru.landgrafhomyak.utility.reference_counter
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic

View File

@ -1,4 +1,4 @@
package ru.landrafhomyak.utility.reference_counter package ru.landgrafhomyak.utility.reference_counter
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic

View File

@ -4,14 +4,21 @@ import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
import ru.landgrafhomyak.utility.reference_counter._Platform
import ru.landgrafhomyak.utility.reference_counter.CloseableReferenceCounter as moved_CloseableReferenceCounter
@Suppress("DEPRECATION_ERROR")
@Deprecated(
message = "Class moved to another package",
level = DeprecationLevel.ERROR
)
public class CloseableReferenceCounter : MayBeClosedReferenceCounter { public class CloseableReferenceCounter : MayBeClosedReferenceCounter {
public constructor(errMessageClosed: String) : super(errMessageClosed) public constructor(errMessageClosed: String) : super(moved_CloseableReferenceCounter(errMessageClosed))
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME", "NON_FINAL_MEMBER_IN_FINAL_CLASS")
@JvmName("close") @JvmName("close")
public override fun close(errExistRefs: String) { public open fun close(errExistRefs: String) {
super.close(errExistRefs) (this._moved as moved_CloseableReferenceCounter).close(errExistRefs)
} }
public companion object { public companion object {
@ -22,14 +29,9 @@ public class CloseableReferenceCounter : MayBeClosedReferenceCounter {
contract { contract {
callsInPlace(scope, InvocationKind.EXACTLY_ONCE) callsInPlace(scope, InvocationKind.EXACTLY_ONCE)
} }
_Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed")
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
_Platform.jvm_assertNotNull(scope, "param: scope") _Platform.jvm_assertNotNull(scope, "param: scope")
val refcnt = CloseableReferenceCounter(errMessageClosed) return moved_CloseableReferenceCounter.autoClosed(errMessageClosed, errExistRefs, WrapperReferenceCounter.wrapperLambda(scope))
val ret = scope(refcnt)
refcnt.close(errExistRefs)
return ret
} }
} }
} }

View File

@ -5,70 +5,57 @@ package ru.landrafhomyak.utility.reference_counter
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.jvm.JvmField
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 import ru.landgrafhomyak.utility.reference_counter.CloseableReferenceCounter_Debug as moved_CloseableReferenceCounter_Debug
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
@Suppress("DEPRECATION_ERROR")
@Deprecated(
message = "Class moved to another package",
level = DeprecationLevel.ERROR
)
@OptIn(moved_CloseableReferenceCounter_Debug.RequiresExplicitDebug::class)
@CloseableReferenceCounter_Debug.RequiresExplicitDebug @CloseableReferenceCounter_Debug.RequiresExplicitDebug
public class CloseableReferenceCounter_Debug { public class CloseableReferenceCounter_Debug {
public fun interface Observer { public fun interface Observer {
public fun observeState(instance: CloseableReferenceCounter_Debug, actions: String) public fun observeState(instance: CloseableReferenceCounter_Debug, actions: String)
} }
private class ObserverAdapter(private val old: Observer) : moved_CloseableReferenceCounter_Debug.Observer {
lateinit var wrapper: CloseableReferenceCounter_Debug
override fun observeState(instance: moved_CloseableReferenceCounter_Debug, actions: String) {
this.old.observeState(this.wrapper, actions)
}
}
@RequiresOptIn(level = RequiresOptIn.Level.WARNING) @RequiresOptIn(level = RequiresOptIn.Level.WARNING)
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
public annotation class RequiresExplicitDebug public annotation class RequiresExplicitDebug
private val _dbgName: String @PublishedApi
private val _errMessage: String @JvmField
private val _logger: Observer? internal val _moved: moved_CloseableReferenceCounter_Debug
private val _value: _AtomicLong
private val _id: Long
public constructor(dbgName: String, errMessage: String, logger: Observer? = null) { public constructor(dbgName: String, errMessage: String, logger: Observer? = null) {
_Platform.jvm_assertNotNull(dbgName, "param: dbgName") val obs = logger?.let(::ObserverAdapter)
_Platform.jvm_assertNotNull(errMessage, "param: errMessage") this._moved = moved_CloseableReferenceCounter_Debug(dbgName, errMessage, obs)
obs?.wrapper = this
this._dbgName = dbgName
this._errMessage = dbgName
this._logger = logger
this._value = _AtomicLong(0L)
@Suppress("RemoveRedundantQualifierName")
this._id = CloseableReferenceCounter_Debug._nextId.getAndUpdate(Long::inc)
}
@Suppress("NOTHING_TO_INLINE")
private inline fun _throwErrors(valueToCheck: Long) {
when {
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")
}
} }
@RequiresExplicitDebug @RequiresExplicitDebug
@JvmName("throwErrors") @JvmName("throwErrors")
public fun throwErrors() { public fun throwErrors() {
this._throwErrors(this._value.get()) this._moved.throwErrors()
} }
@JvmName("throwClosed") @JvmName("throwClosed")
public fun throwClosed() { public fun throwClosed() {
throw IllegalStateException(this._errMessage) this._moved.throwClosed()
} }
@JvmName("incref") @JvmName("incref")
public fun incref() { public fun incref() {
this._value.update { o -> this._moved.incref()
if (o < 0) {
this._throwErrors(o)
this.throwClosed()
this._throwErrors(o + 1)
}
return@update o + 1
}
this._logger?.observeState(this, "incref")
} }
@JvmName("tryIncref\$kt") @JvmName("tryIncref\$kt")
@ -76,26 +63,17 @@ public class CloseableReferenceCounter_Debug {
contract { contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE) callsInPlace(block, InvocationKind.EXACTLY_ONCE)
} }
this.incref() return this._moved.tryIncref(block)
return safeAutoClose2(onError = this::decref, action = block)
} }
@JvmName("assertNotClosed") @JvmName("assertNotClosed")
public fun assertNotClosed() { public fun assertNotClosed() {
if (this._value.get() < 0) this.throwClosed() this._moved.assertNotClosed()
} }
@JvmName("decref") @JvmName("decref")
public fun decref() { public fun decref() {
this._value.update { o -> this._moved.decref()
if (o < 0) {
this._throwErrors(o)
this.throwClosed()
this._throwErrors(o - 1)
}
return@update o - 1
}
this._logger?.observeState(this, "decref")
} }
@JvmName("tryDecref\$kt") @JvmName("tryDecref\$kt")
@ -103,59 +81,34 @@ public class CloseableReferenceCounter_Debug {
contract { contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE) callsInPlace(block, InvocationKind.EXACTLY_ONCE)
} }
this.assertNotClosed() return this._moved.tryDecref(block)
return safeAutoClose2(onSuccess = this::decref, action = block)
} }
@get:JvmName("isClosed") @get:JvmName("isClosed")
public val isClosed: Boolean public val isClosed: Boolean
get() { get() = this._moved.isClosed
val state = this._value.get()
this._throwErrors(state)
return state < 0;
}
@JvmName("close") @JvmName("close")
public fun close(errExistRefs: String) { public fun close(errExistRefs: String) {
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") this._moved.close(errExistRefs)
val state = this._value.compareAndExchange(0, _Misc.CLOSED_STATE_VALUE)
this._throwErrors(state)
when {
state > 0 -> throw IllegalStateException(errExistRefs)
state < 0 -> this.throwClosed()
}
this._logger?.observeState(this, "closed")
} }
@JvmName("withRef\$kt") @JvmName("withRef\$kt")
public inline fun <R> withRef(protected: () -> R): R { public inline fun <R> withRef(protected: () -> R): R {
this.incref() contract {
return safeAutoClose1(finally = this::decref, action = protected) callsInPlace(protected, InvocationKind.EXACTLY_ONCE)
}
return this._moved.withRef(protected)
} }
override fun toString(): String { override fun toString(): String {
val refcntCached = this._value.get() val orig = this._moved.toString()
val stateRepr: String return orig.substring(0, orig.length - 1) + " !deprecated class used!>"
@Suppress("LiftReturnOrAssignment")
when {
refcntCached >= 0 -> stateRepr = refcntCached.toString()
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}]>"
}
public companion object {
private val _nextId = _AtomicLong(0L)
} }
public object ObserveToStdout : Observer { public object ObserveToStdout : Observer {
override fun observeState(instance: CloseableReferenceCounter_Debug, actions: String) { override fun observeState(instance: CloseableReferenceCounter_Debug, actions: String) {
_Platform.jvm_assertNotNull(instance, "param: instance") moved_CloseableReferenceCounter_Debug.ObserveToStdout.observeState(instance._moved, actions)
_Platform.jvm_assertNotNull(actions, "param: actions")
print("${instance} ${actions}\n")
} }
} }
} }

View File

@ -5,31 +5,36 @@ package ru.landrafhomyak.utility.reference_counter
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.jvm.JvmField
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 import ru.landgrafhomyak.utility.reference_counter._Platform
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2 import ru.landgrafhomyak.utility.reference_counter.MayBeClosedReferenceCounter as moved_MayBeClosedReferenceCounter
@Deprecated(
message = "Class moved to another package",
/*replaceWith = ReplaceWith(
imports = ["ru.landgrafhomyak.utility.reference_counter.MayBeClosedReferenceCounter"],
expression = "MayBeClosedReferenceCounter"
),*/
level = DeprecationLevel.ERROR
)
public sealed class MayBeClosedReferenceCounter { public sealed class MayBeClosedReferenceCounter {
private val _value: _AtomicLong @PublishedApi
private val _errMessageClosed: String @JvmField
internal val _moved: moved_MayBeClosedReferenceCounter
protected constructor(errMessageClosed: String) { protected constructor(moved: moved_MayBeClosedReferenceCounter) {
_Platform.jvm_assertNotNull(errMessageClosed, "param: errMessageClosed") this._moved = moved
this._errMessageClosed = errMessageClosed
this._value = _AtomicLong(0L)
} }
@JvmName("throwClosed") @JvmName("throwClosed")
public fun throwClosed() { public fun throwClosed() {
throw IllegalStateException(this._errMessageClosed) this._moved.throwClosed()
} }
@JvmName("incref") @JvmName("incref")
public fun incref() { public fun incref() {
this._value.update { o -> this._moved.incref()
if (o < 0) this.throwClosed()
return@update o + 1
}
} }
@JvmName("tryIncref\$kt") @JvmName("tryIncref\$kt")
@ -37,18 +42,17 @@ public sealed class MayBeClosedReferenceCounter {
contract { contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE) callsInPlace(block, InvocationKind.EXACTLY_ONCE)
} }
this.incref() return this._moved.tryIncref(block)
return safeAutoClose2(onError = this::decref, action = block)
} }
@JvmName("assertNotClosed") @JvmName("assertNotClosed")
public fun assertNotClosed() { public fun assertNotClosed() {
if (this._value.get() < 0) this.throwClosed() this._moved.assertNotClosed()
} }
@JvmName("decref") @JvmName("decref")
public fun decref() { public fun decref() {
this._value.update(Long::dec) this._moved.decref()
} }
@JvmName("tryDecref\$kt") @JvmName("tryDecref\$kt")
@ -56,43 +60,27 @@ public sealed class MayBeClosedReferenceCounter {
contract { contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE) callsInPlace(block, InvocationKind.EXACTLY_ONCE)
} }
this.assertNotClosed() return this._moved.tryDecref(block)
return safeAutoClose2(onSuccess = this::decref, action = block)
} }
@get:JvmName("isClosed") @get:JvmName("isClosed")
public val isClosed: Boolean get() = this._value.get() < 0 public val isClosed: Boolean get() =
this._moved.isClosed
@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") @JvmName("withRef\$kt")
public inline fun <R> withRef(protected: () -> R): R { public inline fun <R> withRef(protected: () -> R): R {
contract { contract {
callsInPlace(protected, InvocationKind.EXACTLY_ONCE) callsInPlace(protected, InvocationKind.EXACTLY_ONCE)
} }
this.incref() return this._moved.withRef(protected)
return safeAutoClose1(finally = this::decref, action = protected)
} }
override fun toString(): String { override fun toString(): String {
val refcntCached = this._value.get() val orig = this._moved.toString()
@Suppress("LiftReturnOrAssignment") return orig.substring(0, orig.length - 1) + " !deprecated class used!>"
if (refcntCached < 0)
return "<ref counter [closed]>"
else
return "<ref counter [${refcntCached}]>"
} }
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND") @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND", "DEPRECATION_ERROR")
@JvmName("child") @JvmName("child")
public fun <R> child(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { public fun <R> child(errMessageClosed: String, errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R {
contract { contract {
@ -103,29 +91,18 @@ public sealed class MayBeClosedReferenceCounter {
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs") _Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
_Platform.jvm_assertNotNull(scope, "param: scope") _Platform.jvm_assertNotNull(scope, "param: scope")
this.withRef { return this._moved.child(errMessageClosed, errExistRefs, WrapperReferenceCounter.wrapperLambda(scope))
return CloseableReferenceCounter.autoClosed(
errMessageClosed = errMessageClosed,
errExistRefs = errExistRefs,
scope = scope
)
}
} }
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND") @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND", "DEPRECATION_ERROR")
@JvmName("child_inheritErrMessage") @JvmName("child_inheritErrMessage")
public fun <R> child_inheritErrMessage(errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R { public fun <R> child_inheritErrMessage(errExistRefs: String, scope: (MayBeClosedReferenceCounter) -> R): R {
contract { contract {
callsInPlace(scope, InvocationKind.EXACTLY_ONCE) callsInPlace(scope, InvocationKind.EXACTLY_ONCE)
} }
_Platform.jvm_assertNotNull(errExistRefs, "param: errExistRefs")
_Platform.jvm_assertNotNull(scope, "param: scope") _Platform.jvm_assertNotNull(scope, "param: scope")
return this.child( return this._moved.child_inheritErrMessage(errExistRefs, WrapperReferenceCounter.wrapperLambda(scope))
errMessageClosed = this._errMessageClosed,
errExistRefs = errExistRefs,
scope = scope
)
} }
} }

View File

@ -0,0 +1,20 @@
package ru.landrafhomyak.utility.reference_counter
import kotlin.jvm.JvmStatic
import ru.landgrafhomyak.utility.reference_counter.MayBeClosedReferenceCounter as moved_MayBeClosedReferenceCounter
@Suppress("DEPRECATION_ERROR")
@Deprecated(
message = "Utility class for deprecated refcounters",
level = DeprecationLevel.ERROR
)
internal class WrapperReferenceCounter : MayBeClosedReferenceCounter {
constructor(refcnt: moved_MayBeClosedReferenceCounter) : super(refcnt)
companion object {
@JvmStatic
fun <R> wrapperLambda(old: (MayBeClosedReferenceCounter) -> R): (moved_MayBeClosedReferenceCounter) -> R {
return w@{ moved -> return@w old(WrapperReferenceCounter(moved)) }
}
}
}

View File

@ -1,4 +1,4 @@
package ru.landrafhomyak.utility.reference_counter package ru.landgrafhomyak.utility.reference_counter
import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicLong

View File

@ -1,4 +1,4 @@
package ru.landrafhomyak.utility.reference_counter package ru.landgrafhomyak.utility.reference_counter
import java.util.Objects import java.util.Objects
import kotlin.contracts.contract import kotlin.contracts.contract

View File

@ -1,11 +1,11 @@
package ru.landrafhomyak.utility.reference_counter.tests package ru.landgrafhomyak.utility.reference_counter.tests
import java.lang.AssertionError import java.lang.AssertionError
import org.testng.annotations.Test import org.testng.annotations.Test
import org.testng.asserts.Assertion import org.testng.asserts.Assertion
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1 import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
import ru.landrafhomyak.utility.reference_counter.CloseableReferenceCounter import ru.landgrafhomyak.utility.reference_counter.CloseableReferenceCounter
import ru.landrafhomyak.utility.reference_counter.CloseableReferenceCounter_Debug import ru.landgrafhomyak.utility.reference_counter.CloseableReferenceCounter_Debug
@Test @Test
class KotlinStdlibDependencyTest { class KotlinStdlibDependencyTest {

View File

@ -1,4 +1,4 @@
package ru.landrafhomyak.utility.reference_counter package ru.landgrafhomyak.utility.reference_counter
import kotlinx.atomicfu.AtomicLong import kotlinx.atomicfu.AtomicLong
import kotlinx.atomicfu.atomic import kotlinx.atomicfu.atomic

View File

@ -1,4 +1,4 @@
package ru.landrafhomyak.utility.reference_counter package ru.landgrafhomyak.utility.reference_counter
@PublishedApi @PublishedApi