liblinux++

A hosted C++ runtime without any libc.
git clone git://henryandlizzy.uk/liblinux++
Log | Files | Refs

commit 4e799093ad1f9b1bbc06edd48d5432d8f886d79b
parent d7a745b6f8e9c23ff4e621e895aa39f908376345
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Sun, 11 Jan 2026 20:33:58 +0000

Coroutines from scratch!

Diffstat:
Acoro.cpp | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+), 0 deletions(-)

diff --git a/coro.cpp b/coro.cpp @@ -0,0 +1,109 @@ +#include "linux.hpp" + +void* operator new(size_t size) +{ + return *mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, {}, 0); +} + +void operator delete(void* p, size_t size) noexcept +{ + *munmap(p, size); +} + +struct coroutine_frame +{ + void(*resume)(coroutine_frame*); + void(*destroy)(coroutine_frame*); +}; + +namespace std +{ + +template <typename T, typename... Ts> +struct coroutine_traits +{ + using promise_type = T::promise_type; +}; + +template <typename T = void> +struct coroutine_handle { + static coroutine_handle<T> from_address(void* ptr) + { + return {(coroutine_frame*)ptr}; + } + void resume() const { + assert(frame); + assert(frame->resume); + frame->resume(frame); + } + void destroy() const { + assert(frame); + assert(frame->destroy); + frame->destroy(frame); + } + operator coroutine_handle<void>() const { return {frame}; } + bool done() const + { + assert(frame); + return not frame->resume; + } +//private: + coroutine_frame* frame = nullptr; +}; + +struct suspend_always +{ + bool await_ready() noexcept { return false; } + void await_suspend(coroutine_handle<>) noexcept { } + void await_resume() noexcept {} +}; + +struct suspend_never +{ + bool await_ready() noexcept { return true; } + void await_suspend(coroutine_handle<>) noexcept { __builtin_trap(); } + void await_resume() noexcept {} +}; + +} + +struct task +{ + struct promise_type { + std::suspend_never initial_suspend() { return {}; } + std::suspend_always final_suspend() noexcept { return {}; } + task get_return_object() { + void* p = reinterpret_cast<char*>(this) - sizeof(coroutine_frame); + return {std::coroutine_handle<promise_type>::from_address(p)}; + } + void unhandled_exception() noexcept {} + void return_void() {} + }; + + std::coroutine_handle<promise_type> h; +}; + +task mytask() +{ + *write(stdout, "mytask: started\n"_sp); + for (int i = 0; i < 3; ++i) + { + co_await std::suspend_always{}; + *write(stdout, "mytask: resumed\n"_sp); + } + co_return; +} + +int main() +{ + *write(stdout, "main\n"_sp); + [[maybe_unused]] task t = mytask(); + *write(stdout, "main: mytask created\n"_sp); + while (not t.h.done()) + { + t.h.resume(); + *write(stdout, "main: back from resume\n"_sp); + } + t.h.destroy(); + *write(stdout, "main: mytask destroyed\n"_sp); +}