commit 4e799093ad1f9b1bbc06edd48d5432d8f886d79b
parent d7a745b6f8e9c23ff4e621e895aa39f908376345
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Sun, 11 Jan 2026 20:33:58 +0000
Coroutines from scratch!
Diffstat:
| A | coro.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);
+}