#include "async.h" #include #include #include namespace async { namespace { using namespace std::literals::chrono_literals; struct Stuff { std::coroutine_handle<> h; std::chrono::system_clock::time_point expiration; Stuff* next; }; std::atomic work; std::array, static_cast(AwaitableType::kNumTypes)> queues; } // namespace void schedule(std::coroutine_handle<> h, int ms) { std::chrono::system_clock::time_point exp = std::chrono::system_clock::now() + std::chrono::milliseconds(ms); Stuff* news = new Stuff{ .h = h, .expiration = exp, }; Stuff* stuff = work; if (!stuff || stuff->expiration > exp) { news->next = stuff; work = news; return; } Stuff* s = stuff; while (s->next && s->next->expiration <= exp) { s = s->next; } news->next = s->next; s->next = news; } void main_loop(void (*idle_function)()) { while (1) { if (idle_function != nullptr) { idle_function(); } Stuff* stuff = work; if (stuff == nullptr) { continue; // busyloop } auto now = std::chrono::system_clock::now(); auto dt = stuff->expiration - now; if (dt > 0ms) { continue; } stuff->h(); if (stuff->h.done()) { stuff->h.destroy(); } Stuff* oldstuff = stuff; work = stuff->next; delete oldstuff; } } void enqueue(std::coroutine_handle<> h, AwaitableType type) { Stuff* item = new Stuff{.h = h}; auto ttype = static_cast(type); Stuff* stuff = queues[ttype]; if (stuff == nullptr) { queues[ttype] = item; return; } while (stuff->next != nullptr) { stuff = stuff->next; } stuff->next = item; } void resume(AwaitableType type) { auto ttype = static_cast(type); Stuff* stuff = queues[ttype]; if (stuff == nullptr) { return; } queues[ttype] = stuff->next; schedule(stuff->h); delete stuff; } } // namespace async #if 0 task readline() { int size = 0; char c; buffer buff = buffer::make(32); // fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); while (true) { int n = read(0, &c, 1); if (n < 1) { co_await co_waitio(); continue; } buff.data[size++] = static_cast(c); if (c == '\n') { buff.data = buff.data.subspan(0, size); co_return buff; } } } #endif // 0