Morten Minke
11/25/2024, 7:39 PMreadInto
method which is a suspend method (which makes sense with io operations). I want convert this FileKit specific PlatformInputStream into a generic kotlinx.io (Raw)Source to further use in my application. However, the kotlinx.io RawSource has a method, override fun readAtMostTo
, which I need to implement for this, but this method is not a suspend function.
Because this is a MPP and both FileKit and kotlinx.io are also MPP I think I should be able to make this work in common code, but I fail because the readInto method is not a suspend function but I need a coroutine context to call the readAtMostTo and wait for the result to return. In jvm I would be able to use runBlocking to call and wait for the result, but this is not possible in MPP common code. I really thought about different solutions but I cannot find a good solution for this. Does anybody have an idea?
For simplicity here is some pseudo code showing what I try to achieve:
class PlatformInputStreamSource(
private val platformInputStream: PlatformInputStream
) : RawSource {
override fun readAtMostTo(sink: Buffer, byteCount: Long): Long {
...
<< Here i need to start a coroutine context and wait for the numberOfBytesCopied
val numberOfBytesCopied = platformInputStream.readInto(buffer, byteCount, bufferSize))
...
<< This non suspend function needs to return the number of bytes copied and therefor has to wait for the result from the readInto function.
return numberOfBytesCopied.toLong()
}
}
Filipp Zhinkin
11/26/2024, 4:24 PMrunBlocking
for Web targets.
There are some hacky approaches that might work (like scheduling readInto
call via setTimeout
and then polling the status in a loop inside the readAtMostTo
implementation), but such approaches need to be considered twice before using them.
There was an attempt to provide suspendable counterparts for RawSink
and RawSource
, but it is currently on pause (mainly, because there were not so many use cases to work with).
However, there are some outcomes of the work we had done that you may find helpful.
We concluded, that the best we can do in order to bridge blocking and suspendable IO APIs is abstain from reimplementing all the blocking functions with suspend
keyword being added to declarations. Instead, only a few suspendable function responsible for filling a kotlinx.io.Buffer
could be introduced. Once they filled a buffer, all the blocking API could be used without worrying about the suspend
attribute.
See https://github.com/Kotlin/kotlinx-io/issues/163#issuecomment-1669133140.
Perhaps, that approach would make more sense for you compared to all the hacks required to emulate runBlocking
across all KMP targets.Morten Minke
12/06/2024, 3:25 PM