Problem with CoroutineScope(Dispatchers.Main) - kotlin

im new in kotlin. Druing studying i got this kind of exception
Exception in thread "main" java.lang.RuntimeException: Exception while trying to handle coroutine exception
Suppressed: java.lang.IllegalStateException: Module with the Main dispatcher had failed to initialize. For tests Dispatchers.setMain from kotlinx-coroutines-test module can be used
That is my code
fun main(args: Array<String>) {
val scope = CoroutineScope(Dispatchers.Main)
println("1")
scope.launch { println("2") }
println("3")
}
What's wrong with that?
I changed scope declaration to
val scope = CoroutineScope(Dispatchers.Default)
and it's working, could anyone explain me why i cant use Dispatchers.Main in that case?

Dispatchers.Main is only available on each platform under certain conditions. You can check the documentation about this:
Access to this property may throw an IllegalStateException if no main dispatchers are present in the classpath.
Depending on platform and classpath, it can be mapped to different dispatchers:
On JS and Native it is equivalent to the Default dispatcher.
On JVM it is either the Android main thread dispatcher, JavaFx or Swing EDT dispatcher. It is chosen by the ServiceLoader.
In order to work with the Main dispatcher, the following artifact should be added to the project runtime dependencies:
kotlinx-coroutines-android — for Android Main thread dispatcher
kotlinx-coroutines-javafx — for JavaFx Application thread dispatcher
kotlinx-coroutines-swing — for Swing EDT dispatcher
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html
So for example, when running an app on Android this will be available as a dispatcher based on the main Looper but in a test or main function it will be absent and throw the stated exception.
Your code sample works when using Dispatchers.Default because this is always available on all platforms (hence the "default").

Related

Why can `runBlocking` be invoked without providing a CoroutineContext, if there's no default value for it?

I always check the implementation of the things I use.
Currently I'm using an injection library that doesn't support suspensable functions (Koin), so, only (even if discouraged) for bootstrapping the app, I'm using runBlocking some times.
In order to have richer logs, I'm enriching the coroutine context with some info, yet that info is lost in most context changes (launch, async, and runBlocking among others).
Specially, given the fact that non-suspend methods don't have access to a CoroutineContext, I'm super curious where does runBlocking gets it from.
You can use runBlocking like:
runBlocking {...}
Yet, when I check its implementation, it has two parameters: a CoroutineContext and the suspend block to be executed. None of those parameters have default value, so why can I call it without passing it? I really don't get it!
Additionally, the page says that the default value is EmptyCoroutineContext but the code docs say something about an event loop.
So I ask again? Why can I call it without passing a value, and what's the actual default?
By default runBlocking() starts with an empty coroutine context.
The fact that the context doesn't have a default value is indeed confusing and strange. I think (but I'm not 100% sure) this is because by ctrl+clicking on runBlocking() we go the implementation, so actual definition. But the code is compiled against the expect declaration. I didn't find an easy way to see expect declaration directly in IntelliJ, but it can be found here:
public expect fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T
As we can see, context in this declaration has a default value. Still, this is really confusing when using IntelliJ.
And regarding the mentioned event loop: yes, runBlocking() creates (or re-uses) an event loop, but I don't see how it relates to the coroutine context.
Remember that the context you pass to a coroutine builder like runBlocking or launch is not the context that will actually become available inside the coroutine, but its parent. The builder adds its own items and merges them into the context you provided.
runBlocking uses its own dispatcher, which exists only during the lifetime of the runBlocking function call. You can find this dispatcher in the coroutine context available inside the body of runBlocking, for example using this code:
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
val ctxElems = coroutineContext.fold(mutableListOf<Pair<Any, Any>>()) { list, element ->
list.also { it.add(element.key to element) }
}
for ((key, value) in ctxElems) {
println("${key::class.qualifiedName}: $value")
}
}
}
This prints
kotlinx.coroutines.CoroutineId.Key: CoroutineId(1)
kotlinx.coroutines.Job.Key: "coroutine#1":BlockingCoroutine{Active}#12843fce
kotlin.coroutines.ContinuationInterceptor.Key: BlockingEventLoop#3dd3bcd
(coroutine dispatchers belong to the broader category of continuation interceptors)
The other part of your question, why you don't have to pass in the seemingly non-default parameter, is answered elsewhere. Basically, it's an artifact of the IDE and the expected vs. actual declarations. The relevant declaration is the expected one, and actual is an implementation detail, but the IDE takes you to that one.

ClassCastException after obfuscation internal classes with suspend functions

