commit 9f14c4c1b95ad1cabd4d8c40fb85690740d44e90
parent 4e799093ad1f9b1bbc06edd48d5432d8f886d79b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Thu, 15 Jan 2026 01:17:51 +0000
coro: memory buffer based allocation
Diffstat:
| M | coro.cpp | | | 74 | +++++++++++++++++++++++++++++++++++++++++--------------------------------- |
1 file changed, 41 insertions(+), 33 deletions(-)
diff --git a/coro.cpp b/coro.cpp
@@ -1,19 +1,9 @@
#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*);
+ void(*resume)(coroutine_frame*) noexcept;
+ void(*destroy)(coroutine_frame*) noexcept;
};
namespace std
@@ -27,41 +17,47 @@ struct coroutine_traits
template <typename T = void>
struct coroutine_handle {
- static coroutine_handle<T> from_address(void* ptr)
+ static coroutine_handle from_address(void* ptr) noexcept
+ {
+ return coroutine_handle{ptr};
+ }
+ static coroutine_handle from_promise(T& promise) noexcept
{
- return {(coroutine_frame*)ptr};
+ return coroutine_handle{((char*)&promise) - sizeof(coroutine_frame)};
}
- void resume() const {
+ void resume() const noexcept {
assert(frame);
assert(frame->resume);
frame->resume(frame);
}
- void destroy() const {
+ void destroy() const noexcept {
assert(frame);
assert(frame->destroy);
frame->destroy(frame);
}
- operator coroutine_handle<void>() const { return {frame}; }
- bool done() const
+ bool done() const noexcept
{
assert(frame);
return not frame->resume;
}
-//private:
+private:
+ coroutine_handle(void* ptr) noexcept : frame{reinterpret_cast<coroutine_frame*>(ptr)} {}
coroutine_frame* frame = nullptr;
};
struct suspend_always
{
bool await_ready() noexcept { return false; }
- void await_suspend(coroutine_handle<>) noexcept { }
+ template <typename T> // easier to do this that provide a <void> specialisation for now
+ void await_suspend(coroutine_handle<T>) noexcept {}
void await_resume() noexcept {}
};
struct suspend_never
{
bool await_ready() noexcept { return true; }
- void await_suspend(coroutine_handle<>) noexcept { __builtin_trap(); }
+ template <typename T>
+ void await_suspend(coroutine_handle<T>) noexcept { __builtin_trap(); }
void await_resume() noexcept {}
};
@@ -70,20 +66,30 @@ struct suspend_never
struct task
{
struct promise_type {
- std::suspend_never initial_suspend() { return {}; }
+ std::suspend_never initial_suspend() noexcept { 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)};
+ task get_return_object() noexcept {
+ return {std::coroutine_handle<promise_type>::from_promise(*this)};
}
void unhandled_exception() noexcept {}
- void return_void() {}
+ void return_void() noexcept {}
+ void* operator new(size_t s, span<char> storage) noexcept {
+ assert(s <= storage.size());
+ return storage.begin();
+ }
+ void operator delete(void*, size_t) noexcept {}
};
+ ~task() { h.destroy(); }
+ bool done() const noexcept { return h.done(); }
+ void resume() const noexcept { h.resume(); }
+private:
+ friend struct promise_type;
+ task(std::coroutine_handle<promise_type> ch) : h{ch} {}
std::coroutine_handle<promise_type> h;
};
-task mytask()
+task mytask(span<char> /*forwarded to new*/) noexcept
{
*write(stdout, "mytask: started\n"_sp);
for (int i = 0; i < 3; ++i)
@@ -97,13 +103,15 @@ task mytask()
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);
+ char memory[56];
+ task t = mytask(span{memory});
+ *write(stdout, "main: mytask created\n"_sp);
+ while (not t.done())
+ {
+ t.resume();
+ *write(stdout, "main: back from resume\n"_sp);
+ }
}
- t.h.destroy();
*write(stdout, "main: mytask destroyed\n"_sp);
}