@file:OptIn(ExperimentalContracts::class) 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 = newAtomicLong(0L) public constructor() public fun getCurrentUsagesCount(): Long = this._value.get() public open override fun throwClosed(): Nothing { throw IllegalStateException("Object is closed") } public open override fun throwInUse(): Nothing { throw IllegalStateException("Failed close object because it is in use") } public final override val isClosed: Boolean get() = this._value.get() < 0 public final override fun assertNotClosed() { if (this._value.get() < 0) this.throwClosed() } @ManualStateManipulation public final override fun startUsage() { this._value.update { o -> if (o < 0) this.throwClosed() return@update o + 1 } } @ManualStateManipulation public final override fun finishUsage() { this._value.update(Long::dec) } @ManualStateManipulation public final override fun close() { val state = this._value.compareAndExchange(0, Misc.CLOSED_STATE_VALUE) when { state > 0 -> this.throwInUse() state < 0 -> this.throwClosed() } } override fun toString(): String { val cached = this._value.get() @Suppress("LiftReturnOrAssignment") if (cached < 0) return "" else return "" } }