version 0.4.1
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
24template <typename MT>
26{
27public:
28 using MessageType = MT;
30 virtual ~IObserver() = default;
31
36 void update(MessageType message) {
37 checkMessageType(message);
38 updateImpl(message);
39 }
40
46 void update(MessageType message, double val) {
47 checkMessageType(message);
48 updateImpl(message, val);
49 }
50
56 void update(MessageType message, int val) {
57 checkMessageType(message);
58 updateImpl(message, val);
59 };
60
66 void update(MessageType message, const std::string& val) {
67 checkMessageType(message);
68 updateImpl(message, val);
69 };
70
77 void update(MessageType message, int val1, double val2) {
78 checkMessageType(message);
79 updateImpl(message, val1, val2);
80 };
81
88 void update(MessageType message, int val1, const std::string& val2) {
89 checkMessageType(message);
90 updateImpl(message, val1, val2);
91 };
92
98 void update(MessageType message, const Eigen::VectorXd& vec) {
99 checkMessageType(message);
100 updateImpl(message, vec);
101 }
102
103protected:
104 virtual void updateImpl([[maybe_unused]] MessageType message) {};
105 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] double val) {};
106 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] int val) {};
107 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] const std::string& val) {};
108 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] int val1, const std::string& val2) {};
109 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] int val1, double val2) {};
110 virtual void updateImpl([[maybe_unused]] MessageType message, [[maybe_unused]] const Eigen::VectorXd& vec) {}
111
112private:
113 void checkMessageType(MessageType message) {
114 if (MessageType::END == message)
115 DUNE_THROW(Dune::InvalidStateException, "The END enum type should not be used");
116 if (MessageType::BEGIN == message)
117 DUNE_THROW(Dune::InvalidStateException, "The BEGIN enum type should not be used");
118 }
119};
120
127template <typename MessageType>
129{
130public:
132 for (MessageType msg = MessageType::BEGIN; msg != MessageType::END; Ikarus::increment(msg))
133 messages_.push_back(msg);
134 }
135 virtual ~IObservable() = default;
141 void subscribe(MessageType message, std::shared_ptr<IObserver<MessageType>> observer);
146 void subscribeAll(std::shared_ptr<IObserver<MessageType>> observer);
151 void subscribeAll(std::initializer_list<std::shared_ptr<IObserver<MessageType>>> observers);
157 void unSubscribe(MessageType message, std::shared_ptr<IObserver<MessageType>> observer);
162 void unSubscribeAll(std::shared_ptr<IObserver<MessageType>> observer);
167 void notify(MessageType message);
168
175 template <std::floating_point ScalarType>
176 void notify(MessageType message, ScalarType val);
177
183 void notify(MessageType message, int val);
184
190 void notify(MessageType message, const std::string& val);
191
198 void notify(MessageType message, int val1, double val2);
199
206 void notify(MessageType message, int val1, const std::string& val2);
207
214 template <std::floating_point ScalarType>
215 void notify(MessageType message, Eigen::VectorX<ScalarType> vec);
216
217private:
218 using ObserverVector = std::vector<std::shared_ptr<IObserver<MessageType>>>;
219 using ObserverMap = std::map<MessageType, ObserverVector>;
220 ObserverMap observers_;
221 std::vector<MessageType> messages_;
222};
223
224template <typename MT>
225void IObservable<MT>::subscribe(MT message, std::shared_ptr<IObserver<MT>> observer) {
226 observers_[message];
227 auto&& vectorOfObserversOfASpecificMessage = observers_[message];
228 vectorOfObserversOfASpecificMessage.push_back(observer);
229}
230
231template <typename MT>
232void IObservable<MT>::subscribeAll(std::shared_ptr<IObserver<MT>> observer) {
233 for (auto& msg : messages_)
234 subscribe(msg, observer);
235}
236
237template <typename MT>
238void IObservable<MT>::subscribeAll(std::initializer_list<std::shared_ptr<IObserver<MT>>> observers) {
239 for (auto& observer : observers)
240 for (auto& msg : messages_)
241 subscribe(msg, observer);
242}
243
244template <typename MT>
245void IObservable<MT>::unSubscribe(MT message, std::shared_ptr<IObserver<MT>> observer) {
246 auto vectorOfObserversOfASpecificMessage = observers_[message];
247 std::ranges::remove_if(vectorOfObserversOfASpecificMessage, [&observer](auto&& obs) { return obs == observer; });
248}
249
250template <typename MT>
251void IObservable<MT>::unSubscribeAll(std::shared_ptr<IObserver<MT>> observer) {
252 for (auto& msg : messages_)
253 unSubscribe(msg, observer);
254}
255
256template <typename MT>
257void IObservable<MT>::notify(MT message) {
258 auto vectorOfObserversOfASpecificMessage = observers_[message];
259 for (auto&& obs : vectorOfObserversOfASpecificMessage)
260 obs->update(message);
261}
262
263template <typename MT>
264template <std::floating_point ScalarType>
265void IObservable<MT>::notify(MT message, ScalarType val) {
266 auto vectorOfObserversOfASpecificMessage = observers_[message];
267 for (auto&& obs : vectorOfObserversOfASpecificMessage)
268 obs->update(message, val);
269}
270
271template <typename MT>
272void IObservable<MT>::notify(MT message, int val) {
273 auto vectorOfObserversOfASpecificMessage = observers_[message];
274 for (auto&& obs : vectorOfObserversOfASpecificMessage)
275 obs->update(message, val);
276}
277
278template <typename MT>
279void IObservable<MT>::notify(MT message, const std::string& val) {
280 auto vectorOfObserversOfASpecificMessage = observers_[message];
281 for (auto&& obs : vectorOfObserversOfASpecificMessage)
282 obs->update(message, val);
283}
284
285template <typename MT>
286void IObservable<MT>::notify(MT message, int val1, double val2) {
287 auto vectorOfObserversOfASpecificMessage = observers_[message];
288 for (auto&& obs : vectorOfObserversOfASpecificMessage)
289 obs->update(message, val1, val2);
290}
291
292template <typename MT>
293void IObservable<MT>::notify(MT message, int val1, const std::string& val2) {
294 auto vectorOfObserversOfASpecificMessage = observers_[message];
295 for (auto&& obs : vectorOfObserversOfASpecificMessage)
296 obs->update(message, val1, val2);
297}
298
299template <typename MT>
300template <std::floating_point ScalarType>
301void IObservable<MT>::notify(MT message, Eigen::VectorX<ScalarType> vec) {
302 auto vectorOfObserversOfASpecificMessage = observers_[message];
303 for (auto&& obs : vectorOfObserversOfASpecificMessage)
304 obs->update(message, vec);
305}
306} // namespace Ikarus
Implementation of the make enum macro.
MessageType & increment(MessageType &e)
Increments the given enum value.
Definition: makeenum.hh:68
Definition: simpleassemblers.hh:22
Generic observer interface for the Observer design pattern. See for a description of the design patt...
Definition: observer.hh:26
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:88
void update(MessageType message, const Eigen::VectorXd &vec)
Update method for receiving notifications with a message and an Eigen::VectorXd.
Definition: observer.hh:98
virtual ~IObserver()=default
Virtual destructor for the observer interface.
void update(MessageType message, double val)
Update method for receiving notifications with a message and a double value.
Definition: observer.hh:46
virtual void updateImpl(MessageType message, const std::string &val)
Definition: observer.hh:107
virtual void updateImpl(MessageType message, const Eigen::VectorXd &vec)
Definition: observer.hh:110
virtual void updateImpl(MessageType message, int val1, const std::string &val2)
Definition: observer.hh:108
virtual void updateImpl(MessageType message, double val)
Definition: observer.hh:105
virtual void updateImpl(MessageType message, int val)
Definition: observer.hh:106
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:77
void update(MessageType message, int val)
Update method for receiving notifications with a message and an integer value.
Definition: observer.hh:56
void update(MessageType message, const std::string &val)
Update method for receiving notifications with a message and a string value.
Definition: observer.hh:66
void update(MessageType message)
Update method for receiving notifications with a message.
Definition: observer.hh:36
virtual void updateImpl(MessageType message)
Definition: observer.hh:104
MT MessageType
Definition: observer.hh:28
virtual void updateImpl(MessageType message, int val1, double val2)
Definition: observer.hh:109
Generic observable interface for the Observer design pattern. See for a description of the design pa...
Definition: observer.hh:129
void subscribeAll(std::initializer_list< std::shared_ptr< IObserver< MessageType > > > observers)
Subscribe multiple observers to receive notifications for all message types.
void subscribeAll(std::shared_ptr< IObserver< MessageType > > observer)
Subscribe an observer to receive notifications for all message types.
void notify(MessageType message, const std::string &val)
Notify observers about a specific message type with a string value.
void unSubscribeAll(std::shared_ptr< IObserver< MessageType > > observer)
Unsubscribe an observer from receiving notifications for all message types.
Definition: observer.hh:251
void unSubscribe(MessageType message, std::shared_ptr< IObserver< MessageType > > observer)
Unsubscribe an observer from receiving notifications for a specific message type.
Definition: observer.hh:245
void notify(MessageType message, int val)
Notify observers about a specific message type with an integer value.
void notify(MessageType message)
Notify observers about a specific message type.
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.
void notify(MessageType message, ScalarType val)
Notify observers about a specific message type with a floating-point value.
void notify(MessageType message, Eigen::VectorX< ScalarType > vec)
Notify observers about a specific message type with an Eigen::VectorX.
IObservable()
Definition: observer.hh:131
virtual ~IObservable()=default
void subscribe(MessageType message, std::shared_ptr< IObserver< MessageType > > observer)
Subscribe an observer to receive notifications for a specific message type.
Definition: observer.hh:225
void notify(MessageType message, int val1, double val2)
Notify observers about a specific message type with an integer and a double value.