AMDiS  2.10
The Adaptive Multi-Dimensional Simulation Toolbox
Observer.hpp
1 #pragma once
2 
3 #include <list>
4 #include <utility>
5 
6 #include <amdis/Output.hpp>
7 #include <amdis/common/ConceptsBase.hpp>
8 #include <amdis/common/Index.hpp>
9 #include <amdis/common/TypeTraits.hpp>
10 
11 namespace AMDiS
12 {
13  namespace event
14  {
19  struct preAdapt { bool value = true; };
20 
25  struct adapt { bool value = true; };
26 
30  struct postAdapt {};
31  }
32 
33 
34  template <class Event>
36  {
37  public:
38  virtual ~ObserverInterface() = default;
39  virtual void update(Event e) = 0;
40  virtual void unset() = 0;
41  };
42 
43 
45 
53  template <class Event, class... Events>
54  class Notifier
55  : public Notifier<Event>
56  , public Notifier<Events...>
57  {
58  public:
60  using Notifier<Events...>::notify;
61  };
62 
63  template <class Event>
64  class Notifier<Event>
65  {
66  public:
67  virtual ~Notifier()
68  {
69  // Remove remaining pointers to this to avoid segfaults
70  for (ObserverInterface<Event>* o : observers_)
71  o->unset();
72  }
73 
75  void notify(Event const& e)
76  {
77  for (ObserverInterface<Event>* o : observers_)
78  o->update(e);
79  }
80 
83  {
84  // insert only if not yet in the list
85  if (std::find(observers_.begin(), observers_.end(), o) == observers_.end())
86  observers_.push_back(o);
87  }
88 
91  {
92  observers_.remove(o);
93  }
94 
95  private:
96  std::list<ObserverInterface<Event>*> observers_;
97  };
98 
99 
101  template <class Event, class... Tags>
102  class Observer
103  : public ObserverInterface<Event>
104  {
105  public:
106  template <class N,
107  REQUIRES(std::is_base_of_v<Notifier<Event>,N>)>
108  Observer(N const& notifier)
109  : notifier_(const_cast<N*>(&notifier))
110  {
111  notifier_->attach(this);
112  }
113 
114  template <class N,
115  REQUIRES(not std::is_base_of_v<Notifier<Event>,N>)>
116  Observer(N const& notifier)
117  {
118  warning("Ignoring Notifier. Use AdaptiveGrid wrapper.");
119  }
120 
121 
123  virtual ~Observer()
124  {
125  if (notifier_)
126  notifier_->detach(this);
127  }
128 
130  Observer(Observer const& other)
131  : notifier_(other.notifier_)
132  {
133  notifier_->attach(this);
134  }
135 
137  Observer& operator=(Observer const& other)
138  {
139  if (&other != this) {
140  notifier_->detach(this);
141  notifier_ = other.notifier_;
142  notifier_->attach(this);
143  }
144  return *this;
145  }
146 
149  void unset() final
150  {
151  notifier_ = nullptr;
152  }
153 
156  void update(Event e) final
157  {
158  updateImpl(e, Tags{}...);
159  }
160 
161  protected:
163  // NOTE: The additional `Tags...` arguments can be used to distinguish
164  // between multiple observers of the same event.
165  virtual void updateImpl(Event e, Tags...) = 0;
166 
167  private:
168  Notifier<Event>* notifier_ = nullptr;
169  };
170 
171 
172  namespace Impl
173  {
174  template <class Event, class Tags>
175  class ObserverSequenceImpl;
176 
178  template <class Event, std::size_t... Is>
179  class ObserverSequenceImpl<Event, std::index_sequence<Is...>>
180  : private Observer<Event,index_t<Is>>...
181  {
182  public:
183  template <class... Notifiers,
184  REQUIRES(sizeof...(Notifiers) == sizeof...(Is))>
185  ObserverSequenceImpl(Notifiers&&... notifiers)
186  : Observer<Event,index_t<Is>>(FWD(notifiers))...
187  {}
188  };
189 
190  } // end namespace Impl
191 
192  template <class Event, std::size_t N>
193  using ObserverSequence = Impl::ObserverSequenceImpl<Event, std::make_index_sequence<N>>;
194 
195 } // end namespace AMDiS
Definition: Observer.hpp:35
void attach(ObserverInterface< Event > *o)
Attach a new observer that gets called on notify.
Definition: Observer.hpp:82
Definition: AdaptBase.hpp:6
Implementation of the ObserverInterface.
Definition: Observer.hpp:102
Observer & operator=(Observer const &other)
Copy-assignment operator, copies the notifier and attaches this.
Definition: Observer.hpp:137
Definition: Observer.hpp:64
virtual ~Observer()
Destructor, detaches from the notifier.
Definition: Observer.hpp:123
Definition: Observer.hpp:25
Definition: Observer.hpp:30
Mixin for signaling of certain events.
Definition: Observer.hpp:54
void update(Event e) final
Definition: Observer.hpp:156
void detach(ObserverInterface< Event > *o)
Detaches the passed observer from the list, if stored.
Definition: Observer.hpp:90
Observer(Observer const &other)
Copy constructor. Attaches this to the copied notifier.
Definition: Observer.hpp:130
void notify(Event const &e)
Call the update method on all attached observers.
Definition: Observer.hpp:75
Definition: Observer.hpp:19
void unset() final
Definition: Observer.hpp:149