https://kotlinlang.org logo
#coroutines
Title
# coroutines
a

altavir

01/19/2019, 9:10 AM
@Ilmir Usmanov [JB] I've looked up
runTest
and sadly, it does not solve the problem with "blocking" calls in JS (also it could be run only from test). I am still thinking if it is really necessary. My use case is that I have an interface with a regular blocking function and implementation which utilizes coroutines for parallel computations. Currently I can't do it since I can't collect parallel elements in a non-blocking way. Maybe there are better ways.
i

Ilmir Usmanov [JB]

01/21/2019, 11:17 AM
an interface with a regular blocking function
can't do it since I can't collect parallel elements in a non-blocking way.
If I understood you correctly, the code looks like
Copy code
interface A {
    fun doSomething(): Long
}

class B: A, CoroutineScope {
    override fun doSomething(): Long {
        val jobs = arrayListOf<Deferred<Long>>()
        for (i in 0..100) jobs += async {
            // some computation
            1L
        }
        var result: Long = 0
        runBlocking {
            result = jobs.awaitAll().reduce { acc, l -> acc + l }
        }
        return result
    }

    override val coroutineContext = Dispatchers.Default
}
And you want to replace
runBlocking
with something, that works on all platforms?
a

altavir

01/21/2019, 11:25 AM
In nutshell, yes. I want to use lazy evaluation an parallel capabilities from blocking code.
Another example is a
CompletableDeferred
that I can't use to immediately get result from blocking code.
v

Vsevolod Tolstopyatov [JB]

01/21/2019, 12:10 PM
runBlocking
is impossible to implement on JS due to limitations of the JS runtime itself. Not only promises and timeouts, but inability to advance current event loop is the main issue. What you can do though is the following: 1) Write your own event loop (or copy one from
kotlinx.coroutines
), optionally prohibit calls to
delay
and
promise
using some global variable 2) Launch all parallel computations from within this event loop. In order to achieve parallelism on JVM, explicitly specify dispatcher:
Copy code
suspend expect fun dispatcher()
// Jvm
actual fun dispatcher() = your jvm dispatcher
// Js
actual suspend fun dispatcher() = coroutineContext[CoroutineInterceptor]!!

// Usage
var result: Long = 0
runEventLoop {
    val jobs = arrayListOf<Deferred<Long>>()
    for (i in 0..100) jobs += async(dispatcher()) {
        // some computation
        1L
    }
    result = jobs.awaitAll().reduce { acc, l -> acc + l }
}
return result
a

altavir

01/21/2019, 12:14 PM
OK, thanks. I was thinking about something like that (your example simplifies my search). Or complete API revision to separate blocking and non-blocking variants.
It seems to be rather frequent case though. Should it be added to coroutines library?
v

Vsevolod Tolstopyatov [JB]

01/21/2019, 12:20 PM
I was writing trivial counter-examples why it is not possible to write general-purpose JS-specific
eventLoop
, but was able to find solution for each 🙂 Could you please create an issue with your specific use-case?
a

altavir

01/21/2019, 12:21 PM
OK
3 Views