I'm building a kotlin AAR library which I need to obfuscate before publishing. I have the following structure:
package com.example.token
interface TokenManager {
suspend fun getTokenStatus(): String
}
The above is a public interface available for the api client. The implementation is moved to an internal package:
package com.example.token.internal
internal class RestApiTokenManager: TokenManager {
override suspend fun getTokenStatus(): String {
//....
}
}
My obfuscation exception includes only the public interface package:
-keep class com.example.token.*{*;}
Unfortunately this results in a class cast exception:
java.lang.ClassCastException: e.e.a.a.l.d.e$a cannot be cast to c.a.a.e.a.a$a
In order to fix this I need to add an obfuscation exception for the implementation package, which I want to avoid.
Now the true weird problem is that the ClassCastException disappears as soon as I remove the suspend modifier.
I tried adding -keeptkotlinmetadata but I get R8: Unknown option error.
I've been stuck with this for a long time now, without a solution which won't force me to add an exception for my internal implementation classes.
This could be a bug in R8, and I have opened issue 167373399 to track this.
Please follow up there with information on the version of Android Studio / R8 you are currently using?
Please also take a look at this Medium post, which has more details on shrinking Kotlin code with R8.
The discussion continued and was concluded on the issuetracker 167373399

When to specify Dispatchers.xxx for coroutines in classes

I often create classes that have functions that contain a coroutine. It isn't always clear whether the function is being used by some component that is bound to the UI or whether it's doing background work that is more IO oriented. Here's an example:
fun myFunction() {
GlobalScope.launch {
// Do something
}
}
In this example, no Dispatcher.MAIN or Dispatchers.IO is specified. Is this the correct way to do this? Does the coroutine use the scope of whatever the calling client happens to be using? Should I only specify a dispatcher when I know definitively that I need a specific scope?
GlobalScope binds the lifecycle of the Coroutine to the lifecycle of the application itself.
Which means Coroutine started from this scope would continue to live until one of two things occur
Coroutine completes its job.
The Application itself is killed.
Using async or launch on the instance of GlobalScope is highly discouraged.
No Dispatcher.MAIN or Dispatchers.IO is specified. Is this the correct way to do this?
Yea, why not? If the work inside coroutine is not related to either UI or IO go for it.
Should I only specify a dispatcher when I know definitively that I
need a specific scope?
To answer this, let's first see the definition of launch from docs,
fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit ): Job (source)
The Dispatcher which we are talking about is a kind of CoroutineContext. As you can see in the definition if the CoroutineContext is not mentioned(which means we have not mentioned the Dispatcher too) it is by default set to EmptyCoroutineContext which internally uses Dispatchers.Default and this is what docs say about it,
The default CoroutineDispatcher that is used by all standard builders
like launch, async, etc if neither a dispatcher nor any other
ContinuationInterceptor is specified in their context.
It is backed by a shared pool of threads on JVM. By default, the
maximum number of threads used by this dispatcher is equal to the
number of CPU cores, but is at least two.
So even if you forget to mention the Dispatcher, Scheduler will pick any random available thread from the pool and hand it the Coroutine. But make sure that not to initiate any UI related work without mentioning the Dispatcher.
First of all, you must differentiate the scope from the context and dispatcher.
Coroutine scope is primarily about the lifecycle of the coroutine and deals with the concept of structured concurrency. It may have a default dispatcher, which would be the one logically associated with the object to which you tie the coroutine's lifecycle. For example, if you scope a coroutine to an Android activity, the default dispatcher will be UI.
Coroutine context refers to a dispatcher. The context should change during the coroutine's execution, as the logic inside requires it. Typically, you will use withContext to temporarily switch dispatchers in order to avoid blocking the UI thread. You will not typically launch the whole coroutine in the thread pool, unless all of it should run on a background thread (e.g., no UI interaction).
Second, the choice of dispatcher should be collocated with the code that requires a specific one. It should happen within the function that deals with a given concern, like making REST requests or DB operations. This once again reinforces the practice not to decide on dispatchers when launching the coroutine.
GlobalScope is an EmptyCoroutineScope and all coroutines launched with this scope are like demo threads. They cannot be canceled and remain active until their completion. I suggest implementing a specific scope e not using GlobalScope in order to control all the coroutines that are launched. The GlobalScope use the Dispatchers.Default as the default dispatcher and in your case you always create coroutines in the default dispatcher.

Launching a TornadoFX App from (an existing) Kotlin program

fun main(args: Array<String>) {
HelloWorldApp().launch()
}
fun App.launch() {
JFXPanel()
Platform.runLater({
start(Stage())
})
}
This is what I do right now. Is there a better? more succinct way?
Is it safe to run multiple different TornadoFX apps from within the same kotlin program this way? I read something somewhere about a global variable so I'm wondering if only 1 is allowed/recommended.
The JVM already knows how to start JavaFX applications, and since your App class extends tornadofx.App which again extends javafx.application.Application, you can simply point your JVM to that main class and it will run just fine. If you want to explicitly launch your TornadoFX application, JavaFX provides a static launch method you should use.
A typical main function that starts a JavaFX or TornadoFX application would be:
fun main(args: Array<String>) {
Application.launch(HelloWorldApp::class.java, *args)
}
JavaFX only allows the Application.launch function to be called one time in the life of a JVM, so you can't really start more than one anyways. However, TornadoFX provides special OSGi support allowing you to actually stop and relaunch other TornadoFX apps in the same JVM by utilizing an application proxy instance.
TornadoFX also supports JPro by using Scopes, which allows multiple application instance, though without actually calling Application.launch several times.
You can start it like this:
fun main(args: Array<String>) {
launch<HelloWorldApp>(args)
}
The launch function is defined in tornadofx package as a top-level function, HelloWorldApp is a random Application class.

