Skip to content

Guide

Generators

auto fib = coro::generator<int>::create([](coro::coroutine_handle h) {
    int a = 0, b = 1;
    while (true) {
        (void)coro::yield_value(h, a);
        int next = a + b;
        a = b;
        b = next;
    }
});

for (int value : *fib) {
    std::printf("%d ", value);
    if (value > 100) break;
}
// Output: 0 1 1 2 3 5 8 13 21 34 55 89 144

Passing data

auto coro = coro::coroutine::create([](coro::coroutine_handle h) {
    auto value = h.pop<int>();
    if (value) {
        std::printf("received: %d\n", *value);
    }
});

(void)coro->push(42);
(void)coro->resume();
// Output: received: 42

Task runner

coro::task_runner runner;

runner.add(std::move(*coro::coroutine::create([](coro::coroutine_handle h) {
    std::puts("task A: step 1");
    (void)h.yield();
    std::puts("task A: step 2");
})));

runner.add(std::move(*coro::coroutine::create([](coro::coroutine_handle h) {
    std::puts("task B: step 1");
    (void)h.yield();
    std::puts("task B: step 2");
})));

(void)runner.run();
// Output: task A: step 1, task B: step 1, task A: step 2, task B: step 2

Exceptions

Exceptions thrown inside a coroutine are captured and can be inspected by the caller:

auto coro = coro::coroutine::create([](coro::coroutine_handle h) {
    (void)h.yield();
    throw std::runtime_error("something went wrong");
});

(void)coro->resume();  // step 1: OK
(void)coro->resume();  // step 2: coroutine throws, exception is captured

if (coro->has_exception()) {
    try {
        coro->rethrow_if_exception();
    } catch (std::exception const& e) {
        std::fprintf(stderr, "coroutine failed: %s\n", e.what());
    }
}

An exception can't unwind through the assembly switch, so ucoro catches it at the coroutine boundary. See Safety.

Unchecked API

These skip the state checks. Use them only when you already know the state:

auto coro = coro::coroutine::create([](coro::coroutine_handle h) {
    while (true) {
        int val = h.pop_unchecked<int>();
        h.push_unchecked(val * 2);
        h.yield_unchecked();
    }
});

coro->push_unchecked(21);
coro->resume_unchecked();
int result = coro->pop_unchecked<int>(); // 42