Kotlin vs. modern Java

I don’t know it very well, but as far as I understand the concept, it is even simpler. We don’t need withContext(Dispatechers.IO), because we can call the “blocking” code as normal.

Main thread is an interesting problem though, @fvasco mentioned it already. I assume it should be possible to run an executor with parallelism=1, maybe even assign it to a single physical thread, and it would provide a similar functionality, but there are still 2 problems:

  • The main idea behind event loops is that we can mutate the shared state freely, events are guaranteed to be handled fully before picking up the next one, etc. This is still partially valid in Kotlin, because coroutines are scheduled cooperatively, so as long as we don’t suspend, we keep the same benefits. With preemtive scheduling, we lose main advantages of using event loops. Does Loom allow to selectively switch to cooperative scheduling?
  • Kotlin couroutines could easily wrap an existing implementation of an event loop, which doesn’t know about Kotlin. This is possible because suspending is implemented by returning. It is hard for me to imagine how could it possibly work with Loom. But maybe they already solved this problem somehow.

edit:
The above code shouldn’t be a problem, I don’t see a reason why it wouldn’t be possible with Loom. Problem may happen if we need to suspend inside the main thread.

2 Likes

Roman Elizarov of JetBrains gave a good talk at KotlinConf about Coroutines and Loom. TL;DR is they’re good for different things.

OK, I actually looked into JEP 428, Java’s proposed structured concurrency solution, and I have to agree with what Roman says about it in the video: since it’s bolted on (and not baked in like with coroutines) it’s harder to use. It also doesn’t have the flexibility of Kotlin’s coroutineScope() function.

It’s interesting, you seem to come from the Java threads world, so you think Loom is easier to understand. I come from the anti-threads world, so I think coroutines is easier to understand.

2 Likes

If you’re asking, “Can I use Loom to write a chunk of code where some of it runs on a background thread and some of it runs on the main thread?” then I’m pretty sure the answer is no. Loom allows virtual threads, but conceptually they’re still threads, and you have to use the same techniques Java programmers have been using for decades to communicate between them.

2 Likes

I was never a huge fun of threading in Java and I love coroutines in Kotlin. But I can’t deny virtual threads are just simpler and easier to use. At least on the conceptual level, because if we look into the code, then all Java APIs are always clumsy and require 3x Kotlin’s amount of code.

Essentially, threads and coroutines are pretty similar concepts, they have much more similarities than differences. We launch some block of code, we execute it sequentially from top to bottom, we wait in-place - that’s it. Asynchronous programming based on callbacks, promises or reactive streams are much, much different concepts, but threads and coroutines seem like the same end-user pattern, but with a different implementation underneath.

But the difference is that in coroutines we often have to plan and think of things and problems that I suspect may not even exist in Loom. Is it suspend or not? How to execute it then, as I’m not in the suspend context? How to pass the suspend context through 3rd party library? How to adapt existing asynchronous library to coroutines? Is this operation blocking or not? How to utilize a library which uses locks, ThreadLocal, etc.? What is a continuation? In Java we do what I said above: we execute a virtual thread and that’s pretty much it.

Switching to another thread is like launching a new execution flow and suspending the first one. I don’t really see a reason why the above code couldn’t be written in Loom as e.g.:

// no need to switch
val response = repository.getResponse()
runInMain {
    uiElement.show(response)
}

Also, I think the whole discussion about switching threads is like an XY problem. We don’t switch threads to switch threads - we do this to solve other problems. Problems that may not even exist in Loom. When was the last time you looked for a way to “switch the CPU core”?

Usually, we have to switch threads to jump between CPU-intensive and I/O. But this is not needed in Loom. Or we need to limit the parallelism, but both coroutines and (as I suspect) Loom provide tools for it, so we don’t have to think in terms of separate thread pools.

Event loops is a different story, and again - I don’t know how the Loom Team plan to tackle this. But maybe the whole even loop pattern is also obsolete and we needed it only because we didn’t have a better alternative. This may sound crazy, I agree, but correct me if I’m wrong - in Compose we don’t think in terms of threads anymore, right? Maybe only for interoperability with other code. Time will tell.

3 Likes

What is that runInMain function you use in your example? It’s not in the Java SDK or Loom.

I don’t think Loom has any plans for the main event loop thread. That’s not the problem they’re trying to solve. But coroutines has the ability to run code on the main/UI thread baked in, and that’s the problem that I need a solution for.

1 Like

That was just an example. Again, I don’t see a reason why that would be impossible. But the problem may appear if we need to suspend inside the main thread. Coroutines support this, thanks to their suspend-by-returning approach. It may be tricky with the Loom though.

I’m surprised nobody mentioned unsigned integers in this thread, which are still missing in java.

4 Likes

Probably not the most important thing but I can say from some flutter development I did, having to go back to semicolons is very painful

1 Like

Why are people comparing Loom against coroutines here?
Is there a reason I could not use Loom with Kotlin?

I’m comparing Loom and coroutines because they are two separate solutions for two different problems.

You can totally use Loom in Kotlin, if that’s the solution you need.

1 Like

People are comparing coroutines and Loom, because they solve pretty much the same problem (yeah, I said the opposite of what @ebrowne72 said :smiley: ). Of course, we can use Loom in Kotlin, it is even technically possible to run coroutines on top of Loom. But the point is: coroutines are one of the biggest selling point of Kotlin. If Loom gets enough adoption in the industry and people will start choosing Loom over coroutines even in Kotlin projects, for example for Java interop, then the Kotlin will partially lose one of its biggest benefits.