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 <algorithm>
7 #include <vector>
8 #include <cassert>
9 
10 namespace openmsx {
11 
16 template <typename T> class Subject
17 {
18 public:
19  void attach(Observer<T>& observer);
20  void detach(Observer<T>& observer);
21 
22 protected:
23  Subject();
24  ~Subject();
25  void notify() const;
26 
27 private:
28  std::vector<Observer<T>*> observers;
29 #ifndef NDEBUG
30  mutable bool notifyInProgress;
31 #endif
32 };
33 
34 template <typename T> Subject<T>::Subject()
35 #ifndef NDEBUG
36  : notifyInProgress(false)
37 #endif
38 {
39 }
40 
41 template <typename T> Subject<T>::~Subject()
42 {
43  assert(!notifyInProgress);
44  auto copy = observers;
45  for (auto& o : copy) {
46  o->subjectDeleted(*static_cast<const T*>(this));
47  }
48  assert(observers.empty());
49 }
50 
51 template <typename T> void Subject<T>::attach(Observer<T>& observer)
52 {
53  assert(!notifyInProgress);
54  observers.push_back(&observer);
55 }
56 
57 template <typename T> void Subject<T>::detach(Observer<T>& observer)
58 {
59  assert(!notifyInProgress);
60  auto it = find(observers.begin(), observers.end(), &observer);
61  assert(it != observers.end());
62  observers.erase(it);
63 }
64 
65 template <typename T> void Subject<T>::notify() const
66 {
67 #ifndef NDEBUG
68  assert(!notifyInProgress);
69  ScopedAssign<bool> sa(notifyInProgress, true);
70 #endif
71 
72  for (auto& o : observers) {
73  o->update(*static_cast<const T*>(this));
74  }
75 }
76 
77 } // namespace openmsx
78 
79 #endif