Hello, I'm working on converting a callback from a C library into a suspend function. I'm considering using :
Copy code
suspend fun myFun() {
val atomicLong = AtomicReference<Long?>(null)
externalFunctionWithCallback { value ->
atomicLong.set(value)
}
while (atomicLong.get() == null) {
yield()
}
return atomicLong.get()
}
Or may be this one
Copy code
suspend fun myFun() {
val atomicLong = AtomicReference<Long?>(null)
externalFunctionWithCallback { value ->
atomicLong.set(value)
}
while (atomicLong.get() == null) {
delay(1000)
}
return atomicLong.get()
}
What do you think? The goal would be to let other coroutine run while I'm waiting something
s
Sam
10/01/2024, 1:06 PM
Did you consider using
suspendCoroutine
(or
suspendCancellableCoroutine
)?
j
Joffrey
10/01/2024, 1:06 PM
Ah, you beat me to it 😅
🫰 1
s
Sam
10/01/2024, 1:08 PM
Copy code
suspend fun myFun() = suspendCoroutine<Long> { cont ->
externalFunctionWithCallback { value ->
cont.resume(value)
}
}
☝️ 1
➕ 1
a
alexandre mommers
10/01/2024, 1:09 PM
Thanks I will check that !
j
Joffrey
10/01/2024, 1:09 PM
And if the external function somehow allows cancellation, you could use the
suspendCancellableCoroutine
variant to make it cooperate with coroutines cancellation:
Copy code
suspend fun myFun() = suspendCancellableCoroutine<Long> { cont ->
// you could also put this after the external call depending on the API to cancel
cont.invokeOnCancellation { ...cancel/stop/cleanup code here... }
externalFunctionWithCallback { value ->
cont.resume(value)
}
}
Joffrey
10/01/2024, 1:10 PM
Note that you could also use this variant if the external function does NOT support cancellation (thus without the
invokeOnCancellation
call), but if you do this, you will technically leak the non-cancelled external function call, which is probably a bad idea