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
|
||||
get() = this._state.isInUse
|
||||
|
||||
@ManualStateManipulation
|
||||
override fun finishUsage(close: Boolean) {
|
||||
this._state.finishUsage(close)
|
||||
}
|
||||
|
||||
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 val isInUse: Boolean
|
||||
|
||||
@ManualStateManipulation
|
||||
public fun finishUsage(close: Boolean)
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@ public class CloseableStateCloseableWrapper(
|
||||
) : CloseableState.ExternallySynchronized {
|
||||
|
||||
override val isInUse: Boolean by this._self::isInUse
|
||||
|
||||
override val isClosed: Boolean by this._self::isInUse
|
||||
|
||||
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
|
||||
override fun close() {
|
||||
this._self.close()
|
||||
|
||||
@ -21,6 +21,9 @@ public expect open class ErrorOnConcurrentAccessState : CloseableState.Externall
|
||||
@ManualStateManipulation
|
||||
public final override fun finishUsage()
|
||||
|
||||
@ManualStateManipulation
|
||||
public final override fun finishUsage(close: Boolean)
|
||||
|
||||
@ManualStateManipulation
|
||||
public final override fun close()
|
||||
|
||||
|
||||
@ -7,23 +7,6 @@ import kotlin.contracts.contract
|
||||
import kotlin.jvm.JvmName
|
||||
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)
|
||||
public inline fun <R> CloseableState.childAC(
|
||||
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
|
||||
|
||||
@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 {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
@ -38,3 +54,42 @@ public inline fun <R> CloseableState.tryFinishUsage(block: () -> R): R {
|
||||
this.assertNotClosed()
|
||||
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
|
||||
public final void finishUsage() {
|
||||
switch (this._currentState.compareAndExchange(State.IN_USE, State.OPEN)) {
|
||||
private void _finishUsage(State nextState) {
|
||||
switch (this._currentState.compareAndExchange(State.IN_USE, nextState)) {
|
||||
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:
|
||||
this.throwClosed();
|
||||
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
|
||||
public final void close() {
|
||||
switch (this._currentState.compareAndExchange(State.OPEN, State.CLOSED)) {
|
||||
|
||||
@ -43,14 +43,22 @@ public actual open class ErrorOnConcurrentAccessState : CloseableState.Externall
|
||||
}
|
||||
|
||||
@ManualStateManipulation
|
||||
public actual final override fun finishUsage() {
|
||||
when (this._state.compareAndExchange(State.IN_USE, State.OPEN)) {
|
||||
State.OPEN -> throw IllegalStateException("Can't finish usage because not it not started")
|
||||
private fun _finishUsage(nextState: State) {
|
||||
when (this._state.compareAndExchange(State.IN_USE, nextState)) {
|
||||
State.OPEN -> throw IllegalStateException("Can't finish usage because it isn't started")
|
||||
State.IN_USE -> {}
|
||||
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
|
||||
public actual final override fun close() {
|
||||
when (this._state.compareAndExchange(State.OPEN, State.CLOSED)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user