openMSX
StateChangeDistributor.cc
Go to the documentation of this file.
2 #include "StateChangeListener.hh"
3 #include "StateChange.hh"
4 #include "stl.hh"
5 #include <algorithm>
6 #include <cassert>
7 
8 namespace openmsx {
9 
11 {
12  assert(listeners.empty());
13 }
14 
15 bool StateChangeDistributor::isRegistered(StateChangeListener* listener) const
16 {
17  return contains(listeners, listener);
18 }
19 
21 {
22  assert(!isRegistered(&listener));
23  listeners.push_back(&listener);
24 }
25 
27 {
28  move_pop_back(listeners, rfind_unguarded(listeners, &listener));
29 }
30 
32 {
33  assert(!recorder);
34  recorder = &recorder_;
35 }
36 
38 {
39  (void)recorder_;
40  assert(recorder == &recorder_);
41  recorder = nullptr;
42 }
43 
45 {
46  if (viewOnlyMode && isReplaying()) return;
47 
48  if (isReplaying()) {
49  stopReplay(event->getTime());
50  }
51  distribute(event);
52 }
53 
55 {
56  assert(isReplaying());
57  distribute(event);
58 }
59 
60 void StateChangeDistributor::distribute(const EventPtr& event)
61 {
62  // Iterate over a copy because signalStateChange() may indirect call
63  // back into registerListener().
64  // e.g. signalStateChange() -> .. -> PlugCmd::execute() -> .. ->
65  // Connector::plug() -> .. -> Joystick::plugHelper() ->
66  // registerListener()
67  if (recorder) recorder->signalStateChange(event);
68  auto copy = listeners;
69  for (auto& l : copy) {
70  if (isRegistered(l)) {
71  // it's possible the listener unregistered itself
72  // (but is still present in the copy)
73  l->signalStateChange(event);
74  }
75  }
76 }
77 
78 void StateChangeDistributor::stopReplay(EmuTime::param time)
79 {
80  if (!isReplaying()) return;
81 
82  if (recorder) recorder->stopReplay(time);
83  for (auto& l : listeners) {
84  l->stopReplay(time);
85  }
86 }
87 
89 {
90  if (recorder) {
91  return recorder->isReplaying();
92  }
93  return false;
94 }
95 
96 } // namespace openmsx
auto copy(InputRange &&range, OutputIter out)
Definition: ranges.hh:149
void unregisterListener(StateChangeListener &listener)
bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
Definition: stl.hh:106
void distributeNew(const EventPtr &event)
Deliver the event to all registered listeners MSX input devices should call the distributeNew() versi...
void registerListener(StateChangeListener &listener)
(Un)registers the given object to receive state change events.
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
Definition: stl.hh:191
void stopReplay(EmuTime::param time)
Explicitly stop replay.
std::shared_ptr< StateChange > EventPtr
void unregisterRecorder(StateChangeRecorder &recorder)
void registerRecorder(StateChangeRecorder &recorder)
(Un)registers the given object to receive state change events.
virtual bool isReplaying() const =0
void distributeReplay(const EventPtr &event)
virtual void signalStateChange(const std::shared_ptr< StateChange > &event)=0
This method gets called when a StateChange event occurs.
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
virtual void stopReplay(EmuTime::param time)=0
This method gets called when we switch from replayed events to live events.
auto rfind_unguarded(RANGE &range, const VAL &val)
Similar to the find(_if)_unguarded functions above, but searches from the back to front...
Definition: stl.hh:166