https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
u

ursus

02/20/2023, 12:19 AM
I notice
suspend
functions get translated to
async throws
automatically, which is neet This however doesn't support cancellation, i.e. when swift
Task
gets cancelled, the source kotlin coroutine keeps on going (In my local testing) So, why is this. Is
async
function some sort of sideffect of objc, rather than a deliberate kotlin native decision? Can I somehow influence the
suspend -> async
adapter?
e

ephemient

02/20/2023, 12:26 AM
https://youtrack.jetbrains.com/issue/KT-47042
Cancellation, dispatchers, coroutine context, task locals etc. are not propagated between Kotlin and Swift, they are discarded at the boundary between Kotlin and Swift.
I think this is inevitable for now, because this is building on the Swift's automatic Objective-C completion handler to async translation
u

ursus

02/20/2023, 12:29 AM
so it just a sugar for the completion handler api?
u

ursus

02/20/2023, 12:30 AM
okay so this necessarily doesn't have anything to do with kmm/kn
e

ephemient

02/20/2023, 12:31 AM
this could be addressed if K/N generated Swift bindings instead of Objective-C. but that's still a ways off. https://youtrack.jetbrains.com/issue/KT-49131
u

ursus

02/20/2023, 12:34 AM
hm, how would that even work? I'd need a CoroutineScope to launch the suspend fun in exposed to Swift, no?
e

ephemient

02/20/2023, 12:43 AM
I haven't seen any designs around it
but Swift has its own (optional) structured concurrency that could be used, perhaps by wrapping with https://developer.apple.com/documentation/swift/withunsafecurrenttask(body:)
u

ursus

02/20/2023, 12:44 AM
okay so to have cancellation, the only way is to have some wrapper in kotlin which will own the coroutine scope, launch the function in that scope, and provide callback api + cancellation handle, to swift
where I'd wrap to async/await with their coroutine builder thingy
e

ephemient

02/20/2023, 12:45 AM
or some wrapper in Swift that turns its Task/TaskGroup into a Kotlin CoroutineScope, and then executes the Kotlin suspend fun with it
it'll probably have to be optional though, since there's uses of
suspend fun
that aren't kotlinx.coroutines
u

ursus

02/20/2023, 12:47 AM
I don't follow..how? is that possible with the current library?
I thought all notions of
suspend
were stripped at the boundary
e

ephemient

02/20/2023, 12:48 AM
in principle it's possible. none of the code to do it exists afaik
h

Howie Nguyen

02/20/2023, 12:48 AM
is this for trying to call a suspend function in shared folder from a aync function in Swift?
Because I am also having this problem
e

ephemient

02/20/2023, 12:48 AM
no, you have a different problem
u

ursus

02/20/2023, 12:48 AM
I see, so possibly in future
wondering about some generic thing, but that would require a suspending lambda, .. so only concrete wrappers .. i.e. codegen to the rescue?
but the adapter will live in kotlin, so its fine .. lmao the rubberducking, sorry 😄
Copy code
class SuspendAdapter<T> {
	private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())

	fun adapt(action: suspend () -> R, onNext: () -> R) : CancellationHandle {
		val job = scope.launch {
			val result = action()
			onNext(result)
		}
		return CancellationHandle(job)
	}
}
nevermind you'd need a concrete FooAdapter class anyways to wrap Foo api .. so yea, codegen to generate them
thanks!
e

ephemient

02/20/2023, 3:45 AM
hmm, seems my previous proposal sorta exists in some form (although it uses one common scope instead of creating one per swift operation as I'd have chosen). https://github.com/rickclephas/KMP-NativeCoroutines/blob/master/KMPNativeCoroutinesAsync/AsyncFunction.swift
149 Views