Difference between a thread and a coroutine in Kotlin

Is there a specific language implementation in Kotlin which differs from another language's implementation of coroutines?
What does it mean that a coroutine is like a lightweight thread?
What is the difference?
Are Kotlin coroutines actually running in parallel (concurrently)?
Even in a multi-core system, is there only one coroutine running at any given time?
Here I'm starting 100,000 coroutines. What happens behind this code?
for(i in 0..100000){
async(CommonPool){
// Run long-running operations
}
}
What does it mean that a coroutine is like a lightweight thread?
Coroutine, like a thread, represents a sequence of actions that are executed concurrently with other coroutines (threads).
What is the difference?
A thread is directly linked to the native thread in the corresponding OS (operating system) and consumes a considerable amount of resources. In particular, it consumes a lot of memory for its stack. That is why you cannot just create 100k threads. You are likely to run out of memory. Switching between threads involves OS kernel dispatcher and it is a pretty expensive operation in terms of CPU cycles consumed.
A coroutine, on the other hand, is purely a user-level language abstraction. It does not tie any native resources and, in the simplest case, uses just one relatively small object in the JVM heap. That is why it is easy to create 100k coroutines. Switching between coroutines does not involve OS kernel at all. It can be as cheap as invoking a regular function.
Are Kotlin coroutines actually running in parallel (concurrently)? Even in a multi-core system, is there only one coroutine running at any given time?
A coroutine can be either running or suspended. A suspended coroutine is not associated to any particular thread, but a running coroutine runs on some thread (using a thread is the only way to execute anything inside an OS process). Whether different coroutines all run on the same thread (a thus may use only a single CPU in a multicore system) or in different threads (and thus may use multiple CPUs) is purely in the hands of a programmer who is using coroutines.
In Kotlin, dispatching of coroutines is controlled via coroutine context. You can read more about then in the
Guide to kotlinx.coroutines
Here I'm starting 100,000 coroutines. What happens behind this code?
Assuming that you are using launch function and CommonPool context from the kotlinx.coroutines project (which is open source) you can examine their source code here:
launch is defined here https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt
CommonPool is defined here https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CommonPool.kt
The launch just creates new coroutine, while CommonPool dispatches coroutines to a ForkJoinPool.commonPool() which does use multiple threads and thus executes on multiple CPUs in this example.
The code that follows launch invocation in {...} is called a suspending lambda. What is it and how are suspending lambdas and functions implemented (compiled) as well as standard library functions and classes like startCoroutines, suspendCoroutine and CoroutineContext is explained in the corresponding Kotlin coroutines design document.
Since I used coroutines only on JVM, I will talk about the JVM backend. There are also Kotlin Native and Kotlin JavaScript, but these backends for Kotlin are out of my scope.
So let's start with comparing Kotlin coroutines to other languages coroutines. Basically, you should know that there are two types of coroutines: stackless and stackful. Kotlin implements stackless coroutines - it means that coroutine doesn't have its own stack, and that limiting a little bit what coroutine can do. You can read a good explanation here.
Examples:
Stackless: C#, Scala, Kotlin
Stackful: Quasar, Javaflow
What does it mean that a coroutine is like a lightweight thread?
It means that coroutine in Kotlin doesn't have its own stack, it doesn't map on a native thread, it doesn't require context switching on a processor.
What is the difference?
Thread - preemptively multitasking. (usually).
Coroutine - cooperatively multitasking.
Thread - managed by OS (usually).
Coroutine - managed by a user.
Are Kotlin coroutines actually running in parallel (concurrently)?
It depends. You can run each coroutine in its own thread, or you can run all coroutines in one thread or some fixed thread pool.
More about how coroutines execute is here.
Even in a multi-core system, is there only one coroutine running at any given time?
No, see the previous answer.
Here I'm starting 100,000 coroutines. What happens behind this code?
Actually, it depends. But assume that you write the following code:
fun main(args: Array<String>) {
for (i in 0..100000) {
async(CommonPool) {
delay(1000)
}
}
}
This code executes instantly.
Because we need to wait for results from async call.
So let's fix this:
fun main(args: Array<String>) = runBlocking {
for (i in 0..100000) {
val job = async(CommonPool) {
delay(1)
println(i)
}
job.join()
}
}
When you run this program, Kotlin will create 2 * 100000 instances of Continuation, which will take a few dozen MB of RAM, and in the console, you will see numbers from 1 to 100000.
So let’s rewrite this code in this way:
fun main(args: Array<String>) = runBlocking {
val job = async(CommonPool) {
for (i in 0..100000) {
delay(1)
println(i)
}
}
job.join()
}
What do we achieve now? Now we create only 100,001 instances of Continuation, and this is much better.
Each created Continuation will be dispatched and executed on CommonPool (which is a static instance of ForkJoinPool).