You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We currently rely on pre-change resp. post-change hooks to let components of the system react to a proposed change, using functions named veto_*_change() resp. on_*_change(). The former typically throw an error to prevent a change that would leave the system in an undefined state, whereas the latter allow the component to react to a change, such as re-tuning long-range solvers parameters.
These methods sometimes take arguments, such as the proposed change to check if the value would lead to an undefined state, or a flag to help skip some checks when the corresponding pre-conditions were already validated upstream.
This mechanism is cumbersome and inflexible. In particular, each event needs a dedicated method, sometimes two if both pre- and post-change hooks are needed. These methods need to appear in all derived class, with the correct flags (which can be optional arguments).
To improve separation of concerns and the open/close principle, we could rewrite these hooks using a message-passing interface. Below is a prototype for this new design. This change is made possible by #4816, which encapsulated all event hooks into the core System class.
#include<any>
#include<functional>
#include<optional>
#include<stdexcept>structOnChange {
enumclassProperty : int {
none = 0,
box_l,
time_step,
};
enumclassWhen : int {
none = 0,
before,
after,
};
OnChange(Property property_, When when_, std::any &&value_) :
property{property_}, when{when_}, value{value_}, callback(std::nullopt) {}
Property property;
When when;
std::any value;
std::optional<std::function<void()>> callback;
};
classSolver {
public:voidon_change(OnChange const &message) {
if (message.when == OnChange::When::before) {
if (message.property == OnChange::Property::time_step) {
autoconst time_step = std::any_cast<double>(message.value);
if (time_step /*...*/) {
throwstd::runtime_error("time step too small for feature Solver");
}
}
}
}
};
classSystem {
public:double box_l;
double time_step;
Solver *solver;
voidset_time_step(double value) {
if (solver) {
auto message = OnChange(OnChange::Property::time_step, OnChange::When::before, value);
solver->on_change(message);
this->time_step = value;
message.when = OnChange::When::after;
solver->on_change(message);
}
}
};
intmain() {
Solver solver{};
System system{10., 0.01, &solver};
system.set_time_step(0.05);
}
No description provided.
The text was updated successfully, but these errors were encountered: