Extracting 'safeAutoClose*' functions family to a separate library
This commit is contained in:
parent
834d12c17b
commit
9538888b77
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
|||||||
[submodule "libs/int-serializers"]
|
[submodule "libs/int-serializers"]
|
||||||
path = libs/int-serializers
|
path = libs/int-serializers
|
||||||
url = https://git.landgrafhomyak.ru/xomrk/int-serializers.kt
|
url = https://git.landgrafhomyak.ru/xomrk/int-serializers.kt
|
||||||
|
[submodule "libs/highlevel-try-finally"]
|
||||||
|
path = libs/highlevel-try-finally
|
||||||
|
url = https://git.landgrafhomyak.ru/xomrk/highlevel-try-finally.kt
|
||||||
|
1
libs/highlevel-try-finally
Submodule
1
libs/highlevel-try-finally
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit ef1d72ca10c361d2eead443d99241a088e130174
|
@ -8,9 +8,9 @@ import kotlinx.datetime.Clock
|
|||||||
import kotlinx.datetime.Instant
|
import kotlinx.datetime.Instant
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.sockets.IcmpSocket
|
import ru.landgrafhomyak.bgtu.networks0.low_level.sockets.IcmpSocket
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.compareAndExchange
|
import ru.landgrafhomyak.bgtu.networks0.utilities.compareAndExchange
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
|
||||||
import ru.landgrafhomyak.utility.IntSerializers
|
import ru.landgrafhomyak.utility.IntSerializers
|
||||||
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
@ -24,7 +24,7 @@ class Pinger1 : AutoCloseable {
|
|||||||
|
|
||||||
|
|
||||||
internal constructor(rawSocket: IcmpSocket) {
|
internal constructor(rawSocket: IcmpSocket) {
|
||||||
safeAutoClose2(onAbort = rawSocket::close) {
|
safeAutoClose2(onError = rawSocket::close) {
|
||||||
this._state = atomic(State.READY)
|
this._state = atomic(State.READY)
|
||||||
this._rawSocket = rawSocket
|
this._rawSocket = rawSocket
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package ru.landgrafhomyak.bgtu.networks0.low_level.multithreading
|
package ru.landgrafhomyak.bgtu.networks0.low_level.multithreading
|
||||||
|
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
|
|
||||||
class CountDownLatch : AutoCloseable {
|
class CountDownLatch : AutoCloseable {
|
||||||
private val _refcnt: CloseableRefCounter
|
private val _refcnt: CloseableRefCounter
|
||||||
@ -14,7 +14,7 @@ class CountDownLatch : AutoCloseable {
|
|||||||
this._refcnt = CloseableRefCounter("Latch was destroyed")
|
this._refcnt = CloseableRefCounter("Latch was destroyed")
|
||||||
this._counter = initialCounterValue
|
this._counter = initialCounterValue
|
||||||
this._mutex = Mutex()
|
this._mutex = Mutex()
|
||||||
safeAutoClose2(onAbort = this._mutex::close) {
|
safeAutoClose2(onError = this._mutex::close) {
|
||||||
this._condition = Condition()
|
this._condition = Condition()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package ru.landgrafhomyak.bgtu.networks0.low_level.multithreading
|
|||||||
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 ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
inline fun <R> Mutex.withLock(synchronizedBlock: () -> R): R {
|
inline fun <R> Mutex.withLock(synchronizedBlock: () -> R): R {
|
||||||
|
@ -14,8 +14,8 @@ import platform.posix.pthread_cond_broadcast
|
|||||||
import platform.posix.pthread_cond_signal
|
import platform.posix.pthread_cond_signal
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
@ -26,7 +26,7 @@ actual class Condition : AutoCloseable {
|
|||||||
actual constructor() {
|
actual constructor() {
|
||||||
this._refcnt = CloseableRefCounter("Pthreads condition was destroyed")
|
this._refcnt = CloseableRefCounter("Pthreads condition was destroyed")
|
||||||
this._descriptor = nativeHeap.alloc<pthread_cond_t>().ptr
|
this._descriptor = nativeHeap.alloc<pthread_cond_t>().ptr
|
||||||
safeAutoClose2(onAbort = { nativeHeap.free(this._descriptor) }) {
|
safeAutoClose2(onError = { nativeHeap.free(this._descriptor) }) {
|
||||||
var err = pthread_cond_init(this._descriptor, null)
|
var err = pthread_cond_init(this._descriptor, null)
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
PosixUtilities.throwErrno { d -> RuntimeException("Failed to initialize pthreads condition: $d") }
|
PosixUtilities.throwErrno { d -> RuntimeException("Failed to initialize pthreads condition: $d") }
|
||||||
|
@ -13,8 +13,8 @@ import platform.posix.pthread_mutex_t
|
|||||||
import platform.posix.pthread_mutex_unlock
|
import platform.posix.pthread_mutex_unlock
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class, Mutex.RefcntAccess::class)
|
@OptIn(ExperimentalForeignApi::class, Mutex.RefcntAccess::class)
|
||||||
actual class Mutex : AutoCloseable {
|
actual class Mutex : AutoCloseable {
|
||||||
@ -28,7 +28,7 @@ actual class Mutex : AutoCloseable {
|
|||||||
actual constructor() {
|
actual constructor() {
|
||||||
this._refcnt = CloseableRefCounter("Pthreads mutex was destroyed")
|
this._refcnt = CloseableRefCounter("Pthreads mutex was destroyed")
|
||||||
this._descriptor = nativeHeap.alloc<pthread_mutex_t>().ptr
|
this._descriptor = nativeHeap.alloc<pthread_mutex_t>().ptr
|
||||||
safeAutoClose2(onAbort = { nativeHeap.free(this._descriptor) }) {
|
safeAutoClose2(onError = { nativeHeap.free(this._descriptor) }) {
|
||||||
var err = pthread_mutex_init(this._descriptor, null)
|
var err = pthread_mutex_init(this._descriptor, null)
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
PosixUtilities.throwErrno(err) { d -> RuntimeException("Failed to create pthreads mutex: $d") }
|
PosixUtilities.throwErrno(err) { d -> RuntimeException("Failed to create pthreads mutex: $d") }
|
||||||
|
@ -9,9 +9,9 @@ import kotlinx.cinterop.StableRef
|
|||||||
import kotlinx.cinterop.asStableRef
|
import kotlinx.cinterop.asStableRef
|
||||||
import kotlinx.cinterop.staticCFunction
|
import kotlinx.cinterop.staticCFunction
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2e
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2e
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.compareAndExchange
|
import ru.landgrafhomyak.bgtu.networks0.utilities.compareAndExchange
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
@ -38,9 +38,9 @@ actual class Thread : AutoCloseable {
|
|||||||
actual constructor(routine: Routine) {
|
actual constructor(routine: Routine) {
|
||||||
this._state = atomic(State.PENDING)
|
this._state = atomic(State.PENDING)
|
||||||
this._bootstrapArgRef = StableRef.create(ThreadBootstrapContext(routine))
|
this._bootstrapArgRef = StableRef.create(ThreadBootstrapContext(routine))
|
||||||
safeAutoClose2(onAbort = this._bootstrapArgRef::dispose) {
|
safeAutoClose2(onError = this._bootstrapArgRef::dispose) {
|
||||||
this._threadBindings = _PthreadsThreadBindings()
|
this._threadBindings = _PthreadsThreadBindings()
|
||||||
safeAutoClose2(onAbort = this._threadBindings::free) {
|
safeAutoClose2(onError = this._threadBindings::free) {
|
||||||
var err = this._threadBindings.create(
|
var err = this._threadBindings.create(
|
||||||
null,
|
null,
|
||||||
staticCFunction({ arg -> return@staticCFunction Thread._threadBootstrap(arg) }),
|
staticCFunction({ arg -> return@staticCFunction Thread._threadBootstrap(arg) }),
|
||||||
@ -60,7 +60,7 @@ actual class Thread : AutoCloseable {
|
|||||||
State.STARTING, State.RUNNING -> throw IllegalStateException("Pthreads thread already running")
|
State.STARTING, State.RUNNING -> throw IllegalStateException("Pthreads thread already running")
|
||||||
State.PENDING -> {}
|
State.PENDING -> {}
|
||||||
}
|
}
|
||||||
safeAutoClose2(onAbort = { this._state.value = State.PENDING }) {
|
safeAutoClose2(onError = { this._state.value = State.PENDING }) {
|
||||||
this._bootstrapArgRef.get().startSignal.decrement()
|
this._bootstrapArgRef.get().startSignal.decrement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,13 +73,13 @@ actual class Thread : AutoCloseable {
|
|||||||
}
|
}
|
||||||
var err = this._threadBindings.join(null)
|
var err = this._threadBindings.join(null)
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
PosixUtilities.throwErrno(err) { d -> RuntimeException("Failed to create pthreads thread") }
|
PosixUtilities.throwErrno(err) { d -> RuntimeException("Failed to create pthreads thread: $d") }
|
||||||
return this._bootstrapArgRef.get().exitedWithError
|
return this._bootstrapArgRef.get().exitedWithError
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
this._state.update { o ->
|
this._state.update { o ->
|
||||||
when (this._state.value) {
|
when (o) {
|
||||||
State.CLOSED -> throw IllegalStateException("Pthreads thread is destroyed")
|
State.CLOSED -> throw IllegalStateException("Pthreads thread is destroyed")
|
||||||
State.STARTING, State.RUNNING -> throw IllegalStateException("Can't destroy pthreads thread while it running")
|
State.STARTING, State.RUNNING -> throw IllegalStateException("Can't destroy pthreads thread while it running")
|
||||||
State.FINISHED, State.PENDING -> {}
|
State.FINISHED, State.PENDING -> {}
|
||||||
@ -113,7 +113,7 @@ actual class Thread : AutoCloseable {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
safeAutoClose2e(
|
safeAutoClose2e(
|
||||||
onAbort = { e ->
|
onError = { e ->
|
||||||
context.exitedWithError = e
|
context.exitedWithError = e
|
||||||
context.threadState.value = State.FINISHED
|
context.threadState.value = State.FINISHED
|
||||||
},
|
},
|
||||||
|
@ -30,8 +30,8 @@ import platform.posix.sockaddr_in6
|
|||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.multithreading.withLock
|
import ru.landgrafhomyak.bgtu.networks0.low_level.multithreading.withLock
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose1
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.multithreading.Mutex as TMutex
|
import ru.landgrafhomyak.bgtu.networks0.low_level.multithreading.Mutex as TMutex
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
@ -187,7 +187,7 @@ class EpollSocketEventLoop : SocketEventLoopScope.Closeable {
|
|||||||
this.read = null
|
this.read = null
|
||||||
this.write = null
|
this.write = null
|
||||||
this.stableRef = StableRef.create(this)
|
this.stableRef = StableRef.create(this)
|
||||||
safeAutoClose2(onAbort = this.stableRef::dispose) {
|
safeAutoClose2(onError = this.stableRef::dispose) {
|
||||||
this.sync = TMutex()
|
this.sync = TMutex()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,13 +205,13 @@ class EpollSocketEventLoop : SocketEventLoopScope.Closeable {
|
|||||||
private val __metadata: _SocketMetadata
|
private val __metadata: _SocketMetadata
|
||||||
|
|
||||||
constructor(ipv4: CValue<sockaddr_in>) : super(ipv4) {
|
constructor(ipv4: CValue<sockaddr_in>) : super(ipv4) {
|
||||||
safeAutoClose2(onAbort = { super.close() }) {
|
safeAutoClose2(onError = { super.close() }) {
|
||||||
this.__metadata = _SocketMetadata(this._socketFd)
|
this.__metadata = _SocketMetadata(this._socketFd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(ipv6: CValue<sockaddr_in6>) : super(ipv6) {
|
constructor(ipv6: CValue<sockaddr_in6>) : super(ipv6) {
|
||||||
safeAutoClose2(onAbort = { super.close() }) {
|
safeAutoClose2(onError = { super.close() }) {
|
||||||
this@EpollSocketEventLoop._socketsCount.tryIncref {
|
this@EpollSocketEventLoop._socketsCount.tryIncref {
|
||||||
this.__metadata = _SocketMetadata(this._socketFd)
|
this.__metadata = _SocketMetadata(this._socketFd)
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ import platform.posix.close as close_lowlevel
|
|||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.CUtilities
|
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.CUtilities
|
||||||
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
import ru.landgrafhomyak.bgtu.networks0.utilities.CloseableRefCounter
|
||||||
import ru.landgrafhomyak.bgtu.networks0.utilities.safeAutoClose2
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
|
|
||||||
@Suppress("CanBeVal")
|
@Suppress("CanBeVal")
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
@ -82,7 +82,7 @@ internal abstract class NonblockingIcmpSocketImpl : IcmpSocket {
|
|||||||
else
|
else
|
||||||
PosixUtilities.throwErrno { d -> RuntimeException("Failed to create ICMP socket over ${protoName}: $d") }
|
PosixUtilities.throwErrno { d -> RuntimeException("Failed to create ICMP socket over ${protoName}: $d") }
|
||||||
}
|
}
|
||||||
safeAutoClose2(onAbort = { if (0 != close_lowlevel(this._socketFd)) PosixUtilities.throwErrno { d -> RuntimeException("Failed to close ICMP socket: $d") } }) {
|
safeAutoClose2(onError = { if (0 != close_lowlevel(this._socketFd)) PosixUtilities.throwErrno { d -> RuntimeException("Failed to close ICMP socket: $d") } }) {
|
||||||
var err = memScoped {
|
var err = memScoped {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return@memScoped connect(sock, addrValue as CValue<sockaddr>, addrSize)
|
return@memScoped connect(sock, addrValue as CValue<sockaddr>, addrSize)
|
||||||
|
@ -22,6 +22,7 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(Dependencies.kotlin_atomicfu)
|
implementation(Dependencies.kotlin_atomicfu)
|
||||||
|
api("ru.landgrafhomyak.utility:highlevel-try-finally:0.4")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import kotlin.contracts.contract
|
|||||||
import kotlinx.atomicfu.AtomicLong
|
import kotlinx.atomicfu.AtomicLong
|
||||||
import kotlinx.atomicfu.atomic
|
import kotlinx.atomicfu.atomic
|
||||||
import kotlinx.atomicfu.update
|
import kotlinx.atomicfu.update
|
||||||
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
|
||||||
|
import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
|
||||||
|
|
||||||
class CloseableRefCounter(private val _errMessage: String) {
|
class CloseableRefCounter(private val _errMessage: String) {
|
||||||
private val _value: AtomicLong = atomic(0L)
|
private val _value: AtomicLong = atomic(0L)
|
||||||
@ -28,7 +30,7 @@ class CloseableRefCounter(private val _errMessage: String) {
|
|||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
}
|
}
|
||||||
this.incref()
|
this.incref()
|
||||||
return safeAutoClose2(onAbort = this::decref, action = block)
|
return safeAutoClose2(onError = this::decref, action = block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkNotClosed() {
|
fun checkNotClosed() {
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
@file:OptIn(ExperimentalContracts::class)
|
|
||||||
|
|
||||||
package ru.landgrafhomyak.bgtu.networks0.utilities
|
|
||||||
|
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
|
|
||||||
@Suppress("WRONG_INVOCATION_KIND")
|
|
||||||
inline fun <R> safeAutoClose1(
|
|
||||||
finally: () -> Unit,
|
|
||||||
action: () -> R
|
|
||||||
): R {
|
|
||||||
contract {
|
|
||||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
|
||||||
callsInPlace(finally, InvocationKind.EXACTLY_ONCE)
|
|
||||||
}
|
|
||||||
return safeAutoClose3(onAbort = finally, onSuccess = finally, onCrossReturn = finally, action = action)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("WRONG_INVOCATION_KIND")
|
|
||||||
inline fun <R> safeAutoClose2(
|
|
||||||
onAbort: () -> Unit = {},
|
|
||||||
onSuccess: () -> Unit = {},
|
|
||||||
action: () -> R
|
|
||||||
): R {
|
|
||||||
contract {
|
|
||||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
|
||||||
callsInPlace(onAbort, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(onSuccess, InvocationKind.AT_MOST_ONCE)
|
|
||||||
}
|
|
||||||
return safeAutoClose3(onAbort = onAbort, onSuccess = onSuccess, onCrossReturn = onSuccess, action = action)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("WRONG_INVOCATION_KIND")
|
|
||||||
inline fun <R> safeAutoClose2e(
|
|
||||||
onAbort: (Throwable) -> Unit = { _ -> },
|
|
||||||
onSuccess: () -> Unit = {},
|
|
||||||
action: () -> R
|
|
||||||
): R {
|
|
||||||
contract {
|
|
||||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
|
||||||
callsInPlace(onAbort, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(onSuccess, InvocationKind.AT_MOST_ONCE)
|
|
||||||
}
|
|
||||||
return safeAutoClose3e(onAbort = onAbort, onSuccess = onSuccess, onCrossReturn = onSuccess, action = action)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <R> safeAutoClose3(
|
|
||||||
onAbort: () -> Unit = {},
|
|
||||||
onSuccess: () -> Unit = {},
|
|
||||||
onCrossReturn: () -> Unit = {},
|
|
||||||
action: () -> R
|
|
||||||
): R {
|
|
||||||
contract {
|
|
||||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
|
||||||
callsInPlace(onAbort, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(onSuccess, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(onCrossReturn, InvocationKind.AT_MOST_ONCE)
|
|
||||||
}
|
|
||||||
return safeAutoClose3e(onAbort = { t -> onAbort() }, onSuccess = onSuccess, onCrossReturn = onCrossReturn, action = action)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <R> safeAutoClose3e(
|
|
||||||
onAbort: (Throwable) -> Unit = { _ -> },
|
|
||||||
onSuccess: () -> Unit = {},
|
|
||||||
onCrossReturn: () -> Unit = {},
|
|
||||||
action: () -> R
|
|
||||||
): R {
|
|
||||||
contract {
|
|
||||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
|
||||||
callsInPlace(onAbort, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(onSuccess, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(onCrossReturn, InvocationKind.AT_MOST_ONCE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val ret: R
|
|
||||||
var wasError = false
|
|
||||||
var crossReturned = true
|
|
||||||
try {
|
|
||||||
ret = action()
|
|
||||||
crossReturned = false
|
|
||||||
} catch (e1: Throwable) {
|
|
||||||
wasError = true
|
|
||||||
try {
|
|
||||||
onAbort(e1)
|
|
||||||
} catch (e2: Throwable) {
|
|
||||||
e1.addSuppressed(e2)
|
|
||||||
}
|
|
||||||
throw e1
|
|
||||||
} finally {
|
|
||||||
if (!wasError) {
|
|
||||||
if (crossReturned)
|
|
||||||
onCrossReturn()
|
|
||||||
else
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
@ -24,6 +24,7 @@ pluginManagement {
|
|||||||
|
|
||||||
|
|
||||||
includeBuild("./libs/int-serializers")
|
includeBuild("./libs/int-serializers")
|
||||||
|
includeBuild("./libs/highlevel-try-finally")
|
||||||
include(":modules:utilities")
|
include(":modules:utilities")
|
||||||
include(":modules:low-level:c-interop-utilities")
|
include(":modules:low-level:c-interop-utilities")
|
||||||
include(":modules:low-level:multithreading")
|
include(":modules:low-level:multithreading")
|
||||||
|
Loading…
Reference in New Issue
Block a user