AMDiS  0.1
The Adaptive Multi-Dimensional Simulation Toolbox
Observer.hpp
1 #pragma once
2 
3 #include <set>
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  observers_.insert(o);
85  }
86 
89  {
90  observers_.erase(o);
91  }
92 
93  private:
94  std::set<ObserverInterface<Event>*> observers_;
95  };
96 
97 
99  template <class Event, class... Tags>
100  class Observer
101  : public ObserverInterface<Event>
102  {
103  public:
104  template <class N,
105  REQUIRES(std::is_base_of_v<Notifier<Event>,N>)>
106  Observer(N const& notifier)
107  : notifier_(const_cast<N*>(&notifier))
108  {
109  notifier_->attach(this);
110  }
111 
112  template <class N,
113  REQUIRES(not std::is_base_of_v<Notifier<Event>,N>)>
114  Observer(N const& notifier)
115  {
116  warning("Ignoring Notifier. Use AdaptiveGrid wrapper.");
117  }
118 
119 
121  virtual ~Observer()
122  {
123  if (notifier_)
124  notifier_->detach(this);
125  }
126 
128  Observer(Observer const& other)
129  : notifier_(other.notifier_)
130  {
131  notifier_->attach(this);
132  }
133 
135  Observer& operator=(Observer const& other)
136  {
137  if (&other != this) {
138  notifier_->detach(this);
139  notifier_ = other.notifier_;
140  notifier_->attach(this);
141  }
142  return *this;
143  }
144 
147  void unset() final
148  {
149  notifier_ = nullptr;
150  }
151 
154  void update(Event e) final
155  {
156  updateImpl(e, Tags{}...);
157  }
158 
159  protected:
161  // NOTE: The additional `Tags...` arguments can be used to distinguish
162  // between multiple observers of the same event.
163  virtual void updateImpl(Event e, Tags...) = 0;
164 
165  private:
166  Notifier<Event>* notifier_ = nullptr;
167  };
168 
169 
170  namespace Impl
171  {
172  template <class Event, class Tags>
173  class ObserverSequenceImpl;
174 
176  template <class Event, std::size_t... Is>
177  class ObserverSequenceImpl<Event, std::index_sequence<Is...>>
178  : private Observer<Event,index_t<Is>>...
179  {
180  public:
181  template <class... Notifiers,
182  REQUIRES(sizeof...(Notifiers) == sizeof...(Is))>
183  ObserverSequenceImpl(Notifiers&&... notifiers)
184  : Observer<Event,index_t<Is>>(FWD(notifiers))...
185  {}
186  };
187 
188  } // end namespace Impl
189 
190  template <class Event, std::size_t N>
191  using ObserverSequence = Impl::ObserverSequenceImpl<Event, std::make_index_sequence<N>>;
192 
193 } // 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
Contains all classes needed for solving linear and non linear equation systems.
Definition: AdaptBase.hpp:6
Implementation of the ObserverInterface.
Definition: Observer.hpp:100
Observer & operator=(Observer const &other)
Copy-assignment operator, copies the notifier and attaches this.
Definition: Observer.hpp:135
Definition: Observer.hpp:64
virtual ~Observer()
Destructor, detaches from the notifier.
Definition: Observer.hpp:121
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:154
void detach(ObserverInterface< Event > *o)
Detaches the passed observer from the list, if stored.
Definition: Observer.hpp:88
Observer(Observer const &other)
Copy constructor. Attaches this to the copied notifier.
Definition: Observer.hpp:128
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:147