Subsystems: bind/init/unbind on add/remove

When adding/remove subsystems to a group which is already bound or
inited, transition the subsystem automatically. This removes the
need to manually transition the subsystem in various places in
Flightgear.
This commit is contained in:
James Turner
2018-08-11 18:41:04 +02:00
parent 8e8ce04e18
commit 1fa77078fc
2 changed files with 68 additions and 17 deletions

View File

@@ -456,13 +456,24 @@ SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
notifyDidChange(subsystem, State::ADD);
if (_state != State::INVALID) {
SG_LOG(SG_GENERAL, SG_DEV_WARN, "TODO: implement SGSubsystemGroup transition when adding after init");
// transition to the correct state
// bind
if (_state >= State::BIND) {
notifyWillChange(subsystem, State::BIND);
subsystem->bind();
notifyDidChange(subsystem, State::BIND);
}
// init
if (_state >= State::INIT) {
notifyWillChange(subsystem, State::INIT);
subsystem->init();
notifyDidChange(subsystem, State::INIT);
}
// post-init
if (_state >= State::POSTINIT) {
notifyWillChange(subsystem, State::POSTINIT);
subsystem->postinit();
notifyDidChange(subsystem, State::POSTINIT);
}
}
}
@@ -504,11 +515,17 @@ SGSubsystemGroup::remove_subsystem(const string &name)
if (_state != State::INVALID) {
// transition out correctly
SG_LOG(SG_GENERAL, SG_DEV_WARN, "TODO: implement SGSubsystemGroup transition when removing before shutdown");
// shutdown
if (_state >= State::INIT) {
notifyWillChange(sub, State::SHUTDOWN);
sub->shutdown();
notifyDidChange(sub, State::SHUTDOWN);
}
// unbind
if (_state >= State::BIND) {
notifyWillChange(sub, State::UNBIND);
sub->unbind();
notifyDidChange(sub, State::UNBIND);
}
}
notifyWillChange(sub, State::REMOVE);
@@ -1152,10 +1169,9 @@ namespace {
group,
minTime);
if (arg->getBoolValue("do-bind-init", false)) {
sub->bind();
sub->init();
}
// we no longer check for the do-bind-init flag here, since set_subsystem
// tracks the group state and will transition the added subsystem
// automatically
return true;
}
@@ -1170,11 +1186,7 @@ namespace {
SG_LOG(SG_GENERAL, SG_ALERT, "do_remove_subsystem: unknown subsytem:" << name);
return false;
}
// is it safe to always call these? let's assume so!
instance->shutdown();
instance->unbind();
// unplug from the manager (this also deletes the instance!)
manager->remove(name.c_str());
return true;

View File

@@ -439,6 +439,44 @@ void testPropertyRoot()
SG_CHECK_EQUAL(props->getIntValue("anothersub/bar"), 172);
}
void testAddRemoveAfterInit()
{
SGSharedPtr<SGSubsystemMgr> manager = new SGSubsystemMgr;
auto d = new RecorderDelegate;
manager->addDelegate(d);
auto group = manager->add<InstrumentGroup>();
SG_VERIFY(group);
auto radio1 = manager->createInstance<FakeRadioSub>("nav1");
group->set_subsystem(radio1);
manager->bind();
manager->init();
SG_VERIFY(d->hasEvent("fake-radio.nav1-will-init"));
SG_VERIFY(d->hasEvent("fake-radio.nav1-did-bind"));
auto radio2 = manager->createInstance<FakeRadioSub>("nav2");
group->set_subsystem(radio2);
SG_VERIFY(d->hasEvent("fake-radio.nav2-will-init"));
SG_VERIFY(d->hasEvent("fake-radio.nav2-did-init"));
SG_VERIFY(d->hasEvent("fake-radio.nav2-did-bind"));
bool ok = manager->remove("fake-radio.nav1");
SG_VERIFY(ok);
SG_VERIFY(d->hasEvent("fake-radio.nav1-will-shutdown"));
SG_VERIFY(d->hasEvent("fake-radio.nav1-did-shutdown"));
SG_VERIFY(d->hasEvent("fake-radio.nav1-will-unbind"));
SG_VERIFY(d->hasEvent("fake-radio.nav1-did-unbind"));
SG_VERIFY(d->hasEvent("fake-radio.nav1-will-remove"));
SG_VERIFY(d->hasEvent("fake-radio.nav1-did-remove"));
}
///////////////////////////////////////////////////////////////////////////////
@@ -450,6 +488,7 @@ int main(int argc, char* argv[])
testIncrementalInit();
testSuspendResume();
testPropertyRoot();
testAddRemoveAfterInit();
cout << __FILE__ << ": All tests passed" << endl;
return EXIT_SUCCESS;