I'm not exactly sure what is the purpose of the yield function. Can you check this example I have?
I am following an example here.
Here is the code:
val job = launch {
val child = launch {
try {
delay(Long.MAX_VALUE)
} finally {
println("Child is cancelled")
}
}
yield() //why do i need this ???????
println("Cancelling child")
child.cancel()
child.join()
yield()
println("Parent is not cancelled")
}
job.join()
When I comment out the first yield I get the following results:
Cancelling child
Parent is not cancelled
but if I leave the yield as it is I get:
Cancelling child
Child is cancelled
Parent is not cancelled
What does it mean to use yield here?
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/yield.html
Yields a thread (or thread pool) of the current coroutine dispatcher to other coroutines to run. If the coroutine dispatcher does not have its own thread pool (like Dispatchers.Unconfined) then this function does nothing, but checks if the coroutine Job was completed. This suspending function is cancellable. If the Job of the current coroutine is cancelled or completed when this suspending function is invoked or while this function is waiting for dispatching, it resumes with CancellationException.
It accomplishes at least a few things
After some research, I see that the term yield is actually from computer science and the term yielding a thread is what I did not understand.
essentially: yield() basically means that the thread is not doing anything that important and if other threads need to be run, they can run. (I'd prefer to use join as Alex Yu mentioned). Basically, if we want to visualize what yield is doing... whatever thread you call yield on will get pushed to the back of the messaging queue, then other threads with the same priority get executed ahead of it. So it's like going to the back of the line at a club.
In your example, yield() is called inside parent job. It says to your parent: "you work much more, wait please, i will let the other tasks to work for some time, after some time i will let you continue to work ".
Thus parent job waits.. Child job works some time.. After some time, parent job passes the next line which comes after yield(), and cancels the child job.
If you do not use yield() in your example, parent job immediately cancels child job.
Let me explain the yield with different example which shows yield in much more clear way. 2 jobs wait in the queue for waiting thread to let them to work. When you call yield, thread looks into the queue and sees other job waiting so it lets the other job to work.
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.yield
fun main() = runBlocking {
val job1 = launch {
repeat(10) {
delay(1000)
println("$it. step done in job 1 ")
yield()
}
}
val job2 = launch {
repeat(10) {
delay(1000)
println("$it. step done in job 2 ")
yield()
}
}
job1.join()
job2.join()
println("done")
}
Output:
0. step done in job 1
0. step done in job 2
1. step done in job 1
1. step done in job 2
2. step done in job 1
2. step done in job 2
3. step done in job 1
3. step done in job 2
4. step done in job 1
4. step done in job 2
5. step done in job 1
5. step done in job 2
6. step done in job 1
6. step done in job 2
7. step done in job 1
7. step done in job 2
8. step done in job 1
8. step done in job 2
9. step done in job 1
9. step done in job 2
done