Project Loom will bring continuations and fibers (similar to kotlin coroutines) natively to the JVM in a not so distant future.
It seems like they will be able to achieve to automatically convert blocking calls to suspending ones, when run inside a fiber. This magically makes things like Thread.sleep() or socket io suspending. There is no need to mark functions with a suspend modifier, annotation or similar.
Also they have plans to provide some form of structured concurrency.
For me the opportunity to automatically turn all the existing, blocking calls into suspending ones is very exciting. For example JDBC would magically become non-blocking
Will kotlin coroutines be able to leverage this new feature? Will a Thread.sleep() on the JVM after project Loom be suspending instead of blocking? Would coroutines on the JVM need to be re-implemented on top of Fibers for that to work? Is that a feasible option?
I think having kotlin coroutines and Fibers integrated very well will be crucial for interoperability. What’s your opinions on this?
With the new java release cycle features are basically scheduled for release when they are done. We will not know when it will be published until some weeks before the release. However in some talks of Ron Pressler (e.g. this one) I got the impression they are quite far and are already actively looking for feedback on the fiber API. Here he says that the he sees the probability quite high that they will be released next year.
The question for me is if coroutines will be able to leverage the changes in the JDK to also suspend on traditionally blocking calls instead of blocking. To me this looks like a huge thing.
The implementation style of project loom continuations seems to be quite different to the approach of kotlin. This has me worried that this sort of integration will be hard if not impossible to achieve with the current implementation.
The project Loom as well as other JDK projects do not have specific release plan so we do not know, when it will be available (from the looks of it, not soon). There were several discussions on integration with coroutines and the most frequent response: we will see when they are done and make integration if it will make sense. So we should wait for more specific information about Loom.
Let’s try to make this concrete with an example. We want to achieve that on JDK platform after Project Loom Thread.sleep() becomes suspending instead of blocking.
This is the current implementation of Thread.sleep() in the loom repository:
public static void sleep(long millis) throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (currentCarrierThread().getFiber() != null) {
Fiber.sleepNanos(TimeUnit.MILLISECONDS.toNanos(millis));
} else {
sleep0(millis);
}
}
private static native void sleep0(long millis) throws InterruptedException;
The if branch related to fibers was newly added. As long as there is no fiber involved, the old blocking behavior will be executed. Why should scheduling on a ForkJoinPool, which still executes the tasks on a regular Thread after all, help in any way? There would have to be at least a fiber somewhere.
I do not really understand, what does it have to do with coroutines. They do not use Threads operations so if you are using coroutines and Thread.sleep implementation changes, you won’t feel it since you do not use it. The only thing that could change is the implementation of the scheduler.
Also, I want to mention that currently, coroutines are much more than lightweight threads. There are a lot of things you can do with coroutines, that won’t be ever possible with loom. For simple example take sequence generators. It use coroutine state-machine, but not the multi-threading.
Does not help in such case, only in the case of a Fiber will be based ForkAndJoinPool
As @darksnake said, may be implemented a Dispatchers.Fiber, but is not required.
Similary can be defined a some kind of structured concurrency integration.
Thread.sleep() was just one example. Much more interesting are other blocking APIs like JDBC. When we use JDBC within a fiber, the operations should become suspending automatically instead of blocking. The thread is free to perform other tasks. This isn’t the case for kotlin coroutines.
I really like coroutines and continuations in kotlin and understand that they provide a lot of value beyond threading. However I don’t see why these things shouldn’t be possible with a (later) version of project Loom. They implement continuations at a very low level as well. Your example of sequence generators is explicitly mentioned quite often in Loom talks.
Project loom implements Delimited continuations, Fibers, and Tails-Call on JVM. So I don’t think the above statement is true for project loom. See this The primitive continuation construct is that of a scoped (AKA multiple-named-prompt), stackful, one-shot (non-reentrant) delimited continuation. The continuation can be cloned, and thus used to implement reentrant delimited continuations. The construct is exposed via the java.lang.Continuation class. Continuations are intended as a low-level API, that application authors are not intended to use directly. They will use higher-level constructs built on top of continuations, such as fibers or generators.
The loom initial design seems mostly mature and it seems likely that loom comes in java 15 as a preview https://cr.openjdk.java.net/~rpressler/loom/loom/sol1_part1.html
It should bring a lot of benefits to kotlin like better performance (io uring, restartable sequences, etc) make all code non blocking for free and most importantly bring better debugger single step support