2 #include <simgear/debug/logstream.hxx>
3 #include <simgear/timing/timestamp.hxx>
5 #include "exception.hxx"
6 #include "subsystem_mgr.hxx"
10 ////////////////////////////////////////////////////////////////////////
11 // Implementation of SGSubsystem
12 ////////////////////////////////////////////////////////////////////////
15 SGSubsystem::SGSubsystem ()
20 SGSubsystem::~SGSubsystem ()
30 SGSubsystem::postinit ()
35 SGSubsystem::reinit ()
45 SGSubsystem::unbind ()
50 SGSubsystem::suspend ()
56 SGSubsystem::suspend (bool suspended)
58 _suspended = suspended;
62 SGSubsystem::resume ()
68 SGSubsystem::is_suspended () const
75 SGSubsystem::printTimingInformation ()
77 SGTimeStamp startTime, endTime;
79 for ( eventTimeVecIterator i = timingInfo.begin();
80 i != timingInfo.end();
82 if (i == timingInfo.begin()) {
83 startTime = i->getTime();
85 endTime = i->getTime();
86 duration = (endTime - startTime);
88 SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp : " << i->getName() << " takes " << duration << " usec.");
95 void SGSubsystem::stamp(string name)
99 timingInfo.push_back(TimingInfo(name, now));
103 ////////////////////////////////////////////////////////////////////////
104 // Implementation of SGSubsystemGroup.
105 ////////////////////////////////////////////////////////////////////////
107 SGSubsystemGroup::SGSubsystemGroup ()
111 SGSubsystemGroup::~SGSubsystemGroup ()
113 for (unsigned int i = 0; i < _members.size(); i++)
115 _members[i]->printTimingStatistics();
121 SGSubsystemGroup::init ()
123 for (unsigned int i = 0; i < _members.size(); i++)
124 _members[i]->subsystem->init();
128 SGSubsystemGroup::postinit ()
130 for (unsigned int i = 0; i < _members.size(); i++)
131 _members[i]->subsystem->postinit();
135 SGSubsystemGroup::reinit ()
137 for (unsigned int i = 0; i < _members.size(); i++)
138 _members[i]->subsystem->reinit();
142 SGSubsystemGroup::bind ()
144 for (unsigned int i = 0; i < _members.size(); i++)
145 _members[i]->subsystem->bind();
149 SGSubsystemGroup::unbind ()
151 for (unsigned int i = 0; i < _members.size(); i++)
152 _members[i]->subsystem->unbind();
156 SGSubsystemGroup::update (double delta_time_sec)
158 for (unsigned int i = 0; i < _members.size(); i++)
160 SGTimeStamp start, now;
162 _members[i]->update(delta_time_sec); // indirect call
164 long b = ( now - start );
165 _members[i]->updateExecutionTime(b);
166 double threshold = _members[i]->getTimeWarningThreshold();
167 if (( b > threshold ) && (b > 10000)) {
168 _members[i]->printTimingInformation(b);
174 SGSubsystemGroup::collectDebugTiming(bool collect)
176 for (unsigned int i = 0; i < _members.size(); i++)
178 _members[i]->collectDebugTiming(collect);
183 SGSubsystemGroup::suspend ()
185 for (unsigned int i = 0; i < _members.size(); i++)
186 _members[i]->subsystem->suspend();
190 SGSubsystemGroup::resume ()
192 for (unsigned int i = 0; i < _members.size(); i++)
193 _members[i]->subsystem->resume();
197 SGSubsystemGroup::is_suspended () const
203 SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
206 Member * member = get_member(name, true);
207 if (member->subsystem != 0)
208 delete member->subsystem;
210 member->subsystem = subsystem;
211 member->min_step_sec = min_step_sec;
215 SGSubsystemGroup::get_subsystem (const string &name)
217 Member * member = get_member(name);
219 return member->subsystem;
225 SGSubsystemGroup::remove_subsystem (const string &name)
227 for (unsigned int i = 0; i < _members.size(); i++) {
228 if (name == _members[i]->name) {
229 _members.erase(_members.begin() + i);
236 SGSubsystemGroup::Member::printTimingStatistics ()
238 if (collectTimeStats) {
239 double minTime = timeStat.min() / 1000;
240 double maxTime = timeStat.max() / 1000;
241 double meanTime = timeStat.mean() / 1000;
242 double stddev = timeStat.stdDev() / 1000;
245 snprintf(buffer, 256, "Timing summary for %20s.\n"
246 "- mean time: %04.2f ms.\n"
247 "- min time : %04.2f ms.\n"
248 "- max time : %04.2f ms.\n"
249 "- stddev : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev);
250 SG_LOG(SG_GENERAL, SG_ALERT, buffer);
256 SGSubsystemGroup::has_subsystem (const string &name) const
258 return (((SGSubsystemGroup *)this)->get_member(name) != 0);
261 SGSubsystemGroup::Member *
262 SGSubsystemGroup::get_member (const string &name, bool create)
264 for (unsigned int i = 0; i < _members.size(); i++) {
265 if (_members[i]->name == name)
269 Member * member = new Member;
270 _members.push_back(member);
279 ////////////////////////////////////////////////////////////////////////
280 // Implementation of SGSubsystemGroup::Member
281 ////////////////////////////////////////////////////////////////////////
284 SGSubsystemGroup::Member::Member ()
289 collectTimeStats(false)
293 SGSubsystemGroup::Member::Member (const Member &)
298 SGSubsystemGroup::Member::~Member ()
304 SGSubsystemGroup::Member::update (double delta_time_sec)
306 elapsed_sec += delta_time_sec;
307 if (elapsed_sec >= min_step_sec) {
308 if (!subsystem->is_suspended()) {
309 subsystem->update(elapsed_sec);
317 SGSubsystemGroup::Member::printTimingInformation(double time)
319 if (collectTimeStats) {
320 SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
321 subsystem->printTimingInformation();
325 double SGSubsystemGroup::Member::getTimeWarningThreshold()
327 return (timeStat.mean() + 3 * timeStat.stdDev());
330 void SGSubsystemGroup::Member::updateExecutionTime(double time)
332 if (collectTimeStats) {
341 ////////////////////////////////////////////////////////////////////////
342 // Implementation of SGSubsystemMgr.
343 ////////////////////////////////////////////////////////////////////////
346 SGSubsystemMgr::SGSubsystemMgr ()
350 SGSubsystemMgr::~SGSubsystemMgr ()
355 SGSubsystemMgr::init ()
357 for (int i = 0; i < MAX_GROUPS; i++)
362 SGSubsystemMgr::postinit ()
364 for (int i = 0; i < MAX_GROUPS; i++)
365 _groups[i].postinit();
369 SGSubsystemMgr::reinit ()
371 for (int i = 0; i < MAX_GROUPS; i++)
376 SGSubsystemMgr::bind ()
378 for (int i = 0; i < MAX_GROUPS; i++)
383 SGSubsystemMgr::unbind ()
385 for (int i = 0; i < MAX_GROUPS; i++)
390 SGSubsystemMgr::update (double delta_time_sec)
392 for (int i = 0; i < MAX_GROUPS; i++) {
393 _groups[i].update(delta_time_sec);
398 SGSubsystemMgr::collectDebugTiming(bool collect)
400 for (int i = 0; i < MAX_GROUPS; i++) {
401 _groups[i].collectDebugTiming(collect);
406 SGSubsystemMgr::suspend ()
408 for (int i = 0; i < MAX_GROUPS; i++)
409 _groups[i].suspend();
413 SGSubsystemMgr::resume ()
415 for (int i = 0; i < MAX_GROUPS; i++)
420 SGSubsystemMgr::is_suspended () const
426 SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
427 GroupType group, double min_time_sec)
429 SG_LOG(SG_GENERAL, SG_INFO, "Adding subsystem " << name);
430 get_group(group)->set_subsystem(name, subsystem, min_time_sec);
432 if (_subsystem_map.find(name) != _subsystem_map.end()) {
433 SG_LOG(SG_GENERAL, SG_ALERT, "Adding duplicate subsystem " << name);
434 throw sg_exception("duplicate subsystem");
436 _subsystem_map[name] = subsystem;
440 SGSubsystemMgr::get_group (GroupType group)
442 return &(_groups[group]);
446 SGSubsystemMgr::get_subsystem (const string &name)
448 map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
450 if (s == _subsystem_map.end())