File indexing completed on 2025-01-18 09:54:52
0001
0002
0003
0004
0005 #ifndef CPPCORO_ROUND_ROBIN_SCHEDULER_HPP_INCLUDED
0006 #define CPPCORO_ROUND_ROBIN_SCHEDULER_HPP_INCLUDED
0007
0008 #include <cppcoro/config.hpp>
0009
0010 #include <cppcoro/coroutine.hpp>
0011 #include <array>
0012 #include <cassert>
0013 #include <algorithm>
0014 #include <utility>
0015
0016 namespace cppcoro
0017 {
0018 #if CPPCORO_COMPILER_SUPPORTS_SYMMETRIC_TRANSFER
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 template<size_t N>
0031 class round_robin_scheduler
0032 {
0033 static_assert(
0034 N >= 2,
0035 "Round robin scheduler must be configured to support at least two coroutines");
0036
0037 class schedule_operation
0038 {
0039 public:
0040 explicit schedule_operation(round_robin_scheduler& s) noexcept : m_scheduler(s) {}
0041
0042 bool await_ready() noexcept
0043 {
0044 return false;
0045 }
0046
0047 cppcoro::coroutine_handle<> await_suspend(
0048 cppcoro::coroutine_handle<> awaitingCoroutine) noexcept
0049 {
0050 return m_scheduler.exchange_next(awaitingCoroutine);
0051 }
0052
0053 void await_resume() noexcept {}
0054
0055 private:
0056 round_robin_scheduler& m_scheduler;
0057 };
0058
0059 friend class schedule_operation;
0060
0061 public:
0062 round_robin_scheduler() noexcept
0063 : m_index(0)
0064 , m_noop(cppcoro::noop_coroutine())
0065 {
0066 for (size_t i = 0; i < N - 1; ++i)
0067 {
0068 m_coroutines[i] = m_noop();
0069 }
0070 }
0071
0072 ~round_robin_scheduler()
0073 {
0074
0075 assert(std::all_of(
0076 m_coroutines.begin(),
0077 m_coroutines.end(),
0078 [&](auto h) { return h == m_noop; }));
0079 }
0080
0081 schedule_operation schedule() noexcept
0082 {
0083 return schedule_operation{ *this };
0084 }
0085
0086
0087 void drain() noexcept
0088 {
0089 size_t countRemaining = N - 1;
0090 do
0091 {
0092 auto nextToResume = exchange_next(m_noop);
0093 if (nextToResume != m_noop)
0094 {
0095 nextToResume.resume();
0096 countRemaining = N - 1;
0097 }
0098 else
0099 {
0100 --countRemaining;
0101 }
0102 } while (countRemaining > 0);
0103 }
0104
0105 private:
0106
0107 cppcoro::coroutine_handle exchange_next(
0108 cppcoro::coroutine_handle<> coroutine) noexcept
0109 {
0110 auto coroutineToResume = std::exchange(
0111 m_scheduler.m_coroutines[m_scheduler.m_index],
0112 awaitingCoroutine);
0113 m_scheduler.m_index = m_scheduler.m_index < (N - 2) ? m_scheduler.m_index + 1 : 0;
0114 return coroutineToResume;
0115 }
0116
0117 size_t m_index;
0118 const cppcoro::coroutine_handle<> m_noop;
0119 std::array<cppcoro::coroutine_handle<>, N - 1> m_coroutines;
0120 };
0121 #endif
0122 }
0123
0124 #endif