examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

commit 665a10412fc08fdc81263695f3bb86fda96eb88e
parent 00c134357d45d84224f4fc126c921f12b2ea2b6f
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Sat,  2 Apr 2022 18:16:05 +0100

Add coroutine timer dispatch example

Diffstat:
Rsrc/robin.cpp -> src/coro-round-robin.cpp | 0
Asrc/coro-timer-dispatch.cpp | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/coro.cpp -> src/coro-unconditional-dispatch.cpp | 0
3 files changed, 180 insertions(+), 0 deletions(-)

diff --git a/src/robin.cpp b/src/coro-round-robin.cpp diff --git a/src/coro-timer-dispatch.cpp b/src/coro-timer-dispatch.cpp @@ -0,0 +1,180 @@ +#include <coroutine> +#include <iostream> +#include <list> +#include <unistd.h> + +static int jiffies; + +struct jiffies_scheduler +{ + struct scheduled_event + { + std::coroutine_handle<> h; + int when; + + friend bool operator <(int w, scheduled_event const& e) noexcept + { + return w < e.when; + } + }; + + struct jiffies_timeout : std::suspend_always + { + jiffies_scheduler& scheduler; + int when; + + jiffies_timeout(jiffies_scheduler& s, int w) + : scheduler(s) + , when(w) + {} + + /*bool await_ready(void) const noexcept + { + return tasks.empty(); + }*/ + + std::coroutine_handle<> await_suspend(std::coroutine_handle<> h) + { + scheduler.schedule(h, when); + return scheduler.next(); + } + }; + + std::list<scheduled_event> tasks; + + void schedule(std::coroutine_handle<> h, int w) + { + auto pos = std::upper_bound(tasks.begin(), tasks.end(), w); + tasks.insert(pos, {h, w}); + } + + std::coroutine_handle<> next(void) noexcept + { + if (tasks.empty()) + return std::noop_coroutine(); + +// std::cout << "Wakeup @: "; +// for (auto e : tasks) +// std::cout << e.when << ' '; +// std::cout << '\n'; + + auto e = tasks.front(); + if (e.when > jiffies) + return std::noop_coroutine(); + + tasks.pop_front(); + return e.h; + } + + jiffies_scheduler(void) = default; + + void destroy(void) + { + if (not tasks.empty()) + std::cout << "Finishing early, cleaning up state of suspended tasks..." << std::endl; + + for (auto e : tasks) + e.h.destroy(); + } + + ~jiffies_scheduler() + { + destroy(); + } + + jiffies_scheduler(jiffies_scheduler&& old) + : tasks(std::move(old.tasks)) + {} + + jiffies_scheduler& operator =(jiffies_scheduler&& old) + { + destroy(); + tasks = std::move(old.tasks); + return *this; + } + + bool operator ()(void) noexcept + { + if (tasks.empty()) + return false; + + auto e = tasks.front(); + tasks.pop_front(); + + int t = e.when - jiffies; + std::cout << "Sleeping for " << t << " seconds\n"; + + ::sleep(t); + jiffies += t; + + e.h(); + + return true; + } + jiffies_timeout operator ()(int t) noexcept + { + return {*this, t + jiffies}; + } +} sleeper; + +struct fire_forget_coroutine +{ + struct promise_type + { + ~promise_type() {} + void get_return_object(void) {} + std::suspend_never initial_suspend(void) + { + //sleeper.schedule(std::coroutine_handle<promise_type>::from_promise(*this), 0); + return {}; + } + void return_void(void) {} + std::suspend_never final_suspend(void) noexcept + { +// sleeper(); + return {}; + } + void unhandled_exception(void) { std::terminate(); } + }; +}; + +fire_forget_coroutine counter3(int x) +{ + std::cout << jiffies << "| +" << x << '\n'; + co_await sleeper(x); + std::cout << jiffies << "| " << x << '\n'; + co_await sleeper(x); + std::cout << jiffies << "| ~" << x << '\n'; + co_return; +} +fire_forget_coroutine counter2(int x) +{ + std::cout << jiffies << ": +" << x << '\n'; + co_await sleeper(x); + std::cout << jiffies << ": ~" << x << '\n'; + co_return; +} + +fire_forget_coroutine counter() +{ + counter3(5); + counter2(5); + counter2(10); + + std::cout << jiffies << ":\n"; + co_await sleeper(1); + std::cout << jiffies << ":\n"; + + std::cout << " DONE" << std::endl; + co_return; +} + +int main() +{ + counter(); + + while (sleeper()) + std::cout << "event loop\n"; + + return 0; +} diff --git a/src/coro.cpp b/src/coro-unconditional-dispatch.cpp