Reputation: 25892
This might be a very basic question in terms of Asynchronous Programming, but I tried reading about it and couldn't find any resource for the same.
Assumption: A general idea I have about asynchronous programming:
When we start a blocking operation(networks call, reading from DB/file), we can delegate it to Kernel thread(s) which will keep our application thread(s) free for other jobs. The kernel thread waits for the job to be done and gives a callback to the application thread whenever the job is done.
Coroutines: I have been reading about Kotlin Coroutines for last few days. I think the concept wise coroutines are language agnostic though. The question I have been getting is:
How the suspension
and continuation
takes place for a co-routine. Coroutines are not threads(which are given a slice of the processor by OS), they are tasks
which will be scheduled on a thread to be executed.
Who keeps looking for the program in execution and say, this coroutine has hit a suspension point and it should be taken out of thread. Another coroutine which needs to be resumed from continuation
should be scheduled on the thread. As for as I have read about Java Fibers
it will be done by a Fiber Scheduler
, is it similar in Kotlin?
Thank for the help in advance.
Upvotes: 9
Views: 824
Reputation: 200168
Coroutine suspension is entirely explicit and first-class. It happens when you call suspendCoroutine()
or suspendCancellableCoroutine()
, passing in a block that receives the continuation as the parameter.
The block can do whatever it wants with the continuation object, and when someone, somewhere, calls continuation.resume(resultValue()
, it will resume. The thread it resumes on is initially the thread that calls resume()
, but the logic inside resume
immediately delegates to the Dispatcher in charge, which then typically submits the resumption to another thread or thread pool.
The Dispatcher logic is again first-class and you can write your own dispatcher. However, this is almost never needed because there are only a handful of meaningful ways to do it, and Kotlin already supports them.
You can also review a concrete example in code that demonstrates the naked usage of suspendCoroutine
and coroutine.resume()
, without the layer the Dispatcher adds to it.
BTW you never delegate blocking operations to "kernel threads" to make them non-blocking. Async operations don't block any thread. On the low level there's for example the mechanism of a selector that receives events from IO operations when they complete. It works much like the event loop in a GUI thread.
Upvotes: 7