How would I make a suspend function wrap a `dispat...
# kotlin-native
r
How would I make a suspend function wrap a
dispatch_async
call returning a result? i.e. how to bridge coroutines and multithreading as coroutines themselves can’t run outside of main thread
I wrote that, not sure if it sucks or not
Copy code
actual suspend fun <T> runAsync(task: () -> T): T {
    var result: Result<T>? = null
    @Suppress("EXPERIMENTAL_UNSIGNED_LITERALS")
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        result = try {
            Result.success(task())
        } catch (t: Throwable) {
            Result.failure(t)
        }
    }
    while (result == null) delay(10)
    return (result as Result<T>).getOrThrow()
}
Nevermind, I guess I’ll use https://github.com/Autodesk/coroutineworker
👍 1
b
Heh yeah I have a function in there for that purpose
r
Yeah I’m using that but I keep getting things like
InvalidMutabilityException: mutation attempt of frozen kotlinx.coroutines.DispatchedContinuation
Not sure what I should freeze and what I should not
I’m using this
Copy code
actual suspend fun <T> runAsync(task: CoroutineScope.() -> T): T =
    threadSafeSuspendCallback<T> { completion ->
        val job = CoroutineWorker.execute {
            val result = runCatching { task() }
            completion(result)
        }
        return@threadSafeSuspendCallback { job.cancel() }
    }
I get
Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen com.autodesk.coroutineworker.$waitAndDelayForConditionCOROUTINE$165@16207c8
b
since you're in a suspend fun already, you can just do this:
Copy code
actual suspend fun <T> runAsync(task: CoroutineScope.() -> T): T =
    CoroutineWorker.withContext {
        task()
    }
r
I think that only works in a CoroutineScope actually
@basher yes I get “No value passed for parameter jvmContext”. If I understand correctly I can pass whatever for this parameter on native, it is ignored
b
That's correct. Pass whatever you want on native
r
I guess I’ll use
EmptyCoroutineContext
🙌 1
b
Should also point out that you also have the option of just executing task without withContext since it's a suspend lambda. It depends on the use case though (not sure what task is actually doing)
r
My original problem is that I am writing so many small files in my iOS app that it freezes the UI. I first tried to basically put my writing calls in that runAsync but obviously it would have been too easy.
task
can’t just capture anything like that, that’s why I got all those errors. I now have moved to a more “actual worker” solution with
CoroutineWorker.execute
and a collection from Stately to pass data to it. What do you mean by “just executing task”? I want it to run on another thread as it’s something that could basically block the thread for some milliseconds
b
i mean just call
task()
. you're already in a
suspend
context. it depends though if you think
task
is actually going to block the current thread
withContext
is useful in cases where you'd want to do
withContext(<http://Dispiatcher.IO|Dispiatcher.IO>)
on JVM
r
It was really a function which was to be called from main thread and should run
task
on another thread. Just running
task()
can never do that
👍 1