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