types of coroutines, fibers
Types of coroutines, fibers
Coroutines have been used in programming since 1958 and were defined by Knuth as a way to generalize a subroutine. While regular subroutines start at the beginning and end at the end, coroutines can pause their execution and resume later from where they left off. An explanation of this can be found here.
The topic is complex because we normally mix "what a coroutine is" with "how it is going to run".
There are two common ways to use coroutines:
- stackless, where the code is transformed into a state machine by the compiler.
- stackful, also known as fibers, which are user-mode threads that run on top of a regular operating system thread.
We can identify two types of coroutines based on their need for a stack:
- stackless, only require a stack while the coroutine is running. Once the coroutine suspends, its local variables can be serialized into a fixed-size structure, and the current call stack can be used for executing the next coroutine.
- stackful, allows you to suspend your coroutines at any point, providing more flexibility than stackless coroutines.
The lack of a stack is what allows the compiler to transform and use a stackless coroutine, while the need for a stack requires a runtime.
When you use async/await in your code, the compiler generates a state machine that will be executed later. This is because when you use async/await, you're only suspending execution at known points, which means you don't need a stack to keep track of where you left off. The compiler can transform your code into a state machine that saves the state of the local variables and continues execution where it left off when it's resumed.
On the other hand, when you use goroutines/fibers/green threads, you can suspend and pause execution anywhere in the code, which means you need a stack to keep track of where you left off. These kinds of coroutines also require a runtime that can manage the stacks and schedule the coroutines to run on the available threads.