Scheduler.hh 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #ifndef SCHEDULER_HH
  2. #define SCHEDULER_HH
  3. #include "EmuTime.hh"
  4. #include "SchedulerQueue.hh"
  5. #include "likely.hh"
  6. #include <vector>
  7. namespace openmsx {
  8. class Schedulable;
  9. class MSXCPU;
  10. class SynchronizationPoint
  11. {
  12. public:
  13. SynchronizationPoint() = default;
  14. SynchronizationPoint(EmuTime::param time, Schedulable* dev)
  15. : timeStamp(time), device(dev) {}
  16. EmuTime::param getTime() const { return timeStamp; }
  17. void setTime(EmuTime::param time) { timeStamp = time; }
  18. Schedulable* getDevice() const { return device; }
  19. template <typename Archive>
  20. void serialize(Archive& ar, unsigned version);
  21. private:
  22. EmuTime timeStamp = EmuTime::zero();
  23. Schedulable* device = nullptr;
  24. };
  25. class Scheduler
  26. {
  27. public:
  28. using SyncPoints = std::vector<SynchronizationPoint>;
  29. Scheduler() = default;
  30. ~Scheduler();
  31. void setCPU(MSXCPU* cpu_)
  32. {
  33. cpu = cpu_;
  34. }
  35. /**
  36. * Get the current scheduler time.
  37. */
  38. EmuTime::param getCurrentTime() const;
  39. /**
  40. * TODO
  41. */
  42. inline EmuTime::param getNext() const
  43. {
  44. return queue.front().getTime();
  45. }
  46. /**
  47. * Schedule till a certain moment in time.
  48. */
  49. inline void schedule(EmuTime::param limit)
  50. {
  51. EmuTime next = getNext();
  52. if (unlikely(limit >= next)) {
  53. scheduleHelper(limit, next); // slow path not inlined
  54. }
  55. scheduleTime = limit;
  56. }
  57. template <typename Archive>
  58. void serialize(Archive& ar, unsigned version);
  59. private: // -> intended for Schedulable
  60. friend class Schedulable;
  61. /**
  62. * Register a syncPoint. When the emulation reaches "timestamp",
  63. * the executeUntil() method of "device" gets called.
  64. * SyncPoints are ordered: smaller EmuTime -> scheduled
  65. * earlier.
  66. * The supplied EmuTime may not be smaller than the current CPU
  67. * time.
  68. * A device may register several syncPoints.
  69. */
  70. void setSyncPoint(EmuTime::param timestamp, Schedulable& device);
  71. SyncPoints getSyncPoints(const Schedulable& device) const;
  72. /**
  73. * Removes a syncPoint of a given device.
  74. * If there is more than one match only one will be removed,
  75. * there is no guarantee that the earliest syncPoint is
  76. * removed.
  77. * Returns false <=> if there was no match (so nothing removed)
  78. */
  79. bool removeSyncPoint(Schedulable& device);
  80. /** Remove all syncpoints for the given device.
  81. */
  82. void removeSyncPoints(Schedulable& device);
  83. /**
  84. * Is there a pending syncPoint for this device?
  85. */
  86. bool pendingSyncPoint(const Schedulable& device, EmuTime& result) const;
  87. private:
  88. void scheduleHelper(EmuTime::param limit, EmuTime next);
  89. /** Vector used as heap, not a priority queue because that
  90. * doesn't allow removal of non-top element.
  91. */
  92. SchedulerQueue<SynchronizationPoint> queue;
  93. EmuTime scheduleTime = EmuTime::zero();
  94. MSXCPU* cpu = nullptr;
  95. bool scheduleInProgress = false;
  96. };
  97. } // namespace openmsx
  98. #endif