Close-on-exit feature
This commit is contained in:
parent
7131a38bd4
commit
96931fda41
@ -59,8 +59,20 @@ public sealed class ChildCloseableState<T : CloseableState> : CloseableState {
|
|||||||
override val isInUse: Boolean
|
override val isInUse: Boolean
|
||||||
get() = this._state.isInUse
|
get() = this._state.isInUse
|
||||||
|
|
||||||
|
@ManualStateManipulation
|
||||||
|
override fun finishUsage(close: Boolean) {
|
||||||
|
this._state.finishUsage(close)
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
TODO("Not yet implemented")
|
when {
|
||||||
|
this._state is OwnedErrorOnConcurrentAccessState || this._state::class === ErrorOnConcurrentAccessState::class -> {
|
||||||
|
val base = this._state.toString()
|
||||||
|
return base.substring(0, base.length - 1) + " (child of ${this._parent})>"
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> return "<child closeable state ${this._state} (parent if ${this._parent})>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -20,5 +20,8 @@ public interface CloseableState {
|
|||||||
|
|
||||||
public interface ExternallySynchronized : CloseableState {
|
public interface ExternallySynchronized : CloseableState {
|
||||||
public val isInUse: Boolean
|
public val isInUse: Boolean
|
||||||
|
|
||||||
|
@ManualStateManipulation
|
||||||
|
public fun finishUsage(close: Boolean)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6,6 +6,7 @@ public class CloseableStateCloseableWrapper(
|
|||||||
) : CloseableState.ExternallySynchronized {
|
) : CloseableState.ExternallySynchronized {
|
||||||
|
|
||||||
override val isInUse: Boolean by this._self::isInUse
|
override val isInUse: Boolean by this._self::isInUse
|
||||||
|
|
||||||
override val isClosed: Boolean by this._self::isInUse
|
override val isClosed: Boolean by this._self::isInUse
|
||||||
|
|
||||||
override fun assertNotClosed(): Unit =
|
override fun assertNotClosed(): Unit =
|
||||||
@ -25,6 +26,13 @@ public class CloseableStateCloseableWrapper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManualStateManipulation
|
||||||
|
override fun finishUsage(close: Boolean) {
|
||||||
|
this._self.tryFinishUsageThenClose(close) {
|
||||||
|
this._parent.finishUsage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ManualStateManipulation
|
@ManualStateManipulation
|
||||||
override fun close() {
|
override fun close() {
|
||||||
this._self.close()
|
this._self.close()
|
||||||
|
|||||||
@ -21,6 +21,9 @@ public expect open class ErrorOnConcurrentAccessState : CloseableState.Externall
|
|||||||
@ManualStateManipulation
|
@ManualStateManipulation
|
||||||
public final override fun finishUsage()
|
public final override fun finishUsage()
|
||||||
|
|
||||||
|
@ManualStateManipulation
|
||||||
|
public final override fun finishUsage(close: Boolean)
|
||||||
|
|
||||||
@ManualStateManipulation
|
@ManualStateManipulation
|
||||||
public final override fun close()
|
public final override fun close()
|
||||||
|
|
||||||
|
|||||||
@ -7,23 +7,6 @@ import kotlin.contracts.contract
|
|||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ManualStateManipulation::class)
|
|
||||||
public inline fun <S : CloseableState, R> autoClosed(
|
|
||||||
constructor: () -> S,
|
|
||||||
scope: (S) -> R,
|
|
||||||
): R {
|
|
||||||
contract {
|
|
||||||
callsInPlace(constructor, InvocationKind.EXACTLY_ONCE)
|
|
||||||
callsInPlace(scope, InvocationKind.EXACTLY_ONCE)
|
|
||||||
}
|
|
||||||
val state = constructor()
|
|
||||||
return safeAutoClose1(
|
|
||||||
action = { scope(state) },
|
|
||||||
finally = state::close
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ManualStateManipulation::class)
|
@OptIn(ManualStateManipulation::class)
|
||||||
public inline fun <R> CloseableState.childAC(
|
public inline fun <R> CloseableState.childAC(
|
||||||
constructor: () -> CloseableState.AllowsConcurrency = ::UsagesCounter,
|
constructor: () -> CloseableState.AllowsConcurrency = ::UsagesCounter,
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
package ru.landgrafhomyak.utility.closeable_state_1.internal
|
|
||||||
|
|
||||||
import kotlin.jvm.JvmStatic
|
|
||||||
|
|
||||||
internal object Misc {
|
|
||||||
@JvmStatic
|
|
||||||
internal inline fun <T> _compareAndExchange(get: () -> T, cas: (T, T) -> Boolean, expected: T, newValue: T): T {
|
|
||||||
while (true) {
|
|
||||||
val old = get()
|
|
||||||
if (old != expected) return old
|
|
||||||
if (cas(old, newValue)) return old
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
internal inline fun <T> _getAndUpdate(get: () -> T, cas: (T, T) -> Boolean, operator: (T) -> T): T {
|
|
||||||
while (true) {
|
|
||||||
val cur = get()
|
|
||||||
val upd = operator(cur)
|
|
||||||
if (cas(cur, upd)) return cur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal const val CLOSED_STATE_VALUE = -0x4000_0000_0000_0000L
|
|
||||||
}
|
|
||||||
@ -9,7 +9,23 @@ import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
|||||||
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
|
|
||||||
@OptIn(ManualStateManipulation::class)
|
@OptIn(ManualStateManipulation::class)
|
||||||
@JvmName("use\$kt")
|
public inline fun <S : CloseableState, R> autoClosed(
|
||||||
|
constructor: () -> S,
|
||||||
|
scope: (S) -> R,
|
||||||
|
): R {
|
||||||
|
contract {
|
||||||
|
callsInPlace(constructor, InvocationKind.EXACTLY_ONCE)
|
||||||
|
callsInPlace(scope, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
val state = constructor()
|
||||||
|
return safeAutoClose1(
|
||||||
|
action = { scope(state) },
|
||||||
|
finally = state::close
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ManualStateManipulation::class)
|
||||||
|
@JvmName("withUse\$kt")
|
||||||
public inline fun <R> CloseableState.withUse(block: () -> R): R {
|
public inline fun <R> CloseableState.withUse(block: () -> R): R {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
@ -37,4 +53,43 @@ public inline fun <R> CloseableState.tryFinishUsage(block: () -> R): R {
|
|||||||
}
|
}
|
||||||
this.assertNotClosed()
|
this.assertNotClosed()
|
||||||
return safeAutoClose2(action = block, onSuccess = this::finishUsage)
|
return safeAutoClose2(action = block, onSuccess = this::finishUsage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ManualStateManipulation::class)
|
||||||
|
@JvmName("withUseThenClose\$kt")
|
||||||
|
public inline fun CloseableState.ExternallySynchronized.withUseThenClose(block: () -> Boolean) {
|
||||||
|
contract {
|
||||||
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
this.startUsage()
|
||||||
|
var needClose = false
|
||||||
|
return safeAutoClose1(
|
||||||
|
action = { needClose = block() },
|
||||||
|
finally = { this.finishUsage(needClose) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ManualStateManipulation
|
||||||
|
@JvmName("tryFinishUsageThenClose\$kt")
|
||||||
|
public inline fun <R> CloseableState.ExternallySynchronized.tryFinishUsageThenClose(close: Boolean, block: () -> R): R {
|
||||||
|
contract {
|
||||||
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
this.assertNotClosed()
|
||||||
|
return safeAutoClose2(action = block, onSuccess = { this.finishUsage(close) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManualStateManipulation
|
||||||
|
@JvmName("tryFinishUsageThenClose\$kt")
|
||||||
|
public inline fun CloseableState.ExternallySynchronized.tryFinishUsageThenClose(block: () -> Boolean) {
|
||||||
|
contract {
|
||||||
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
this.assertNotClosed()
|
||||||
|
var needClose = false
|
||||||
|
return safeAutoClose2(
|
||||||
|
action = { needClose = block() },
|
||||||
|
onSuccess = { this.finishUsage(needClose) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -44,17 +44,27 @@ public /* open */ class jErrorOnConcurrentAccessState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void _finishUsage(State nextState) {
|
||||||
public final void finishUsage() {
|
switch (this._currentState.compareAndExchange(State.IN_USE, nextState)) {
|
||||||
switch (this._currentState.compareAndExchange(State.IN_USE, State.OPEN)) {
|
|
||||||
case OPEN:
|
case OPEN:
|
||||||
throw new IllegalStateException("Can't finish usage because not it not started");
|
throw new IllegalStateException("Can't finish usage because it isn't started");
|
||||||
case CLOSED:
|
case CLOSED:
|
||||||
this.throwClosed();
|
this.throwClosed();
|
||||||
case IN_USE:
|
case IN_USE:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void finishUsage() {
|
||||||
|
this._finishUsage(State.OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishUsage(boolean close) {
|
||||||
|
this._finishUsage(close ? State.CLOSED : State.OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void close() {
|
public final void close() {
|
||||||
switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) {
|
switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) {
|
||||||
|
|||||||
@ -43,14 +43,22 @@ public actual open class ErrorOnConcurrentAccessState : CloseableState.Externall
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ManualStateManipulation
|
@ManualStateManipulation
|
||||||
public actual final override fun finishUsage() {
|
private fun _finishUsage(nextState: State) {
|
||||||
when (this._state.compareAndExchange(State.IN_USE, State.OPEN)) {
|
when (this._state.compareAndExchange(State.IN_USE, nextState)) {
|
||||||
State.OPEN -> throw IllegalStateException("Can't finish usage because not it not started")
|
State.OPEN -> throw IllegalStateException("Can't finish usage because it isn't started")
|
||||||
State.IN_USE -> {}
|
State.IN_USE -> {}
|
||||||
State.CLOSED -> this.throwClosed()
|
State.CLOSED -> this.throwClosed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ManualStateManipulation
|
||||||
|
public actual final override fun finishUsage(): Unit =
|
||||||
|
this._finishUsage(State.OPEN)
|
||||||
|
|
||||||
|
@ManualStateManipulation
|
||||||
|
public actual final override fun finishUsage(close: Boolean): Unit =
|
||||||
|
this._finishUsage(if (close) State.CLOSED else State.OPEN)
|
||||||
|
|
||||||
@ManualStateManipulation
|
@ManualStateManipulation
|
||||||
public actual final override fun close() {
|
public actual final override fun close() {
|
||||||
when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) {
|
when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user