How to make sense of Kotlin coroutines? - asynchronous

I have tried reading various tutorials and pages on Kotlin coroutines and even though it kind of makes sense to me, I still don't feel it has clicked and I dont feel ready to jump on writing async non-blocking code with coroutines. I think what i am missing is a diagram or picture of what exactly happens and in what order when a piece of coroutine code executes. How does that code run at the thread level?
launch {
delay(1000)
println("World (${currentThread().name})")
}
println("Hello (${currentThread().name})")
sleep(1500)
My understanding is this. I am happy to be corrected or given a different example to further my understanding.
Line0: Code starts on main thread
Line1: Launches a new coroutine on a new thread (from forkjoin pool i suppose)
Line2: Suspending function so the coroutine suspends and returns the thread to the thread pool (hence being non-blocking)
Line5: Prints on the main thread
Line6: Blocks the main thread for 1.5s
Line3: The coroutine resumes execution on (not sure which thread here - same as the thread before suspension or can be a different thread?). The coroutines prints on that thread and finishes, hence returning the thread to the pool again.
Another question i have is how would the low-level execution change if i wrap the whole code around runBlocking { ... }

Your code doesn't actually do anything that would reveal the special nature of coroutines. It makes two threads do their thing concurrently, just as they would do it in plain Java.
It only gets interesting when you launch a coroutine on the same thread you're already on (for example, the main thread). This is one of the things you achieve with a runBlocking block:
runBlocking {
launch {
delay(1000)
println("Hello from the launched coroutine. My thread is "
+ Thread.currentThread().name)
}
println("Hello from the top-level coroutine. My thread is "
+ Thread.currentThread().name)
}
This will print
Hello from the top-level coroutine. My thread is main
Hello from the launched coroutine. My thread is main
runBlocking runs an event loop on the calling thread and propagates a reference to it to all the coroutines you launch within it. For example, delay(1000) will post an event to this event loop, with an indicated delay of one second, and then it will suspend the coroutine. This will allow the main thread to run the rest of the code below launch. When the time elapses, the event loop will run the event handler, which will in turn resume the coroutine.
An even more educational example is launching a coroutine without any Dispatcher. This removes the illusion of coroutines looking like threads and reveals their true magic: by calling continuation.resume() you make the current thread jump right into the middle of the suspended coroutine's block of code, and all that happens using plain Java method calls. I suggest studying this answer where this is explained in detail. If you're interested in an even more in-depth explanation of how plain Java methods can do this trick, I suggest you watch Roman Elizarov explaining this on YouTube.

