openMSX
Scheduler.cc
Go to the documentation of this file.
1 #include "Scheduler.hh"
2 #include "Schedulable.hh"
3 #include "Thread.hh"
4 #include "MSXCPU.hh"
5 #include "serialize.hh"
6 #include <cassert>
7 #include <algorithm>
8 #include <iterator> // for back_inserter
9 
10 namespace openmsx {
11 
13  EqualSchedulable(const Schedulable& schedulable_)
14  : schedulable(schedulable_) {}
15  bool operator()(const SynchronizationPoint& sp) const {
16  return sp.getDevice() == &schedulable;
17  }
19 };
20 
21 
23  : scheduleTime(EmuTime::zero)
24  , cpu(nullptr)
25  , scheduleInProgress(false)
26 {
27 }
28 
30 {
31  assert(!cpu);
32  SyncPoints copy(std::begin(queue), std::end(queue));
33  for (auto& s : copy) {
34  s.getDevice()->schedulerDeleted();
35  }
36 
37  assert(queue.empty());
38 }
39 
40 void Scheduler::setSyncPoint(EmuTime::param time, Schedulable& device)
41 {
42  assert(Thread::isMainThread());
43  assert(time >= scheduleTime);
44 
45  // Push sync point into queue.
46  queue.insert(SynchronizationPoint(time, &device),
48  [](const SynchronizationPoint& x, const SynchronizationPoint& y) {
49  return x.getTime() < y.getTime(); });
50 
51  if (!scheduleInProgress && cpu) {
52  // only when scheduleHelper() is not being executed
53  // otherwise getNext() doesn't return the correct time and
54  // scheduleHelper() anyway calls setNextSyncPoint() at the end
55  cpu->setNextSyncPoint(getNext());
56  }
57 }
58 
59 Scheduler::SyncPoints Scheduler::getSyncPoints(const Schedulable& device) const
60 {
61  SyncPoints result;
62  copy_if(std::begin(queue), std::end(queue), back_inserter(result),
63  EqualSchedulable(device));
64  return result;
65 }
66 
67 bool Scheduler::removeSyncPoint(Schedulable& device)
68 {
69  assert(Thread::isMainThread());
70  return queue.remove(EqualSchedulable(device));
71 }
72 
73 void Scheduler::removeSyncPoints(Schedulable& device)
74 {
75  assert(Thread::isMainThread());
76  queue.remove_all(EqualSchedulable(device));
77 }
78 
79 bool Scheduler::pendingSyncPoint(const Schedulable& device,
80  EmuTime& result) const
81 {
82  assert(Thread::isMainThread());
83  auto it = std::find_if(std::begin(queue), std::end(queue),
84  EqualSchedulable(device));
85  if (it != std::end(queue)) {
86  result = it->getTime();
87  return true;
88  } else {
89  return false;
90  }
91 }
92 
94 {
95  assert(Thread::isMainThread());
96  return scheduleTime;
97 }
98 
99 void Scheduler::scheduleHelper(EmuTime::param limit, EmuTime next)
100 {
101  assert(!scheduleInProgress);
102  scheduleInProgress = true;
103  while (true) {
104  assert(scheduleTime <= next);
105  scheduleTime = next;
106 
107  const auto& sp = queue.front();
108  auto* device = sp.getDevice();
109 
110  queue.remove_front();
111 
112  device->executeUntil(next);
113 
114  next = getNext();
115  if (likely(next > limit)) break;
116  }
117  scheduleInProgress = false;
118 
119  cpu->setNextSyncPoint(next);
120 }
121 
122 
123 template <typename Archive>
124 void SynchronizationPoint::serialize(Archive& ar, unsigned /*version*/)
125 {
126  // SynchronizationPoint is always serialized via Schedulable. A
127  // Schedulable has a collection of SynchronizationPoints, all with the
128  // same Schedulable. So there's no need to serialize 'device'.
129  //Schedulable* device;
130  ar.serialize("time", timeStamp);
131 }
133 
134 template <typename Archive>
135 void Scheduler::serialize(Archive& ar, unsigned /*version*/)
136 {
137  ar.serialize("currentTime", scheduleTime);
138  // don't serialize 'queue', each Schedulable serializes its own
139  // syncpoints
140 }
142 
143 } // namespace openmsx
string_ref::const_iterator end(const string_ref &x)
Definition: string_ref.hh:150
EqualSchedulable(const Schedulable &schedulable_)
Definition: Scheduler.cc:13
void serialize(Archive &ar, unsigned version)
Definition: Scheduler.cc:135
void setNextSyncPoint(EmuTime::param time)
Definition: MSXCPU.cc:135
bool operator()(const SynchronizationPoint &sp) const
Definition: Scheduler.cc:15
SynchronizationPoint
Definition: Scheduler.cc:132
EmuTime::param getNext() const
TODO.
Definition: Scheduler.hh:56
void setTime(EmuTime::param time)
Definition: Scheduler.hh:23
Every class that wants to get scheduled at some point must inherit from this class.
Definition: Schedulable.hh:34
Schedulable * getDevice() const
Definition: Scheduler.hh:24
EmuTime::param getCurrentTime() const
Get the current scheduler time.
Definition: Scheduler.cc:93
std::vector< SynchronizationPoint > SyncPoints
Definition: Scheduler.hh:38
void serialize(Archive &ar, unsigned version)
Definition: Scheduler.cc:124
static const EmuTime infinity
Definition: EmuTime.hh:58
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
const Schedulable & schedulable
Definition: Scheduler.cc:18
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:802
#define likely(x)
Definition: likely.hh:14
string_ref::const_iterator begin(const string_ref &x)
Definition: string_ref.hh:149
static bool isMainThread()
Returns true when called from the main thread.
Definition: Thread.cc:19