RTScheduler.cc 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #include "RTScheduler.hh"
  2. #include "RTSchedulable.hh"
  3. #include <algorithm>
  4. #include <limits>
  5. #include <iterator>
  6. namespace openmsx {
  7. struct EqualRTSchedulable {
  8. explicit EqualRTSchedulable(const RTSchedulable& schedulable_)
  9. : schedulable(schedulable_) {}
  10. bool operator()(const RTSyncPoint& sp) const {
  11. return sp.schedulable == &schedulable;
  12. }
  13. const RTSchedulable& schedulable;
  14. };
  15. void RTScheduler::add(uint64_t delta, RTSchedulable& schedulable)
  16. {
  17. queue.insert(RTSyncPoint{Timer::getTime() + delta, &schedulable},
  18. [](RTSyncPoint& sp) {
  19. sp.time = std::numeric_limits<uint64_t>::max(); },
  20. [](const RTSyncPoint& x, const RTSyncPoint& y) {
  21. return x.time < y.time; });
  22. }
  23. bool RTScheduler::remove(RTSchedulable& schedulable)
  24. {
  25. return queue.remove(EqualRTSchedulable(schedulable));
  26. }
  27. bool RTScheduler::isPending(const RTSchedulable& schedulable) const
  28. {
  29. return std::find_if(std::begin(queue), std::end(queue),
  30. EqualRTSchedulable(schedulable)) != std::end(queue);
  31. }
  32. void RTScheduler::scheduleHelper(uint64_t limit)
  33. {
  34. // Process at most this many events to prevent getting stuck in an
  35. // infinite loop when a RTSchedulable keeps on rescheduling itself in
  36. // the (too) near future.
  37. auto count = queue.size();
  38. while (true) {
  39. auto* schedulable = queue.front().schedulable;
  40. queue.remove_front();
  41. schedulable->executeRT();
  42. // It's possible RTSchedulables are canceled in the mean time,
  43. // so we can't rely on 'count' to replace this empty check.
  44. if (queue.empty()) break;
  45. if (likely(queue.front().time > limit)) break;
  46. if (--count == 0) break;
  47. }
  48. }
  49. } // namespace openmsx