00001
00002 #include <simgear/debug/logstream.hxx>
00003 #include <simgear/timing/timestamp.hxx>
00004
00005 #include "exception.hxx"
00006 #include "subsystem_mgr.hxx"
00007
00008 #include <simgear/math/SGMath.hxx>
00009
00010
00011
00013
00015
00016
00017 SGSubsystem::SGSubsystem ()
00018 : _suspended(false)
00019 {
00020 }
00021
00022 SGSubsystem::~SGSubsystem ()
00023 {
00024 }
00025
00026 void
00027 SGSubsystem::init ()
00028 {
00029 }
00030
00031 void
00032 SGSubsystem::postinit ()
00033 {
00034 }
00035
00036 void
00037 SGSubsystem::reinit ()
00038 {
00039 }
00040
00041 void
00042 SGSubsystem::bind ()
00043 {
00044 }
00045
00046 void
00047 SGSubsystem::unbind ()
00048 {
00049 }
00050
00051 void
00052 SGSubsystem::suspend ()
00053 {
00054 _suspended = true;
00055 }
00056
00057 void
00058 SGSubsystem::suspend (bool suspended)
00059 {
00060 _suspended = suspended;
00061 }
00062
00063 void
00064 SGSubsystem::resume ()
00065 {
00066 _suspended = false;
00067 }
00068
00069 bool
00070 SGSubsystem::is_suspended () const
00071 {
00072 return _suspended;
00073 }
00074
00075
00076 void
00077 SGSubsystem::printTimingInformation ()
00078 {
00079 SGTimeStamp startTime;
00080 for ( eventTimeVecIterator i = timingInfo.begin();
00081 i != timingInfo.end();
00082 i++) {
00083 if (i == timingInfo.begin()) {
00084 startTime = i->getTime();
00085 } else {
00086 SGTimeStamp endTime = i->getTime();
00087 SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp : "
00088 << i->getName() << " takes " << endTime - startTime
00089 << " sec.");
00090 startTime = endTime;
00091 }
00092 }
00093 }
00094
00095
00096
00097 void SGSubsystem::stamp(const string& name)
00098 {
00099 timingInfo.push_back(TimingInfo(name, SGTimeStamp::now()));
00100 }
00101
00102
00104
00106
00107 SGSubsystemGroup::SGSubsystemGroup ()
00108 {
00109 }
00110
00111 SGSubsystemGroup::~SGSubsystemGroup ()
00112 {
00113
00114 for (unsigned int i = _members.size(); i > 0; i--)
00115 {
00116 _members[i-1]->printTimingStatistics();
00117 delete _members[i-1];
00118 }
00119 }
00120
00121 void
00122 SGSubsystemGroup::init ()
00123 {
00124 for (unsigned int i = 0; i < _members.size(); i++)
00125 _members[i]->subsystem->init();
00126 }
00127
00128 void
00129 SGSubsystemGroup::postinit ()
00130 {
00131 for (unsigned int i = 0; i < _members.size(); i++)
00132 _members[i]->subsystem->postinit();
00133 }
00134
00135 void
00136 SGSubsystemGroup::reinit ()
00137 {
00138 for (unsigned int i = 0; i < _members.size(); i++)
00139 _members[i]->subsystem->reinit();
00140 }
00141
00142 void
00143 SGSubsystemGroup::bind ()
00144 {
00145 for (unsigned int i = 0; i < _members.size(); i++)
00146 _members[i]->subsystem->bind();
00147 }
00148
00149 void
00150 SGSubsystemGroup::unbind ()
00151 {
00152
00153 for (unsigned int i = _members.size(); i > 0; i--)
00154 _members[i-1]->subsystem->unbind();
00155 }
00156
00157 void
00158 SGSubsystemGroup::update (double delta_time_sec)
00159 {
00160 for (unsigned int i = 0; i < _members.size(); i++)
00161 {
00162 SGTimeStamp timeStamp = SGTimeStamp::now();
00163 _members[i]->update(delta_time_sec);
00164 timeStamp = timeStamp - SGTimeStamp::now();
00165 double b = timeStamp.toUSecs();
00166 _members[i]->updateExecutionTime(b);
00167 double threshold = _members[i]->getTimeWarningThreshold();
00168 if (( b > threshold ) && (b > 10000)) {
00169 _members[i]->printTimingInformation(b);
00170 }
00171 }
00172 }
00173
00174 void
00175 SGSubsystemGroup::collectDebugTiming(bool collect)
00176 {
00177 for (unsigned int i = 0; i < _members.size(); i++)
00178 {
00179 _members[i]->collectDebugTiming(collect);
00180 }
00181 }
00182
00183 void
00184 SGSubsystemGroup::suspend ()
00185 {
00186 for (unsigned int i = 0; i < _members.size(); i++)
00187 _members[i]->subsystem->suspend();
00188 }
00189
00190 void
00191 SGSubsystemGroup::resume ()
00192 {
00193 for (unsigned int i = 0; i < _members.size(); i++)
00194 _members[i]->subsystem->resume();
00195 }
00196
00197 bool
00198 SGSubsystemGroup::is_suspended () const
00199 {
00200 return false;
00201 }
00202
00203 void
00204 SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
00205 double min_step_sec)
00206 {
00207 Member * member = get_member(name, true);
00208 if (member->subsystem != 0)
00209 delete member->subsystem;
00210 member->name = name;
00211 member->subsystem = subsystem;
00212 member->min_step_sec = min_step_sec;
00213 }
00214
00215 SGSubsystem *
00216 SGSubsystemGroup::get_subsystem (const string &name)
00217 {
00218 Member * member = get_member(name);
00219 if (member != 0)
00220 return member->subsystem;
00221 else
00222 return 0;
00223 }
00224
00225 void
00226 SGSubsystemGroup::remove_subsystem (const string &name)
00227 {
00228 for (unsigned int i = 0; i < _members.size(); i++) {
00229 if (name == _members[i]->name) {
00230 _members.erase(_members.begin() + i);
00231 return;
00232 }
00233 }
00234 }
00235
00236 void
00237 SGSubsystemGroup::Member::printTimingStatistics ()
00238 {
00239 if (collectTimeStats) {
00240 double minTime = timeStat.min() / 1000;
00241 double maxTime = timeStat.max() / 1000;
00242 double meanTime = timeStat.mean() / 1000;
00243 double stddev = timeStat.stdDev() / 1000;
00244
00245 char buffer[256];
00246 snprintf(buffer, 256, "Timing summary for %20s.\n"
00247 "- mean time: %04.2f ms.\n"
00248 "- min time : %04.2f ms.\n"
00249 "- max time : %04.2f ms.\n"
00250 "- stddev : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev);
00251 SG_LOG(SG_GENERAL, SG_ALERT, buffer);
00252 }
00253 }
00254
00255
00256 bool
00257 SGSubsystemGroup::has_subsystem (const string &name) const
00258 {
00259 return (((SGSubsystemGroup *)this)->get_member(name) != 0);
00260 }
00261
00262 SGSubsystemGroup::Member *
00263 SGSubsystemGroup::get_member (const string &name, bool create)
00264 {
00265 for (unsigned int i = 0; i < _members.size(); i++) {
00266 if (_members[i]->name == name)
00267 return _members[i];
00268 }
00269 if (create) {
00270 Member * member = new Member;
00271 _members.push_back(member);
00272 return member;
00273 } else {
00274 return 0;
00275 }
00276 }
00277
00278
00279
00281
00283
00284
00285 SGSubsystemGroup::Member::Member ()
00286 : name(""),
00287 subsystem(0),
00288 min_step_sec(0),
00289 elapsed_sec(0),
00290 collectTimeStats(false)
00291 {
00292 }
00293
00294
00295 SGSubsystemGroup::Member::Member (const Member &)
00296 {
00297 }
00298
00299 SGSubsystemGroup::Member::~Member ()
00300 {
00301 delete subsystem;
00302 }
00303
00304 void
00305 SGSubsystemGroup::Member::update (double delta_time_sec)
00306 {
00307 elapsed_sec += delta_time_sec;
00308 if (elapsed_sec >= min_step_sec) {
00309 if (!subsystem->is_suspended()) {
00310 subsystem->update(elapsed_sec);
00311 elapsed_sec = 0;
00312 }
00313 }
00314 }
00315
00316
00317 void
00318 SGSubsystemGroup::Member::printTimingInformation(double time)
00319 {
00320 if (collectTimeStats) {
00321 SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
00322 subsystem->printTimingInformation();
00323 }
00324 }
00325
00326 double SGSubsystemGroup::Member::getTimeWarningThreshold()
00327 {
00328 return (timeStat.mean() + 3 * timeStat.stdDev());
00329 }
00330
00331 void SGSubsystemGroup::Member::updateExecutionTime(double time)
00332 {
00333 if (collectTimeStats) {
00334 timeStat += time;
00335 }
00336 }
00337
00338
00339
00340
00341
00343
00345
00346
00347 SGSubsystemMgr::SGSubsystemMgr ()
00348 {
00349 }
00350
00351 SGSubsystemMgr::~SGSubsystemMgr ()
00352 {
00353 }
00354
00355 void
00356 SGSubsystemMgr::init ()
00357 {
00358 for (int i = 0; i < MAX_GROUPS; i++)
00359 _groups[i].init();
00360 }
00361
00362 void
00363 SGSubsystemMgr::postinit ()
00364 {
00365 for (int i = 0; i < MAX_GROUPS; i++)
00366 _groups[i].postinit();
00367 }
00368
00369 void
00370 SGSubsystemMgr::reinit ()
00371 {
00372 for (int i = 0; i < MAX_GROUPS; i++)
00373 _groups[i].reinit();
00374 }
00375
00376 void
00377 SGSubsystemMgr::bind ()
00378 {
00379 for (int i = 0; i < MAX_GROUPS; i++)
00380 _groups[i].bind();
00381 }
00382
00383 void
00384 SGSubsystemMgr::unbind ()
00385 {
00386
00387 for (int i = MAX_GROUPS-1; i >= 0; i--)
00388 _groups[i].unbind();
00389 }
00390
00391 void
00392 SGSubsystemMgr::update (double delta_time_sec)
00393 {
00394 for (int i = 0; i < MAX_GROUPS; i++) {
00395 _groups[i].update(delta_time_sec);
00396 }
00397 }
00398
00399 void
00400 SGSubsystemMgr::collectDebugTiming(bool collect)
00401 {
00402 for (int i = 0; i < MAX_GROUPS; i++) {
00403 _groups[i].collectDebugTiming(collect);
00404 }
00405 }
00406
00407 void
00408 SGSubsystemMgr::suspend ()
00409 {
00410 for (int i = 0; i < MAX_GROUPS; i++)
00411 _groups[i].suspend();
00412 }
00413
00414 void
00415 SGSubsystemMgr::resume ()
00416 {
00417 for (int i = 0; i < MAX_GROUPS; i++)
00418 _groups[i].resume();
00419 }
00420
00421 bool
00422 SGSubsystemMgr::is_suspended () const
00423 {
00424 return false;
00425 }
00426
00427 void
00428 SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
00429 GroupType group, double min_time_sec)
00430 {
00431 SG_LOG(SG_GENERAL, SG_INFO, "Adding subsystem " << name);
00432 get_group(group)->set_subsystem(name, subsystem, min_time_sec);
00433
00434 if (_subsystem_map.find(name) != _subsystem_map.end()) {
00435 SG_LOG(SG_GENERAL, SG_ALERT, "Adding duplicate subsystem " << name);
00436 throw sg_exception("duplicate subsystem");
00437 }
00438 _subsystem_map[name] = subsystem;
00439 }
00440
00441 SGSubsystemGroup *
00442 SGSubsystemMgr::get_group (GroupType group)
00443 {
00444 return &(_groups[group]);
00445 }
00446
00447 SGSubsystem *
00448 SGSubsystemMgr::get_subsystem (const string &name)
00449 {
00450 map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
00451
00452 if (s == _subsystem_map.end())
00453 return 0;
00454 else
00455 return s->second;
00456 }
00457
00458