Subroutines vs Coroutines vs Generators
- invoked once and executes until it completed.
- can be translated to a coroutine which does not call
- a more generalized form of subroutines.
- can be entered, exited, and resumed at many different points.
- can pause execution and yield control back to the caller or another coroutine. The caller can then resume the coroutine when appropriate. (i.e. it may suspend its execution in one thread and resume in another one. A coroutine is not bound to any particular thread.)
- used for cooperative multitasking and are often compared to fibers, lightweight threads and green threads
Generators: a.k.a. "semicoroutines": a more limited form of coroutine that may only yield to its caller. Primarily used to simplify the writing of iterators.
Both can yield multiple times, suspending their execution and allowing re-entry at multiple entry points.
- Generators: can only yield to its caller. Cannot specify a coroutine to jump to in the
- Coroutines: can control where execution continues immediately after they yield.
- threads: scheduled by the operating systems.
- coroutines: scheduled by the users. (A.k.a. lightweight threads or green threads.)
- C++: coroutines introduced in C++20.
- Kotlin: in an extension lib
kotlinx.coroutines. (NO keywords and NOT in the standard library)
- Java: Project Loom.
- goroutines imply parallelism; coroutines in general do not
- goroutines communicate via channels; coroutines communicate via yield and resume operations
- data structure iterators.
- event-driven code without the inversion of control.
- cooperative multitasking.
- concurrency frameworks such as actors, async-await and dataflow networks.
- expressing asynchrony, and better composition of asynchronous systems.
- capturing continuations.
- expressing backtracking algorithms.
- AI agents such as behavior trees.