Fundamentals 13 min read

Why Coroutines Matter: A Beginner’s Guide to Pausable Functions

This article explains what coroutines are, how they differ from ordinary functions by supporting multiple pause points, demonstrates their behavior with Python code and visual diagrams, covers their historical origins, and details low‑level implementation using stack frames and heap allocation for efficient user‑level concurrency.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Why Coroutines Matter: A Beginner’s Guide to Pausable Functions

What Is a Coroutine?

Coroutines are functions that can be paused and later resumed, allowing multiple return points instead of a single exit. They are language‑agnostic concepts; the article uses Python for simplicity, but the ideas apply to any programming language.

Ordinary Function Example

def func():
    print("a")
    print("b")
    print("c")

Calling func() runs sequentially, printing a, b, c and then returns.

From Ordinary Function to Coroutine

Unlike a normal function, a coroutine can yield control back to the caller multiple times. The pseudo‑code below illustrates the idea of “pause and return” after each print statement.

void func() {
    print("a");
    // pause and return
    print("b");
    // pause and return
    print("c");
}

When the coroutine reaches a yield (or equivalent), execution stops, the current state is saved, and control returns to the caller. Subsequent calls resume execution right after the last yield.

Show Me the Code (Python)

def func():
    print("a")
    yield
    print("b")
    yield
    print("c")
def A():
    co = func()          # obtain the coroutine object
    next(co)             # first resume – prints "a"
    print("in function A")
    next(co)             # second resume – prints "b"

Running A() produces the output:

a
in function A
b

The second next(co) call resumes the coroutine after the first yield, demonstrating that the coroutine remembers where it left off.

Visual Explanation

Images illustrate the control flow of a normal function versus a coroutine. In the normal case, execution follows a single path. In the coroutine case, the flow returns to the caller at each yield and later continues from that point.

Normal function call diagram
Normal function call diagram
Coroutine call diagram
Coroutine call diagram

Coroutines as a Special Case of Functions

A regular function is simply a coroutine without any pause points. Adding yield (or its language‑specific equivalent) turns a function into a coroutine, giving the programmer explicit control over when execution is suspended and resumed.

History of Coroutines

The concept dates back to 1958, predating threads. Early implementations appeared in Simula 67 and Scheme (1972). Interest waned after threads became common, but the rise of high‑concurrency server workloads in the 2010s revived coroutines across many modern languages.

How Coroutines Are Implemented

At a low level, a coroutine’s execution state (its stack frame) must be saved when it yields. The article explains that this state is stored on the heap rather than the traditional call stack, allowing the scheduler to switch between many coroutines without creating OS threads.

// Allocate a heap block for the coroutine’s stack frame
Coroutine *c = malloc(sizeof(CoroutineStack));
// Save registers, locals, etc., into the heap block
save_context(c);
// Later, restore to resume
restore_context(c);

Multiple coroutines share a single OS thread; their stacks live in heap memory, enabling thousands of concurrent execution flows with minimal overhead.

Benefits

Massive concurrency without the cost of kernel threads.

User‑level scheduling gives programmers fine‑grained control.

Coroutines can be visualized as lightweight, user‑space threads.

Understanding coroutines equips developers to write high‑performance, asynchronous code in languages such as Python, Go, JavaScript, and many others.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Pythonasynchronous programmingcoroutineYield
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.