version 0.4
observer.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2024 The Ikarus Developers mueller@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
9#pragma once
10#include <map>
11#include <memory>
12
13#include <Eigen/Core>
14
16namespace Ikarus {
17
24 template <typename MessageType>
25 class IObserver {
26 public:
28 virtual ~IObserver() = default;
29
34 void update(MessageType message) {
35 checkMessageType(message);
36 updateImpl(message);
37 }
38
44 void update(MessageType message, double val) {
45 checkMessageType(message);
46 updateImpl(message, val);
47 }
48
54 void update(MessageType message, int val) {
55 checkMessageType(message);
56 updateImpl(message, val);
57 };
58
64 void update(MessageType message, const std::string& val) {
65 checkMessageType(message);
66 updateImpl(message, val);
67 };
68
75 void update(MessageType message, int val1, double val2) {
76 checkMessageType(message);
77 updateImpl(message, val1, val2);
78 };
79
86 void update(MessageType message, int val1, const std::string& val2) {
87 checkMessageType(message);
88 updateImpl(message, val1, val2);
89 };
90
96 void update(MessageType message, const Eigen::VectorXd& vec) {
97 checkMessageType(message);
98 updateImpl(message, vec);
99 }
100
101 protected:
102 virtual void updateImpl([[maybe_unused]] MessageType message){};
103 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] double val){};
104 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] int val){};
105 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] const std::string& val){};
106 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] int val1, const std::string& val2){};
107 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] int val1, double val2){};
108 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] const Eigen::VectorXd& vec) {}
109
110 private:
111 void checkMessageType(MessageType message) {
112 if (MessageType::END == message) DUNE_THROW(Dune::InvalidStateException, "The END enum type should not be used");
113 if (MessageType::BEGIN == message)
114 DUNE_THROW(Dune::InvalidStateException, "The BEGIN enum type should not be used");
115 }
116 };
117
124 template <typename MessageType>
126 public:
128 for (MessageType msg = MessageType::BEGIN; msg != MessageType::END; Ikarus::increment(msg))
129 messages_.push_back(msg);
130 }
131 virtual ~IObservable() = default;
137 void subscribe(MessageType message, std::shared_ptr<IObserver<MessageType>> observer);
142 void subscribeAll(std::shared_ptr<IObserver<MessageType>> observer);
147 void subscribeAll(std::initializer_list<std::shared_ptr<IObserver<MessageType>>> observers);
153 void unSubscribe(MessageType message, std::shared_ptr<IObserver<MessageType>> observer);
158 void unSubscribeAll(std::shared_ptr<IObserver<MessageType>> observer);
163 void notify(MessageType message);
164
171 template <std::floating_point ScalarType>
172 void notify(MessageType message, ScalarType val);
173
179 void notify(MessageType message, int val);
180
186 void notify(MessageType message, const std::string& val);
187
194 void notify(MessageType message, int val1, double val2);
195
202 void notify(MessageType message, int val1, const std::string& val2);
203
210 template <std::floating_point ScalarType>
211 void notify(MessageType message, Eigen::VectorX<ScalarType> vec);
212
213 private:
214 using ObserverVector = std::vector<std::shared_ptr<IObserver<MessageType>>>;
215 using ObserverMap = std::map<MessageType, ObserverVector>;
216 ObserverMap observers_;
217 std::vector<MessageType> messages_;
218 };
219
220 template <typename MessageType>
221 void IObservable<MessageType>::subscribe(MessageType message, std::shared_ptr<IObserver<MessageType>> observer) {
222 observers_[message];
223 auto&& vectorOfObserversOfASpecificMessage = observers_[message];
224 vectorOfObserversOfASpecificMessage.push_back(observer);
225 }
226
227 template <typename MessageType>
229 for (auto& msg : messages_)
230 subscribe(msg, observer);
231 }
232
233 template <typename MessageType>
235 std::initializer_list<std::shared_ptr<IObserver<MessageType>>> observers) {
236 for (auto& observer : observers)
237 for (auto& msg : messages_)
238 subscribe(msg, observer);
239 }
240
241 template <typename MessageType>
242 void IObservable<MessageType>::unSubscribe(MessageType message, std::shared_ptr<IObserver<MessageType>> observer) {
243 auto vectorOfObserversOfASpecificMessage = observers_[message];
244 std::ranges::remove_if(vectorOfObserversOfASpecificMessage, [&observer](auto&& obs) { return obs == observer; });
245 }
246
247 template <typename MessageType>
249 for (auto& msg : messages_)
250 unSubscribe(msg, observer);
251 }
252
253 template <typename MessageType>
254 void IObservable<MessageType>::notify(MessageType message) {
255 auto vectorOfObserversOfASpecificMessage = observers_[message];
256 for (auto&& obs : vectorOfObserversOfASpecificMessage)
257 obs->update(message);
258 }
259
260 template <typename MessageType>
261 template <std::floating_point ScalarType>
262 void IObservable<MessageType>::notify(MessageType message, ScalarType val) {
263 auto vectorOfObserversOfASpecificMessage = observers_[message];
264 for (auto&& obs : vectorOfObserversOfASpecificMessage)
265 obs->update(message, val);
266 }
267
268 template <typename MessageType>
269 void IObservable<MessageType>::notify(MessageType message, int val) {
270 auto vectorOfObserversOfASpecificMessage = observers_[message];
271 for (auto&& obs : vectorOfObserversOfASpecificMessage)
272 obs->update(message, val);
273 }
274
275 template <typename MessageType>
276 void IObservable<MessageType>::notify(MessageType message, const std::string& val) {
277 auto vectorOfObserversOfASpecificMessage = observers_[message];
278 for (auto&& obs : vectorOfObserversOfASpecificMessage)
279 obs->update(message, val);
280 }
281
282 template <typename MessageType>
283 void IObservable<MessageType>::notify(MessageType message, int val1, double val2) {
284 auto vectorOfObserversOfASpecificMessage = observers_[message];
285 for (auto&& obs : vectorOfObserversOfASpecificMessage)
286 obs->update(message, val1, val2);
287 }
288
289 template <typename MessageType>
290 void IObservable<MessageType>::notify(MessageType message, int val1, const std::string& val2) {
291 auto vectorOfObserversOfASpecificMessage = observers_[message];
292 for (auto&& obs : vectorOfObserversOfASpecificMessage)
293 obs->update(message, val1, val2);
294 }
295
296 template <typename MessageType>
297 template <std::floating_point ScalarType>
298 void IObservable<MessageType>::notify(MessageType message, Eigen::VectorX<ScalarType> vec) {
299 auto vectorOfObserversOfASpecificMessage = observers_[message];
300 for (auto&& obs : vectorOfObserversOfASpecificMessage)
301 obs->update(message, vec);
302 }
303} // namespace Ikarus
Implementation of the make enum macro.
MessageType & increment(MessageType &e)
Increments the given enum value.
Definition: makeenum.hh:63
Definition: simpleassemblers.hh:21
Generic observer interface for the Observer design pattern. See for a description of the design patt...
Definition: observer.hh:25
void update(MessageType message, const std::string &val)
Update method for receiving notifications with a message and a string value.
Definition: observer.hh:64
void update(MessageType message, double val)
Update method for receiving notifications with a message and a double value.
Definition: observer.hh:44
void update(MessageType message, const Eigen::VectorXd &vec)
Update method for receiving notifications with a message and an Eigen::VectorXd.
Definition: observer.hh:96
virtual void updateImpl(MessageType message)
Definition: observer.hh:102
virtual void updateImpl(MessageType message, const Eigen::VectorXd &vec)
Definition: observer.hh:108
virtual void updateImpl(MessageType message, int val1, double val2)
Definition: observer.hh:107
void update(MessageType message, int val1, const std::string &val2)
Update method for receiving notifications with a message, an integer value, and a string value.
Definition: observer.hh:86
virtual void updateImpl(MessageType message, double val)
Definition: observer.hh:103
void update(MessageType message)
Update method for receiving notifications with a message.
Definition: observer.hh:34
void update(MessageType message, int val)
Update method for receiving notifications with a message and an integer value.
Definition: observer.hh:54
void update(MessageType message, int val1, double val2)
Update method for receiving notifications with a message and two values (integer and double).
Definition: observer.hh:75
virtual void updateImpl(MessageType message, int val)
Definition: observer.hh:104
virtual void updateImpl(MessageType message, const std::string &val)
Definition: observer.hh:105
virtual void updateImpl(MessageType message, int val1, const std::string &val2)
Definition: observer.hh:106
virtual ~IObserver()=default
Virtual destructor for the observer interface.
Generic observable interface for the Observer design pattern. See for a description of the design pa...
Definition: observer.hh:125
void subscribeAll(std::initializer_list< std::shared_ptr< IObserver< MessageType > > > observers)
Subscribe multiple observers to receive notifications for all message types.
Definition: observer.hh:234
void subscribeAll(std::shared_ptr< IObserver< MessageType > > observer)
Subscribe an observer to receive notifications for all message types.
Definition: observer.hh:228
void notify(MessageType message, const std::string &val)
Notify observers about a specific message type with a string value.
Definition: observer.hh:276
void notify(MessageType message, int val)
Notify observers about a specific message type with an integer value.
Definition: observer.hh:269
void unSubscribe(MessageType message, std::shared_ptr< IObserver< MessageType > > observer)
Unsubscribe an observer from receiving notifications for a specific message type.
Definition: observer.hh:242
void notify(MessageType message)
Notify observers about a specific message type.
Definition: observer.hh:254
void unSubscribeAll(std::shared_ptr< IObserver< MessageType > > observer)
Unsubscribe an observer from receiving notifications for all message types.
Definition: observer.hh:248
void notify(MessageType message, int val1, const std::string &val2)
Notify observers about a specific message type with an integer value and a string value.
Definition: observer.hh:290
void notify(MessageType message, ScalarType val)
Notify observers about a specific message type with a floating-point value.
Definition: observer.hh:262
void notify(MessageType message, Eigen::VectorX< ScalarType > vec)
Notify observers about a specific message type with an Eigen::VectorX.
Definition: observer.hh:298
IObservable()
Definition: observer.hh:127
virtual ~IObservable()=default
void notify(MessageType message, int val1, double val2)
Notify observers about a specific message type with an integer and a double value.
Definition: observer.hh:283
void subscribe(MessageType message, std::shared_ptr< IObserver< MessageType > > observer)
Subscribe an observer to receive notifications for a specific message type.
Definition: observer.hh:221