coro-round-robin.cpp (2011B)
1 #include "coroutine_owner.hpp" 2 3 #include <iostream> 4 #include <deque> 5 6 struct round_robin_scheduler : std::suspend_always 7 { 8 std::deque<coroutine_owner<>> tasks; 9 10 bool await_ready(void) const noexcept 11 { 12 return tasks.empty(); 13 } 14 15 void schedule(std::coroutine_handle<> h) 16 { 17 tasks.push_back(coroutine_owner<>{h}); 18 } 19 20 std::coroutine_handle<> next(void) noexcept 21 { 22 auto h = tasks.front().release(); 23 tasks.pop_front(); 24 return h; 25 } 26 27 std::coroutine_handle<> await_suspend(std::coroutine_handle<> h) 28 { 29 schedule(h); 30 return next(); 31 } 32 33 round_robin_scheduler(void) = default; 34 35 void destroy(void) 36 { 37 if (not tasks.empty()) 38 std::cout << "Finishing early, cleaning up state of suspended tasks..." << std::endl; 39 } 40 41 ~round_robin_scheduler() 42 { 43 destroy(); 44 } 45 46 round_robin_scheduler(round_robin_scheduler&& old) 47 : tasks(std::move(old.tasks)) 48 {} 49 50 round_robin_scheduler& operator =(round_robin_scheduler&& old) 51 { 52 destroy(); 53 tasks = std::move(old.tasks); 54 return *this; 55 } 56 57 bool operator ()(void) noexcept 58 { 59 if (tasks.empty()) 60 return false; 61 62 next()(); 63 return true; 64 } 65 } round_robin; 66 67 struct fire_forget_coroutine 68 { 69 struct promise_type 70 { 71 ~promise_type() {} 72 void get_return_object(void) {} 73 std::suspend_always initial_suspend(void) 74 { 75 round_robin.schedule(std::coroutine_handle<promise_type>::from_promise(*this)); 76 return {}; 77 } 78 void return_void(void) {} 79 std::suspend_never final_suspend(void) noexcept 80 { 81 round_robin(); 82 return {}; 83 } 84 void unhandled_exception(void) { std::terminate(); } 85 }; 86 }; 87 88 struct state 89 { 90 ~state() 91 { 92 std::cout << " ~state()" << std::endl; 93 } 94 }; 95 96 fire_forget_coroutine counter(int from, int to) 97 { 98 state s; 99 100 for (int i = from;; ++i) 101 { 102 std::cout << "counter [" << from << ',' << to << "): " << i; 103 if (i >= to) 104 break; 105 std::cout << std::endl; 106 co_await round_robin; 107 } 108 std::cout << " DONE" << std::endl; 109 co_return; 110 } 111 112 int main() 113 { 114 counter(1,3); 115 counter(4,5); 116 counter(0,7); 117 118 round_robin(); 119 120 return 0; 121 }