Here is another example metioned here: https://kotlinlang.org/docs/reference/coroutines/basics.html#your-first-coroutine
fun main() {
GlobalScope.launch { // launch a new coroutine in background and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello,") // main thread continues while coroutine is delayed
Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
The above code prints:
Hello,
World!
As you can see, although the code looks synchronous, the execution is asynchronous. That's the whole idea of Coroutine.

Related

A question about Thread.Sleep inside backgroundworker

As far as I understand backgroundworker in .Net runs on a separate threat than in GUI. And Thread.Sleep is not recommended since it freezes the GUI.
Now if one uses Thread.Sleep inside backgroundworker's DoWork, would GUI freeze or this time Sleep will only sleep the BW's thread? Is it still not recommended?
(I tried to give 1 second pauses inside DoWork by Thread.Sleep(1000) seems it doesnt interfere with GUI. Is there another way to give pause inside BW rather than Thread.Sleep? await Task needs sync method which BW is not:()
Now if one uses Thread.Sleep inside backgroundworker's DoWork, would GUI freeze or this time Sleep will only sleep the BW's thread?
Thread.Sleep, like all other methods, runs on the current thread. So Thread.Sleep causes the current thread to sleep. If it's called from the BGW's DoWork, then it will cause the BGW's thread to sleep.
Is there another way to give pause inside BW rather than Thread.Sleep?
No, but you could replace the BackgroundWorker completely with Task.Run, and then you could use await Task.Delay instead of Thread.Sleep.

Kotlin: Any performance impact on converting a "normal" function to a blocking suspend function?

I have a function that looks like this:
fun <R> map(block: (T) -> R): Result<R> { ... }
and I'd like to make a suspending version:
suspend fun <R> mapAsync(block: suspend (T) -> R): Result<R> { ... }
The logic in both bodies are identical, but one suspends and one doesn't.
I don't want to have this duplicated logic. The only way I found for this to work is to have the map function call to the mapAsync function and then wrap the result in runBlocking:
fun <R> map(block: (T) -> R): Result<R> =
runBlocking { mapAsync { block(it) } }
So I have two questions:
Is there any performance considerations in taking a "normal" function, passing it as a suspend parameter, then block until the result is done?
Based on what I've read, it sounds like the initial thread keeps "doing the work" inside the suspend block until it hits the first suspend point. Then, the continuation is put into the wait queue and the initial thread is free to perform other work.
However, in this case, there isn't any "real" suspend point because the actual function is just (T) -> R, though I don't know if the compiler can tell that.
I'm worried that this setup is actually utilizing another thread from the pool that is just notifying my first thread to wake up...
Is there a better way to have a suspend and non-suspend set of functions utilize the same code?
You have encountered the infamous "colored function" problem. The two worlds are indeed separate and, while you can add a superficial layer that unifies them, you can't get it at zero performance cost. This is so fundamental that, even assuming that your suspend block never actually suspends, and the wrapping layer leverages that assumption and doesn't even use runBlocking on it, you will still pay the price of "being ready to suspend". The price isn't huge, though: it means creating a small object per each suspend fun call that holds the data that would normally reside on the thread's native call stack. In your case only the outer block is suspendable, so that's just one such object.
runBlocking runs the coroutine on the thread where you called it and it will finish synchronously on the same thread unless it suspends itself. Therefore your case where you'd have some synchronous code in a suspend block wouldn't suffer an additional performance hit from thread coordination.
If the coroutine does suspend itself, then there will have to be some external worker thread which will react to the event that allows the coroutine to resume, and there will have to be some coordination between that thread and your original runBlocking thread. This is a fundamental mechanism that's there with or without coroutines.
Your approach is correct, runBlocking was specifically designed to serve as a connection between blocking and non-blocking operations. From the documentation:
Runs new coroutine and blocks current thread interruptibly until its
completion. This function should not be used from coroutine. It is
designed to bridge regular blocking code to libraries that are written
in suspending style, to be used in main functions and in tests.
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
Also further read:
https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/basics.md#bridging-blocking-and-non-blocking-worlds
And some interesting videos by Roman Elizarov:
https://youtu.be/_hfBv0a09Jc
https://youtu.be/a3agLJQ6vt8

Swift 3: Why is OS_dispatch_queue_serial the default queue?

When I run the following playground I notice that the default dispatch queue seem to be a serial queue called OS_dispatch_queue_serial.
Why is that?
In this context I am confused on the semantic usage of async and sync, as in this case they seem to be behaving both synchronously and serially.
Am I wrong?
Am I confusing seriality with synchronisation?
Before running the code I was expecting to achieve the following:
Hello World
Hello Moon
world * (or Moon)
Moon * (or world)
// Note: here I assumed that async meant that the codes in the block would have been run in parallel to each other and that this would have meant that either world or Moon would have been printed depending on **race conditions**
Hello World
world
Hello Moon
Moon
Playground code:
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "com.test.myqueue")
queue.async {
print("Hello World")
sleep(2)
print("world")
}
queue.async {
print("Hello Moon")
sleep(1)
print("Moon")
}
queue.sync {
print("Hello World")
sleep(2)
print("world")
}
queue.sync {
print("Hello Moon")
sleep(1)
print("Moon")
}
Any help understanding this quicker would be great.
You're conflating synchronous vs. asynchronous and serial vs. parallel. They're orthogonal. Let me see if I can explain it:
Synchronous and asynchronous describe the behavior of the enqueued blocks relative to the enqueue-er.
Serial and parallel describe the behavior of the enqueued blocks relative to each other.
A serial queue executes blocks enqueued to it one at a time. This is true regardless of whether the blocks were enqueued synchronously or asynchronously.
A parallel queue executes things enqueued to it N at a time, where N is possibly (but not necessarily) greater than 1. This is true regardless of whether the blocks were enqueued synchronously or asynchronously.
If you enqueue a block synchronously, the enqueuing thread is stopped until the block's execution is completed (possibly on another thread). This is true regardless of whether the queue is serial or parallel.
If you enqueue a block asynchronously, the enqueuing thread continues, and the block executes (most likely on another thread) some amount of time later, possibly while the code on the enqueuing thread is still running. This is true regardless of whether the queue is serial or parallel.
As for why serial is the default, it's hard to say, but my guess would be that it's because a 'serial queue' is more in line with the dictionary definition of the word 'queue'.
Queues come in two flavors:
Serial - Runs blocks one at a time
Concurrent - Runs blocks more than one at a time
Dispatching blocks to queues comes in two flavors:
sync - Do this right now I will wait
async - Do this later, some time.
So in your example you create a serial queue (runs only one block at a time). Then you dispatch 4 blocks to that queue. Some of them run at some point (async) and some of the run immediately (sync). But because the queue is serial you only run one of them at a time. So in the illustration below the serial queue will complete block 1 before it starts block 2. The concurrent queue starts block 1 and block 2 at the same time and they both run at the same time.

How do Goliath or EventMachine switch context?

Assume I have an I/O-bounded operations. I do have a callbacks (or em-synchrony)
How does EM switch to proccess next request keeping previous one waiting for callback?
How does it keep Thread.current variables isolated?
How can I emulate long running jobs?
1. How does EM switch to proccess next request keeping previous one waiting for callback?
In any reactor pattern there is a single thread of the execution. Meaning, only one thing can execute at a time. If the reactor is processing a request on that main thread, then no other request can intervene (cooperative scheduling). Now, the request can "relinquish" control either voluntarily (in EM, we have EM.next_tick { # block }), or by scheduling an operation in the future: a timer (EM.add_timer { #block }), or by making another IO operation!
For example, if you're using EM-Synchrony, then when you make an HTTP request (via em-http), then when the request is dispatched, the fiber is paused, and a callback is created for you under the hood.. When the request is finished, the callback is invoked by EventMachine, via an internal callback.. and control returns back to your request. For a more in-depth look:
http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/
2. How does it keep Thread.current variables isolated?
No magic. In Ruby, we have thread local variables: Thread.current[:foo] = bar. Similarly, Fiber's have the same semantics, although what sometimes catches people off-guard is that the same mechanism is used.. aka Thread.current[:foo] = bar.
See here: http://devblog.avdi.org/2012/02/02/ruby-thread-locals-are-also-fiber-local/
3. How can I emulate long running jobs?
Best approach: move them outside of the reactor. This is true of any reactor system.
a) Create a job queue and push it to another process
b) EM does provide EM.defer, which spawns another thread.
Choose (a) whenever possible over (b).. you'll thank yourself later.

Qt application crashes when making 2 network requests from 2 threads

I have a Qt application that launches two threads from the main thread at start up. Both these threads make network requests using distinct instances of the QNetworkAccessManager object. My program keeps crashing about 50% of the times and I'm not sure which thread is crashing.
There is no data sharing or signalling occurring directly between the two threads. When a certain event occurs, one the threads signals the main thread, which may in turn signal the second thread. However, by printing logs, I am pretty certain the crash doesn't occur during the signalling.
The structure of both threads is as follows. There's hardly any difference between the threads except for the URL etc.
MyThread() : QThread() {
moveToThread(this);
}
MyThread()::~MyThread() {
delete m_manager;
delete m_request;
}
MyThread::run() {
m_manager = new QNetworkAccessManager();
m_request = new QNetworkRequest(QUrl("..."));
makeRequest();
exec();
}
MyThread::makeRequest() {
m_reply = m_manager->get(*m_request);
connect(m_reply, SIGNAL(finished()), this, SLOT(processReply()));
// my log line
}
MyThread::processReply() {
if (!m_reply->error()) {
QString data = QString(m_reply->readAll());
emit signalToMainThread(data);
}
m_reply->deleteLater();
exit(0);
}
Now the weird thing is that if I don't start one of the threads, the program runs fine, or at least doesn't crash in around 20 invocations. If both threads run one after the other, the program doesn't crash. The program only crashes about half the times if I start and run both the threads concurrently.
Another interesting thing I gathered from logs is that whenever the program crashes, the line labelled with the comment my log line is the last to be executed by both the threads. So I don't know which thread causes the crash. But it leads me to suspect that QNetworkAccessManager is somehow to blame.
I'm pretty blank about what's causing the crash. I will appreciate any suggestions or pointers. Thanks in advance.
First of all you're doing it wrong! Fix your threading first
// EDIT
From my own experience with this pattern i know that it may lead to many unclear crashes. I would start from clearing this thing out, as it may straighten some things and make finding problem clear. Also I don't know how do you invoke makeRequest. Also about QNetworkRequest. It is only a data structure so you don't need to make it on heap. Stack construction would be enough. Also you should remember (or protect somehow) from overwriting m_reply pointer. Do you call makeRequest more than once? If you do, then it may lead to deleting currently processed request after previous request finished.
What does happen if you call makeRequest twice:
First call of makeRequest assigns m_reply pointer.
Second call of makeRequest assigns m_reply pointer second time (replacing assigned pointer but not deleting pointed object)
Second request finishes before first, so processReply is called. deleteLater is queued at second
Somewhere in eventloop second reply is deleted, so from now m_reply pointer is pointing at some random (deleted) memory.
First reply finishes, so another processReply is called, but it operates on m_reply that is pointing a garbage, so every call at m_reply produces crash.
It is one of possible scenarios. That's why you don't get crash every time.
I'm not sure why do you call exit(0) at reply finish. It's also incorrect here if you use more then one call of makeRequest. Remember that QThread is interface to a single thread, not thread pool. So you can't call start() second time on thread instance when it is still running. Also if you're creating network access manager in entry point run() you should delete it in same place after exec(). Remember that exec() is blocking, so your objects won't be deleted before your thread exits.

Resources