What is a coroutine? How are they related to concurrency?
I find an explanation from this link is pretty straight forward. None of those answers try to explain concurrency vs parallelism except the last bullet point in this answer.
cited from "programming Erlang", by Joe Armstrong, the legendary:
a concurrent program can run potentially faster on a parallel computer.
a concurrent program is a program written in a concurrent programming language. We write concurrent programs for reasons of performance, scalability, or fault tolerance.
a concurrent programming language is a language that has explicit language constructs for writing concurrent programs. These constructs are an integral part of programming language and behave the same way on all operating systems.
a parallel computer is a computer that has several processing units (CPUs or cores) that can run at the same time.
So concurrency is not the same as parallelism. You can still write concurrent programs on a single-core computer. The time-sharing scheduler will make you feel your program is running concurrently.
The concurrent program has the potential to run in parallel in a parallel computer but not guaranteed. OS may only give you one core to run your program.
Therefore, concurrency is a software model from a concurrent program that doesn't mean your program can run in parallel physically.
The word “coroutine” is composed of two words: “co” (cooperative) and “routines” (functions).
a. does it achieve concurrency or parallelism?
To be simple, let's discuss it on a single-core computer.
Concurrency is achieved by time-shares from OS. A thread executes its code in its assigned time frames on the CPU core. It can be preempted by OS. It may also yield control to OS.
A coroutine, on the other hand, yields control to another coroutine within the thread, not to OS. So all coroutines within a thread still exploit the time frame for that thread without yielding the CPU core to other threads managed by OS.
Therefore, you can think of coroutine achieves time-shares by the user not by OS (or quasi-parallelism). Coroutines run on the same core assigned to the thread that runs those coroutines.
Does Coroutine achieve parallelism? If it's CPU-bound code, no. Like time-shares, it makes you feel they run in parallel but their executions are interleaved not overlapped. If it's IO-bound, yes, it achieves parallel by hardware (IO devices) not by your code.
b. the difference with function call?
As the pic shows, it doesn't need to call return to switch control. It can yield without return. A coroutine saves and shares state on the current function frame (stack). So it's much more lightweight than function since you don't have to save registers and local variables to stack and rewind call stack when call ret.