101 :
private StateMachine<State<SimulationMachine, SimulationContext>, SimulationContext> {
111 new StepSimulators{
this},
112 new StepControllers{
this},
122 new Disconnect{
this},
139 StateId
id = initial;
140 std::optional<StateId> interrupt;
144 while ((interrupt = pop_interrupt()) ||
id !=
nullptr) {
156 if (ctx.
config.engine.watchdog_mode == cloe::WatchdogMode::Off) {
158 id = run_state(
id, ctx);
166 logger()->error(
"Unhandled reset request in {} state: {}",
id, e.what());
169 logger()->error(
"Unhandled stop request in {} state: {}",
id, e.what());
172 logger()->error(
"Unhandled abort request in {} state: {}",
id, e.what());
175 logger()->error(
"Unhandled model error in {} state: {}",
id, e.what());
177 }
catch (std::exception& e) {
178 logger()->critical(
"Fatal error in {} state: {}",
id, e.what());
192 std::chrono::milliseconds timeout = ctx.
config.engine.watchdog_default_timeout;
193 if (ctx.
config.engine.watchdog_state_timeouts.count(
id)) {
194 auto maybe = ctx.
config.engine.watchdog_state_timeouts[id];
199 auto interval = timeout.count() > 0 ? timeout : ctx.
config.engine.polling_interval;
202 std::future<StateId> f =
203 std::async(std::launch::async, [
this,
id, &ctx]() {
return run_state(
id, ctx); });
205 std::future_status status;
207 status = f.wait_for(interval);
208 if (status == std::future_status::ready) {
210 }
else if (status == std::future_status::deferred) {
211 if (timeout.count() > 0) {
212 logger()->warn(
"Watchdog waiting on deferred execution.");
214 }
else if (status == std::future_status::timeout) {
215 if (timeout.count() > 0) {
216 logger()->critical(
"Watchdog timeout of {} ms exceeded for state: {}", timeout.count(),
219 if (ctx.
config.engine.watchdog_mode == cloe::WatchdogMode::Abort) {
220 logger()->critical(
"Aborting simulation... this might take a while...");
222 }
else if (ctx.
config.engine.watchdog_mode == cloe::WatchdogMode::Kill) {
223 logger()->critical(
"Killing program... this is going to be messy...");
241 logger()->debug(
"Handle interrupt: {}", interrupt);
245 if (interrupt == PAUSE) {
247 }
else if (interrupt == RESUME) {
252 return this->run_state(interrupt, ctx);
259 {
"states", m.states()},
263 #define DEFINE_STATE(Id, S) DEFINE_STATE_STRUCT(SimulationMachine, SimulationContext, Id, S)
265 DEFINE_STATE(CONNECT, Connect);
266 DEFINE_STATE(PROBE, Probe);
267 DEFINE_STATE(START, Start);
268 DEFINE_STATE(STEP_BEGIN, StepBegin);
269 DEFINE_STATE(STEP_SIMULATORS, StepSimulators);
270 DEFINE_STATE(STEP_CONTROLLERS, StepControllers);
271 DEFINE_STATE(STEP_END, StepEnd);
272 DEFINE_STATE(PAUSE, Pause);
273 DEFINE_STATE(RESUME, Resume);
274 DEFINE_STATE(SUCCESS, Success);
275 DEFINE_STATE(FAIL, Fail);
276 DEFINE_STATE(ABORT, Abort);
277 DEFINE_STATE(STOP, Stop);
278 DEFINE_STATE(RESET, Reset);
279 DEFINE_STATE(KEEP_ALIVE, KeepAlive);
280 DEFINE_STATE(DISCONNECT, Disconnect);
Definition: model.hpp:106
Definition: model.hpp:127
Definition: simulation_machine.hpp:101
void run(SimulationContext &ctx)
Definition: simulation_machine.hpp:132
void run_machine(StateId initial, SimulationContext &ctx)
Definition: simulation_machine.hpp:138
StateId run_state_async(StateId id, SimulationContext &ctx)
Definition: simulation_machine.hpp:191
StateId handle_interrupt(StateId nominal, StateId interrupt, SimulationContext &ctx) override
Definition: simulation_machine.hpp:240
Definition: state_machine.hpp:122
virtual cloe::Logger logger() const
Definition: state_machine.hpp:219
void push_interrupt(StateId id)
Definition: state_machine.hpp:187
Definition: state_machine.hpp:49
@ Success
Simulation explicitly concluded with success.
Definition: simulation_context.hpp:67
cloe::Stack config
Input configuration.
Definition: simulation_context.hpp:79
bool pause_execution
Definition: simulation_context.hpp:134