openMSX
Subject.hh
Go to the documentation of this file.
1 #ifndef SUBJECT_HH
2 #define SUBJECT_HH
3 
4 #include "Observer.hh"
5 #include "ScopedAssign.hh"
6 #include "stl.hh"
7 #include <algorithm>
8 #include <vector>
9 #include <cassert>
10 
11 namespace openmsx {
12 
17 template <typename T> class Subject
18 {
19 public:
20  void attach(Observer<T>& observer);
21  void detach(Observer<T>& observer);
22 
23 protected:
24  Subject() = default;
25  ~Subject();
26  void notify() const;
27 
28 private:
29  std::vector<Observer<T>*> observers; // unordered
30 #ifndef NDEBUG
31  mutable bool notifyInProgress = false;
32 #endif
33 };
34 
35 template <typename T> Subject<T>::~Subject()
36 {
37  assert(!notifyInProgress);
38  auto copy = observers;
39  for (auto& o : copy) {
40  o->subjectDeleted(*static_cast<const T*>(this));
41  }
42  assert(observers.empty());
43 }
44 
45 template <typename T> void Subject<T>::attach(Observer<T>& observer)
46 {
47  assert(!notifyInProgress);
48  observers.push_back(&observer);
49 }
50 
51 template <typename T> void Subject<T>::detach(Observer<T>& observer)
52 {
53  assert(!notifyInProgress);
54  move_pop_back(observers, rfind_unguarded(observers, &observer));
55 }
56 
57 template <typename T> void Subject<T>::notify() const
58 {
59 #ifndef NDEBUG
60  assert(!notifyInProgress);
61  ScopedAssign<bool> sa(notifyInProgress, true);
62 #endif
63 
64  for (auto& o : observers) {
65  o->update(*static_cast<const T*>(this));
66  }
67 }
68 
69 } // namespace openmsx
70 
71 #endif
auto copy(InputRange &&range, OutputIter out)
Definition: ranges.hh:149
void notify() const
Definition: Subject.hh:57
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
Definition: stl.hh:191
void attach(Observer< T > &observer)
Definition: Subject.hh:45
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
Generic Gang-of-Four Subject class of the Observer pattern, templatized edition.
Definition: Subject.hh:17
void detach(Observer< T > &observer)
Definition: Subject.hh:51
Generic Gang-of-Four Observer class, templatized edition.
Definition: Observer.hh:9
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
Subject()=default
Assign new value to some variable and restore the original value when this object goes out of scope...
Definition: ScopedAssign.hh:7