X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fstructure%2Fsubsystem_mgr.cxx;h=387d097a091bd855ebfe189aeb38b092135ded59;hb=5f2f95676c4b46e0c2ef3764baa2fd8c87abd238;hp=2adf0e7841176c00bbe93bb5e960c929fb0a8437;hpb=25cefd91298485eb94959017b1aa17bc550d2f3f;p=simgear.git diff --git a/simgear/structure/subsystem_mgr.cxx b/simgear/structure/subsystem_mgr.cxx index 2adf0e78..387d097a 100644 --- a/simgear/structure/subsystem_mgr.cxx +++ b/simgear/structure/subsystem_mgr.cxx @@ -5,8 +5,10 @@ #include "exception.hxx" #include "subsystem_mgr.hxx" +#include - + +const int SG_MAX_SUBSYSTEM_EXCEPTIONS = 4; //////////////////////////////////////////////////////////////////////// // Implementation of SGSubsystem //////////////////////////////////////////////////////////////////////// @@ -36,6 +38,11 @@ SGSubsystem::reinit () { } +void +SGSubsystem::shutdown () +{ +} + void SGSubsystem::bind () { @@ -74,27 +81,27 @@ SGSubsystem::is_suspended () const void SGSubsystem::printTimingInformation () { - SGTimeStamp startTime, endTime; - long duration; + SGTimeStamp startTime; for ( eventTimeVecIterator i = timingInfo.begin(); i != timingInfo.end(); i++) { if (i == timingInfo.begin()) { startTime = i->getTime(); } else { - endTime = i->getTime(); - duration = (endTime - startTime); + SGTimeStamp endTime = i->getTime(); + SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp : " + << i->getName() << " takes " << endTime - startTime + << " sec."); startTime = endTime; - SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp : " << i->getName() << " takes " << duration << " usec."); } } } -void SGSubsystem::stamp(string name) + + +void SGSubsystem::stamp(const string& name) { - SGTimeStamp now; - now.stamp(); - timingInfo.push_back(TimingInfo(name, now)); + timingInfo.push_back(TimingInfo(name, SGTimeStamp::now())); } @@ -102,14 +109,20 @@ void SGSubsystem::stamp(string name) // Implementation of SGSubsystemGroup. //////////////////////////////////////////////////////////////////////// -SGSubsystemGroup::SGSubsystemGroup () +SGSubsystemGroup::SGSubsystemGroup () : + _fixedUpdateTime(-1.0), + _updateTimeRemainder(0.0) { } SGSubsystemGroup::~SGSubsystemGroup () { - for (unsigned int i = 0; i < _members.size(); i++) - delete _members[i]; + // reverse order to prevent order dependency problems + for (unsigned int i = _members.size(); i > 0; i--) + { + _members[i-1]->printTimingStatistics(); + delete _members[i-1]; + } } void @@ -133,6 +146,14 @@ SGSubsystemGroup::reinit () _members[i]->subsystem->reinit(); } +void +SGSubsystemGroup::shutdown () +{ + // reverse order to prevent order dependency problems + for (unsigned int i = _members.size(); i > 0; i--) + _members[i-1]->subsystem->shutdown(); +} + void SGSubsystemGroup::bind () { @@ -143,25 +164,47 @@ SGSubsystemGroup::bind () void SGSubsystemGroup::unbind () { - for (unsigned int i = 0; i < _members.size(); i++) - _members[i]->subsystem->unbind(); + // reverse order to prevent order dependency problems + for (unsigned int i = _members.size(); i > 0; i--) + _members[i-1]->subsystem->unbind(); } void SGSubsystemGroup::update (double delta_time_sec) +{ + int loopCount = 1; + // if dt == 0.0, we are paused, so we need to run one iteration + // of our members; if we have a fixed update time, we compute a + // loop count, and locally adjust dt + if ((delta_time_sec > 0.0) && (_fixedUpdateTime > 0.0)) { + double localDelta = delta_time_sec + _updateTimeRemainder; + loopCount = SGMiscd::roundToInt(localDelta / _fixedUpdateTime); + _updateTimeRemainder = delta_time_sec - (loopCount * _fixedUpdateTime); + delta_time_sec = _fixedUpdateTime; + } + + while (loopCount-- > 0) { + for (unsigned int i = 0; i < _members.size(); i++) + { + SGTimeStamp timeStamp = SGTimeStamp::now(); + _members[i]->update(delta_time_sec); // indirect call + timeStamp = timeStamp - SGTimeStamp::now(); + double b = timeStamp.toUSecs(); + _members[i]->updateExecutionTime(b); + double threshold = _members[i]->getTimeWarningThreshold(); + if (( b > threshold ) && (b > 10000)) { + _members[i]->printTimingInformation(b); + } + } + } // of multiple update loop +} + +void +SGSubsystemGroup::collectDebugTiming(bool collect) { for (unsigned int i = 0; i < _members.size(); i++) { - SGTimeStamp start, now; - start.stamp(); - _members[i]->update(delta_time_sec); // indirect call - now.stamp(); - long b = ( now - start ); - if ( b > 10000 ) { - SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << b << " " << _members[i]->name); - //int a = 1; - _members[i]->printTimingInformation(); - } + _members[i]->collectDebugTiming(collect); } } @@ -218,6 +261,32 @@ SGSubsystemGroup::remove_subsystem (const string &name) } } +void +SGSubsystemGroup::set_fixed_update_time(double dt) +{ + _fixedUpdateTime = dt; +} + +void +SGSubsystemGroup::Member::printTimingStatistics () +{ + if (collectTimeStats) { + double minTime = timeStat.min() / 1000; + double maxTime = timeStat.max() / 1000; + double meanTime = timeStat.mean() / 1000; + double stddev = timeStat.stdDev() / 1000; + + char buffer[256]; + snprintf(buffer, 256, "Timing summary for %20s.\n" + "- mean time: %04.2f ms.\n" + "- min time : %04.2f ms.\n" + "- max time : %04.2f ms.\n" + "- stddev : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev); + SG_LOG(SG_GENERAL, SG_ALERT, buffer); + } +} + + bool SGSubsystemGroup::has_subsystem (const string &name) const { @@ -251,13 +320,15 @@ SGSubsystemGroup::Member::Member () : name(""), subsystem(0), min_step_sec(0), - elapsed_sec(0) + elapsed_sec(0), + collectTimeStats(false), + exceptionCount(0) { } +// This shouldn't be called due to subsystem pointer ownership issues. SGSubsystemGroup::Member::Member (const Member &) { - Member(); } SGSubsystemGroup::Member::~Member () @@ -269,21 +340,53 @@ void SGSubsystemGroup::Member::update (double delta_time_sec) { elapsed_sec += delta_time_sec; - if (elapsed_sec >= min_step_sec) { - if (!subsystem->is_suspended()) { - subsystem->update(elapsed_sec); - elapsed_sec = 0; - } + if (elapsed_sec < min_step_sec) { + return; + } + + if (subsystem->is_suspended()) { + return; + } + + try { + subsystem->update(elapsed_sec); + elapsed_sec = 0; + } catch (sg_exception& e) { + SG_LOG(SG_GENERAL, SG_ALERT, "caught exception processing subsystem:" << name + << "\nmessage:" << e.getMessage()); + + if (++exceptionCount > SG_MAX_SUBSYSTEM_EXCEPTIONS) { + SG_LOG(SG_GENERAL, SG_ALERT, "(exceptionCount=" << exceptionCount << + ", suspending)"); + subsystem->suspend(); + } } } void -SGSubsystemGroup::Member::printTimingInformation() +SGSubsystemGroup::Member::printTimingInformation(double time) { - subsystem->printTimingInformation(); + if (collectTimeStats) { + SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name); + subsystem->printTimingInformation(); + } } +double SGSubsystemGroup::Member::getTimeWarningThreshold() +{ + return (timeStat.mean() + 3 * timeStat.stdDev()); +} + +void SGSubsystemGroup::Member::updateExecutionTime(double time) +{ + if (collectTimeStats) { + timeStat += time; + } +} + + + //////////////////////////////////////////////////////////////////////// @@ -293,52 +396,80 @@ SGSubsystemGroup::Member::printTimingInformation() SGSubsystemMgr::SGSubsystemMgr () { + for (int i = 0; i < MAX_GROUPS; i++) { + _groups[i] = new SGSubsystemGroup; + } } SGSubsystemMgr::~SGSubsystemMgr () { + // ensure get_subsystem returns NULL from now onwards, + // before the SGSubsystemGroup destructors are run + _subsystem_map.clear(); + + for (int i = 0; i < MAX_GROUPS; i++) { + delete _groups[i]; + } } void SGSubsystemMgr::init () { for (int i = 0; i < MAX_GROUPS; i++) - _groups[i].init(); + _groups[i]->init(); } void SGSubsystemMgr::postinit () { for (int i = 0; i < MAX_GROUPS; i++) - _groups[i].postinit(); + _groups[i]->postinit(); } void SGSubsystemMgr::reinit () { for (int i = 0; i < MAX_GROUPS; i++) - _groups[i].reinit(); + _groups[i]->reinit(); } +void +SGSubsystemMgr::shutdown () +{ + // reverse order to prevent order dependency problems + for (int i = MAX_GROUPS-1; i >= 0; i--) + _groups[i]->shutdown(); +} + + void SGSubsystemMgr::bind () { for (int i = 0; i < MAX_GROUPS; i++) - _groups[i].bind(); + _groups[i]->bind(); } void SGSubsystemMgr::unbind () { - for (int i = 0; i < MAX_GROUPS; i++) - _groups[i].unbind(); + // reverse order to prevent order dependency problems + for (int i = MAX_GROUPS-1; i >= 0; i--) + _groups[i]->unbind(); } void SGSubsystemMgr::update (double delta_time_sec) { for (int i = 0; i < MAX_GROUPS; i++) { - _groups[i].update(delta_time_sec); + _groups[i]->update(delta_time_sec); + } +} + +void +SGSubsystemMgr::collectDebugTiming(bool collect) +{ + for (int i = 0; i < MAX_GROUPS; i++) { + _groups[i]->collectDebugTiming(collect); } } @@ -346,14 +477,14 @@ void SGSubsystemMgr::suspend () { for (int i = 0; i < MAX_GROUPS; i++) - _groups[i].suspend(); + _groups[i]->suspend(); } void SGSubsystemMgr::resume () { for (int i = 0; i < MAX_GROUPS; i++) - _groups[i].resume(); + _groups[i]->resume(); } bool @@ -376,16 +507,39 @@ SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem, _subsystem_map[name] = subsystem; } +SGSubsystem* +SGSubsystemMgr::remove(const char* name) +{ + SubsystemDict::iterator s =_subsystem_map.find(name); + if (s == _subsystem_map.end()) { + return NULL; + } + + SGSubsystem* sub = s->second; + _subsystem_map.erase(s); + +// tedious part - we don't know which group the subsystem belongs too + for (int i = 0; i < MAX_GROUPS; i++) { + if (_groups[i]->get_subsystem(name) == sub) { + _groups[i]->remove_subsystem(name); + break; + } + } // of groups iteration + + return sub; +} + + SGSubsystemGroup * SGSubsystemMgr::get_group (GroupType group) { - return &(_groups[group]); + return _groups[group]; } SGSubsystem * -SGSubsystemMgr::get_subsystem (const string &name) +SGSubsystemMgr::get_subsystem (const string &name) const { - map::iterator s =_subsystem_map.find(name); + SubsystemDict::const_iterator s =_subsystem_map.find(name); if (s == _subsystem_map.end()) return 0;