Skip to content

Commit 1c244fb

Browse files
committed
add state machine checks
1 parent 0ce70dc commit 1c244fb

1 file changed

Lines changed: 112 additions & 53 deletions

File tree

export/src/fmu4cpp/fmi3.cpp

Lines changed: 112 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,6 @@
1313
namespace {
1414

1515

16-
fmiStatus toCommonStatusFromFmi3(fmi3Status status) {
17-
switch (status) {
18-
case fmi3OK:
19-
return fmiOK;
20-
case fmi3Warning:
21-
return fmiWarning;
22-
case fmi3Discard:
23-
return fmiDiscard;
24-
case fmi3Error:
25-
return fmiError;
26-
case fmi3Fatal:
27-
return fmiFatal;
28-
default:
29-
return fmiStatusUnknown;
30-
}
31-
}
32-
3316
fmi3Status toFmi3StatusFromCommon(fmiStatus status) {
3417
switch (status) {
3518
case fmiOK:
@@ -66,13 +49,23 @@ namespace {
6649
// A struct that holds all the data for one model instance.
6750
struct Fmi3Component {
6851

52+
enum class State {
53+
Instantiated = 1 << 0,
54+
InitializationMode = 1 << 1,
55+
StepMode = 1 << 2,
56+
Terminated = 1 << 3,
57+
Invalid = 1 << 4
58+
};
59+
6960
Fmi3Component(std::unique_ptr<fmu4cpp::fmu_base> slave, fmi3InstanceEnvironment env, fmi3LogMessageCallback logCallback)
70-
: slave(std::move(slave)),
61+
: state(State::Instantiated),
62+
slave(std::move(slave)),
7163
logger(std::make_unique<fmi3Logger>(env, logCallback, this->slave->instanceName())) {
7264

7365
this->slave->__set_logger(logger.get());
7466
}
7567

68+
State state;
7669
std::unique_ptr<fmu4cpp::fmu_base> slave;
7770
std::unique_ptr<fmu4cpp::logger> logger;
7871
};
@@ -87,7 +80,7 @@ namespace {
8780
FMU_TYPE(type) values[], \
8881
size_t nValues) { \
8982
const auto component = static_cast<Fmi3Component *>(c); \
90-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), std::string("Unsupported function fmi3Get") + #type); \
83+
component->logger->log(fmiError, std::string("Unsupported function fmi3Get") + #type); \
9184
return fmi3Error; \
9285
}
9386

@@ -99,7 +92,7 @@ namespace {
9992
const FMU_TYPE(type) values[], \
10093
size_t nValues) { \
10194
const auto component = static_cast<Fmi3Component *>(c); \
102-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), std::string("Unsupported function fmi3Set") + #type); \
95+
component->logger->log(fmiError, std::string("Unsupported function fmi3Set") + #type); \
10396
return fmi3Error; \
10497
}
10598

@@ -191,10 +184,18 @@ fmi3Instance fmi3InstantiateCoSimulation(
191184
return nullptr;
192185
}
193186

194-
auto c = std::make_unique<Fmi3Component>(std::move(slave), instanceEnvironment, logMessage);
195-
c->logger->setDebugLogging(loggingOn);
187+
try {
188+
auto c = std::make_unique<Fmi3Component>(std::move(slave), instanceEnvironment, logMessage);
189+
c->logger->setDebugLogging(loggingOn);
190+
191+
return c.release();
192+
} catch (const std::exception &e) {
196193

197-
return c.release();
194+
fmi3Logger l(instanceEnvironment, logMessage, instanceName);
195+
l.log(fmiFatal, "Unable to instantiate model! " + std::string(e.what()));
196+
197+
return nullptr;
198+
}
198199
}
199200

200201
fmi3Status fmi3EnterEventMode(fmi3Instance instance) {
@@ -220,27 +221,43 @@ fmi3Status fmi3EnterInitializationMode(fmi3Instance c,
220221
const auto component = static_cast<Fmi3Component *>(c);
221222

222223
try {
224+
225+
if (component->state != Fmi3Component::State::Instantiated) {
226+
throw std::logic_error("Invalid state. Expected Instantiated.");
227+
}
228+
223229
component->slave->enter_initialisation_mode(startTime, stop, tol);
230+
component->state = Fmi3Component::State::InitializationMode;
224231
return fmi3OK;
225232
} catch (const fmu4cpp::fatal_error &ex) {
226-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
233+
component->logger->log(fmiFatal, ex.what());
234+
component->state = Fmi3Component::State::Invalid;
227235
return fmi3Fatal;
228236
} catch (const std::exception &ex) {
229-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
237+
component->logger->log(fmiError, ex.what());
238+
component->state = Fmi3Component::State::Terminated;
230239
return fmi3Error;
231240
}
232241
}
233242

234243
fmi3Status fmi3ExitInitializationMode(fmi3Instance c) {
235244
const auto component = static_cast<Fmi3Component *>(c);
236245
try {
246+
247+
if (component->state != Fmi3Component::State::InitializationMode) {
248+
throw std::logic_error("Invalid state. Expected InitializationMode.");
249+
}
250+
237251
component->slave->exit_initialisation_mode();
252+
component->state = Fmi3Component::State::StepMode;
238253
return fmi3OK;
239254
} catch (const fmu4cpp::fatal_error &ex) {
240-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
255+
component->logger->log(fmiFatal, ex.what());
256+
component->state = Fmi3Component::State::Invalid;
241257
return fmi3Fatal;
242258
} catch (const std::exception &ex) {
243-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
259+
component->logger->log(fmiError, ex.what());
260+
component->state = Fmi3Component::State::Terminated;
244261
return fmi3Error;
245262
}
246263
}
@@ -249,12 +266,15 @@ fmi3Status fmi3Terminate(fmi3Instance c) {
249266
const auto component = static_cast<Fmi3Component *>(c);
250267
try {
251268
component->slave->terminate();
269+
component->state = Fmi3Component::State::Terminated;
252270
return fmi3OK;
253271
} catch (const fmu4cpp::fatal_error &ex) {
254-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
272+
component->logger->log(fmiFatal, ex.what());
273+
component->state = Fmi3Component::State::Invalid;
255274
return fmi3Fatal;
256275
} catch (const std::exception &ex) {
257-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
276+
component->logger->log(fmiError, ex.what());
277+
component->state = Fmi3Component::State::Terminated;
258278
return fmi3Error;
259279
}
260280
}
@@ -270,6 +290,11 @@ fmi3Status fmi3DoStep(fmi3Instance c,
270290

271291
const auto component = static_cast<Fmi3Component *>(c);
272292
try {
293+
294+
if (component->state != Fmi3Component::State::StepMode) {
295+
throw std::logic_error("Invalid state. Expected StepMode.");
296+
}
297+
273298
if (component->slave->step(currentCommunicationPoint, communicationStepSize)) {
274299
*earlyReturn = false;
275300
*terminateSimulation = false;
@@ -278,12 +303,16 @@ fmi3Status fmi3DoStep(fmi3Instance c,
278303
return fmi3OK;
279304
}
280305

306+
component->logger->log(fmiWarning, "Step returned false!");
307+
281308
return fmi3Discard;
282309
} catch (const fmu4cpp::fatal_error &ex) {
283-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
310+
component->logger->log(fmiFatal, ex.what());
311+
component->state = Fmi3Component::State::Invalid;
284312
return fmi3Fatal;
285313
} catch (const std::exception &ex) {
286-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
314+
component->logger->log(fmiError, ex.what());
315+
component->state = Fmi3Component::State::Terminated;
287316
return fmi3Error;
288317
}
289318
}
@@ -294,8 +323,19 @@ fmi3Status fmi3CancelStep(fmi3Instance) {
294323

295324
fmi3Status fmi3Reset(fmi3Instance c) {
296325
const auto component = static_cast<Fmi3Component *>(c);
297-
component->slave->reset();
298-
return fmi3OK;
326+
try {
327+
component->slave->reset();
328+
component->state = Fmi3Component::State::Instantiated;
329+
return fmi3OK;
330+
} catch (const fmu4cpp::fatal_error &ex) {
331+
component->logger->log(fmiFatal, ex.what());
332+
component->state = Fmi3Component::State::Invalid;
333+
return fmi3Fatal;
334+
} catch (const std::exception &ex) {
335+
component->logger->log(fmiError, ex.what());
336+
component->state = Fmi3Component::State::Terminated;
337+
return fmi3Error;
338+
}
299339
}
300340

301341
fmi3Status fmi3GetInt32(
@@ -310,10 +350,12 @@ fmi3Status fmi3GetInt32(
310350
component->slave->get_integer(vr, nvr, value);
311351
return fmi3OK;
312352
} catch (const fmu4cpp::fatal_error &ex) {
313-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
353+
component->logger->log(fmiFatal, ex.what());
354+
component->state = Fmi3Component::State::Invalid;
314355
return fmi3Fatal;
315356
} catch (const std::exception &ex) {
316-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
357+
component->logger->log(fmiError, ex.what());
358+
component->state = Fmi3Component::State::Terminated;
317359
return fmi3Error;
318360
}
319361
}
@@ -330,10 +372,12 @@ fmi3Status fmi3GetFloat64(
330372
component->slave->get_real(vr, nvr, value);
331373
return fmi3OK;
332374
} catch (const fmu4cpp::fatal_error &ex) {
333-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
375+
component->logger->log(fmiFatal, ex.what());
376+
component->state = Fmi3Component::State::Invalid;
334377
return fmi3Fatal;
335378
} catch (const std::exception &ex) {
336-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
379+
component->logger->log(fmiError, ex.what());
380+
component->state = Fmi3Component::State::Terminated;
337381
return fmi3Error;
338382
}
339383
}
@@ -350,10 +394,12 @@ fmi3Status fmi3GetBoolean(
350394
component->slave->get_boolean(vr, nvr, value);
351395
return fmi3OK;
352396
} catch (const fmu4cpp::fatal_error &ex) {
353-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
397+
component->logger->log(fmiFatal, ex.what());
398+
component->state = Fmi3Component::State::Invalid;
354399
return fmi3Fatal;
355400
} catch (const std::exception &ex) {
356-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
401+
component->logger->log(fmiError, ex.what());
402+
component->state = Fmi3Component::State::Terminated;
357403
return fmi3Error;
358404
}
359405
}
@@ -370,10 +416,12 @@ fmi3Status fmi3GetString(
370416
component->slave->get_string(vr, nvr, value);
371417
return fmi3OK;
372418
} catch (const fmu4cpp::fatal_error &ex) {
373-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
419+
component->logger->log(fmiFatal, ex.what());
420+
component->state = Fmi3Component::State::Invalid;
374421
return fmi3Fatal;
375422
} catch (const std::exception &ex) {
376-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
423+
component->logger->log(fmiError, ex.what());
424+
component->state = Fmi3Component::State::Terminated;
377425
return fmi3Error;
378426
}
379427
}
@@ -390,10 +438,12 @@ fmi3Status fmi3SetInt32(
390438
component->slave->set_integer(vr, nvr, value);
391439
return fmi3OK;
392440
} catch (const fmu4cpp::fatal_error &ex) {
393-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
441+
component->logger->log(fmiFatal, ex.what());
442+
component->state = Fmi3Component::State::Invalid;
394443
return fmi3Fatal;
395444
} catch (const std::exception &ex) {
396-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
445+
component->logger->log(fmiError, ex.what());
446+
component->state = Fmi3Component::State::Terminated;
397447
return fmi3Error;
398448
}
399449
}
@@ -410,10 +460,12 @@ fmi3Status fmi3SetFloat64(
410460
component->slave->set_real(vr, nvr, value);
411461
return fmi3OK;
412462
} catch (const fmu4cpp::fatal_error &ex) {
413-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
463+
component->logger->log(fmiFatal, ex.what());
464+
component->state = Fmi3Component::State::Invalid;
414465
return fmi3Fatal;
415466
} catch (const std::exception &ex) {
416-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
467+
component->logger->log(fmiError, ex.what());
468+
component->state = Fmi3Component::State::Terminated;
417469
return fmi3Error;
418470
}
419471
}
@@ -430,10 +482,12 @@ fmi3Status fmi3SetBoolean(
430482
component->slave->set_boolean(vr, nvr, value);
431483
return fmi3OK;
432484
} catch (const fmu4cpp::fatal_error &ex) {
433-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
485+
component->logger->log(fmiFatal, ex.what());
486+
component->state = Fmi3Component::State::Invalid;
434487
return fmi3Fatal;
435488
} catch (const std::exception &ex) {
436-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
489+
component->logger->log(fmiError, ex.what());
490+
component->state = Fmi3Component::State::Terminated;
437491
return fmi3Error;
438492
}
439493
}
@@ -450,10 +504,12 @@ fmi3Status fmi3SetString(
450504
component->slave->set_string(vr, nvr, value);
451505
return fmi3OK;
452506
} catch (const fmu4cpp::fatal_error &ex) {
453-
component->logger->log(toCommonStatusFromFmi3(fmi3Fatal), ex.what());
507+
component->logger->log(fmiFatal, ex.what());
508+
component->state = Fmi3Component::State::Invalid;
454509
return fmi3Fatal;
455510
} catch (const std::exception &ex) {
456-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), ex.what());
511+
component->logger->log(fmiError, ex.what());
512+
component->state = Fmi3Component::State::Terminated;
457513
return fmi3Error;
458514
}
459515
}
@@ -467,7 +523,7 @@ fmi3Status fmi3GetBinary(fmi3Instance c,
467523

468524
const auto component = static_cast<Fmi3Component *>(c);
469525

470-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), "Unsupported function fmi3GetBinary");
526+
component->logger->log(fmiError, "Unsupported function fmi3GetBinary");
471527
return fmi3Error;
472528
}
473529

@@ -480,7 +536,7 @@ fmi3Status fmi3SetBinary(fmi3Instance c,
480536

481537
const auto component = static_cast<Fmi3Component *>(c);
482538

483-
component->logger->log(toCommonStatusFromFmi3(fmi3Error), "Unsupported function fmi3SetBinary");
539+
component->logger->log(fmiError, "Unsupported function fmi3SetBinary");
484540
return fmi3Error;
485541
}
486542

@@ -800,7 +856,10 @@ fmi3Status fmi3ActivateModelPartition(fmi3Instance instance,
800856
}
801857

802858
void fmi3FreeInstance(fmi3Instance c) {
803-
const auto component = static_cast<Fmi3Component *>(c);
804-
delete component;
859+
if (c) {
860+
const auto component = static_cast<Fmi3Component *>(c);
861+
component->state = Fmi3Component::State::Invalid;
862+
delete component;
863+
}
805864
}
806865
}

0 commit comments

Comments
 (0)