I'm using pthreads from Kotlin Native, and for the...
# kotlin-native
l
I'm using pthreads from Kotlin Native, and for the most part it works fine. I just call the functions in
platform.posix
. However, I'm trying to use
pthread_cleanup_push
and it doesn't seem to exist in this package. In fact, I can't see it anywhere. Is this a bug? Should I report it?
a
I think
pthread_cleanup_push
is defined as a macro, not a function, cinterop can't generate a Kotlin Native binding for it
it's possible to manually define regular C functions that call the macros, so cinterop will generate bindings https://kotlinlang.org/docs/native-c-interop.html#macros
so, I don't think it's a bug, but I think it'd be worth creating a YouTrack issue for it.
l
Oh, I see. So one would have to create a wrapper around it. Thanks a lot.
e
POSIX.1 permits
pthread_cleanup_push()
and
pthread_cleanup_pop()
to be implemented as macros that expand to text containing '`{
' and '
}`', respectively. For this reason, the caller must ensure that calls to these functions are paired within the same function, and at the same lexical nesting level.
you cannot (portably) wrap them individually
you can safely use them within the same C function, for example a wrapper C function like
Copy code
void pthread_push_pop(void (*routine)(void *), void *arg1, void *arg2, bool execute) {
    pthread_cleanup_push(routine, arg1);
    routine(arg2);
    pthread_cleanup_pop(execute);
}
and then use it from Kotlin like
Copy code
fun invokePinnedFunPtr(arg: NativePtr) {
    interpretPointed<Pinned<() -> Unit>>(arg)()
}

fun runFinally(cleanup: () -> Unit, execute: Boolean, block: () -> Unit) {
    block.usePinned { block ->
        cleanup.usePinned { cleanup ->
            pturead_push_pop(staticCFunction(::invokePinnedFunPtr), cleanup.addressOf(0), block.addressOf(0), execute)
        }
    }
}
but really that's worse than
Copy code
fun runFinally(block: () -> Unit, cleanup: () -> Unit, execute: Boolean) {
    var doCleanup = true
    try {
        block()
        doCleanup = execute
    } finally {
        if (doCleanup) cleanup()
    }
}
since the pthread version will just break if the Kotlin functions throw exceptions
what are you trying to do?
l
I did not realise that.
What I'm actually doing is implementing thread-local variables without using the pthread key stuff.
At first I implemented it using
pthread_getspecific
, but for some reason the when a Kotlin function is called from the key destructor, I get a crash. Very strange. So I implemented it myself using a hashmap attached to the thread, but I need to clear that out when the thread exits, which is why I looked at
pthread_cleanup_push
.
e
@ThreadLocal
doesn't work for you?
probably Kotlin code doesn't expect to run in a destructed thread or something like that
l
I did look into
@ThreadLocal
a long time ago, but there was some issue with it. Perhaps I misunderstood it, because I tried again and it does seem to work.
@ephemient it worked by the way. Look how many lines of code I could remove, and now the code is more stable too: https://codeberg.org/loke/array/commit/c881ee2ee1a35952edfe716372483a82ed0a69d6
nice spin 1