Bindings to implement posix thread

This commit is contained in:
Andrew Golovashevich 2025-03-19 01:02:05 +03:00
parent c1f96f4915
commit 2b5eed2abe
4 changed files with 104 additions and 24 deletions

View File

@ -0,0 +1,35 @@
package ru.landgrafhomyak.bgtu.networks0.low_level.multithreading
import kotlinx.cinterop.CFunction
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.CPointerVarOf
import kotlinx.cinterop.CValuesRef
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.nativeHeap
import kotlinx.cinterop.alloc
import kotlinx.cinterop.free
import kotlinx.cinterop.pointed
import kotlinx.cinterop.ptr
import kotlinx.cinterop.value
import platform.posix.pthread_tVar
import platform.posix.pthread_create
import platform.posix.pthread_join
@OptIn(ExperimentalForeignApi::class)
internal actual class _PthreadsThreadBindings private constructor(private val _ptr: CPointer<pthread_tVar>) {
actual constructor() : this(nativeHeap.alloc<pthread_tVar>().ptr)
actual fun create(
attr: CValuesRef<platform.posix.pthread_attr_t>?,
routine: CPointer<CFunction<(CPointer<*>?) -> CPointer<*>?>>?,
arg: CValuesRef<*>?
): Int = pthread_create(this._ptr, attr, routine, arg)
actual fun join(
routineReturn: CValuesRef<CPointerVarOf<CPointer<*>>>?
): Int = pthread_join(this._ptr.pointed.value, routineReturn)
actual fun free() {
nativeHeap.free(this._ptr)
}
}

View File

@ -0,0 +1,36 @@
package ru.landgrafhomyak.bgtu.networks0.low_level.multithreading
import kotlinx.cinterop.CFunction
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.CPointerVarOf
import kotlinx.cinterop.CValuesRef
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.nativeHeap
import kotlinx.cinterop.alloc
import kotlinx.cinterop.free
import kotlinx.cinterop.pointed
import kotlinx.cinterop.ptr
import kotlinx.cinterop.value
import platform.posix.pthread_attr_t
import platform.posix.pthread_tVar
import platform.posix.pthread_create
import platform.posix.pthread_join
@OptIn(ExperimentalForeignApi::class)
internal actual class _PthreadsThreadBindings private constructor(private val _ptr: CPointer<pthread_tVar>) {
actual constructor() : this(nativeHeap.alloc<pthread_tVar>().ptr)
actual fun create(
attr: CValuesRef<pthread_attr_t>?,
routine: CPointer<CFunction<(CPointer<*>?) -> CPointer<*>?>>?,
arg: CValuesRef<*>?
): Int = pthread_create(this._ptr, attr, routine, arg)
actual fun join(
routineReturn: CValuesRef<CPointerVarOf<CPointer<*>>>?
): Int = pthread_join(this._ptr.pointed.value, routineReturn)
actual fun free() {
nativeHeap.free(this._ptr)
}
}

View File

@ -6,17 +6,8 @@ import kotlinx.atomicfu.update
import kotlinx.cinterop.CPointer import kotlinx.cinterop.CPointer
import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.StableRef import kotlinx.cinterop.StableRef
import kotlinx.cinterop.nativeHeap
import kotlinx.cinterop.alloc
import kotlinx.cinterop.asStableRef import kotlinx.cinterop.asStableRef
import kotlinx.cinterop.free
import kotlinx.cinterop.pointed
import kotlinx.cinterop.ptr
import kotlinx.cinterop.staticCFunction import kotlinx.cinterop.staticCFunction
import kotlinx.cinterop.value
import platform.posix.pthread_create
import platform.posix.pthread_join
import platform.posix.pthread_tVar
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.PosixUtilities
@OptIn(ExperimentalForeignApi::class) @OptIn(ExperimentalForeignApi::class)
@ -36,7 +27,7 @@ actual class Thread : AutoCloseable {
var exitedWithError: Throwable? = null var exitedWithError: Throwable? = null
} }
private val _threadHandler: CPointer<pthread_tVar> private val _threadBindings: _PthreadsThreadBindings
private val _bootstrapArgRef: StableRef<ThreadBootstrapContext> private val _bootstrapArgRef: StableRef<ThreadBootstrapContext>
private val _state: AtomicRef<State> private val _state: AtomicRef<State>
@ -44,10 +35,9 @@ actual class Thread : AutoCloseable {
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(onAbort = this._bootstrapArgRef::dispose) {
this._threadHandler = nativeHeap.alloc<pthread_tVar>().ptr this._threadBindings = _PthreadsThreadBindings()
_safeAutoClose2(onAbort = { nativeHeap.free(this._threadHandler) }) { _safeAutoClose2(onAbort = this._threadBindings::free) {
var err = pthread_create( var err = this._threadBindings.create(
this._threadHandler,
null, null,
staticCFunction(Thread::_threadBootstrap), staticCFunction(Thread::_threadBootstrap),
this._bootstrapArgRef.asCPointer() this._bootstrapArgRef.asCPointer()
@ -59,7 +49,6 @@ actual class Thread : AutoCloseable {
} }
actual fun start() { actual fun start() {
when (this._state.compareAndExchange(State.PENDING, State.STARTING)) { when (this._state.compareAndExchange(State.PENDING, State.STARTING)) {
State.CLOSED -> throw IllegalStateException("Pthreads thread is destroyed") State.CLOSED -> throw IllegalStateException("Pthreads thread is destroyed")
@ -78,7 +67,7 @@ actual class Thread : AutoCloseable {
State.FINISHED -> return this._bootstrapArgRef.get().exitedWithError State.FINISHED -> return this._bootstrapArgRef.get().exitedWithError
State.STARTING, State.RUNNING, State.PENDING -> {} State.STARTING, State.RUNNING, State.PENDING -> {}
} }
var err = pthread_join(this._threadHandler.pointed.value, 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") }
return this._bootstrapArgRef.get().exitedWithError return this._bootstrapArgRef.get().exitedWithError
@ -96,23 +85,18 @@ actual class Thread : AutoCloseable {
_safeAutoClose1( _safeAutoClose1(
action = { action = {
var err = pthread_join(this._threadHandler.pointed.value, 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") }
}, },
finally = { finally = {
_safeAutoClose1( _safeAutoClose1(
action = { nativeHeap.free(this._threadHandler) }, action = { this._threadBindings.free() },
finally = {
_safeAutoClose1(
action = { nativeHeap.free(this._threadHandler) },
finally = { this._bootstrapArgRef.dispose() } finally = { this._bootstrapArgRef.dispose() }
) )
} }
) )
} }
)
}
companion object { companion object {
private fun _threadBootstrap(arg: CPointer<*>?): CPointer<*>? { private fun _threadBootstrap(arg: CPointer<*>?): CPointer<*>? {

View File

@ -0,0 +1,25 @@
package ru.landgrafhomyak.bgtu.networks0.low_level.multithreading
import kotlinx.cinterop.CFunction
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.CPointerVarOf
import kotlinx.cinterop.CValuesRef
import kotlinx.cinterop.ExperimentalForeignApi
import platform.posix.pthread_attr_t
@OptIn(ExperimentalForeignApi::class)
internal expect class _PthreadsThreadBindings {
constructor()
fun create(
attr: CValuesRef<pthread_attr_t>?,
routine: CPointer<CFunction<(CPointer<*>?) -> CPointer<*>?>>?,
arg: CValuesRef<*>?
): Int
fun join(
routineReturn: CValuesRef<CPointerVarOf<CPointer<*>>>?
): Int
fun free()
}