2 #include <simgear/debug/logstream.hxx>
3 #include <simgear/timing/timestamp.hxx>
5 #include "exception.hxx"
6 #include "subsystem_mgr.hxx"
8 #include <simgear/math/SGMath.hxx>
12 ////////////////////////////////////////////////////////////////////////
13 // Implementation of SGSubsystem
14 ////////////////////////////////////////////////////////////////////////
17 SGSubsystem::SGSubsystem ()
22 SGSubsystem::~SGSubsystem ()
32 SGSubsystem::postinit ()
37 SGSubsystem::reinit ()
47 SGSubsystem::unbind ()
52 SGSubsystem::suspend ()
58 SGSubsystem::suspend (bool suspended)
60 _suspended = suspended;
64 SGSubsystem::resume ()
70 SGSubsystem::is_suspended () const
77 SGSubsystem::printTimingInformation ()
79 SGTimeStamp startTime;
80 for ( eventTimeVecIterator i = timingInfo.begin();
81 i != timingInfo.end();
83 if (i == timingInfo.begin()) {
84 startTime = i->getTime();
86 SGTimeStamp endTime = i->getTime();
87 SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp : "
88 << i->getName() << " takes " << endTime - startTime
97 void SGSubsystem::stamp(const string& name)
99 timingInfo.push_back(TimingInfo(name, SGTimeStamp::now()));
103 ////////////////////////////////////////////////////////////////////////
104 // Implementation of SGSubsystemGroup.
105 ////////////////////////////////////////////////////////////////////////
107 SGSubsystemGroup::SGSubsystemGroup ()
111 SGSubsystemGroup::~SGSubsystemGroup ()
113 // reverse order to prevent order dependency problems
114 for (unsigned int i = _members.size(); i > 0; i--)
116 _members[i-1]->printTimingStatistics();
117 delete _members[i-1];
122 SGSubsystemGroup::init ()
124 for (unsigned int i = 0; i < _members.size(); i++)
125 _members[i]->subsystem->init();
129 SGSubsystemGroup::postinit ()
131 for (unsigned int i = 0; i < _members.size(); i++)
132 _members[i]->subsystem->postinit();
136 SGSubsystemGroup::reinit ()
138 for (unsigned int i = 0; i < _members.size(); i++)
139 _members[i]->subsystem->reinit();
143 SGSubsystemGroup::bind ()
145 for (unsigned int i = 0; i < _members.size(); i++)
146 _members[i]->subsystem->bind();
150 SGSubsystemGroup::unbind ()
152 // reverse order to prevent order dependency problems
153 for (unsigned int i = _members.size(); i > 0; i--)
154 _members[i-1]->subsystem->unbind();
158 SGSubsystemGroup::update (double delta_time_sec)
160 for (unsigned int i = 0; i < _members.size(); i++)
162 SGTimeStamp timeStamp = SGTimeStamp::now();
163 _members[i]->update(delta_time_sec); // indirect call
164 timeStamp = timeStamp - SGTimeStamp::now();
165 double b = timeStamp.toUSecs();
166 _members[i]->updateExecutionTime(b);
167 double threshold = _members[i]->getTimeWarningThreshold();
168 if (( b > threshold ) && (b > 10000)) {
169 _members[i]->printTimingInformation(b);
175 SGSubsystemGroup::collectDebugTiming(bool collect)
177 for (unsigned int i = 0; i < _members.size(); i++)
179 _members[i]->collectDebugTiming(collect);
184 SGSubsystemGroup::suspend ()
186 for (unsigned int i = 0; i < _members.size(); i++)
187 _members[i]->subsystem->suspend();
191 SGSubsystemGroup::resume ()
193 for (unsigned int i = 0; i < _members.size(); i++)
194 _members[i]->subsystem->resume();
198 SGSubsystemGroup::is_suspended () const
204 SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
207 Member * member = get_member(name, true);
208 if (member->subsystem != 0)
209 delete member->subsystem;
211 member->subsystem = subsystem;
212 member->min_step_sec = min_step_sec;
216 SGSubsystemGroup::get_subsystem (const string &name)
218 Member * member = get_member(name);
220 return member->subsystem;
226 SGSubsystemGroup::remove_subsystem (const string &name)
228 for (unsigned int i = 0; i < _members.size(); i++) {
229 if (name == _members[i]->name) {
230 _members.erase(_members.begin() + i);
237 SGSubsystemGroup::Member::printTimingStatistics ()
239 if (collectTimeStats) {
240 double minTime = timeStat.min() / 1000;
241 double maxTime = timeStat.max() / 1000;
242 double meanTime = timeStat.mean() / 1000;
243 double stddev = timeStat.stdDev() / 1000;
246 snprintf(buffer, 256, "Timing summary for %20s.\n"
247 "- mean time: %04.2f ms.\n"
248 "- min time : %04.2f ms.\n"
249 "- max time : %04.2f ms.\n"
250 "- stddev : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev);
251 SG_LOG(SG_GENERAL, SG_ALERT, buffer);
257 SGSubsystemGroup::has_subsystem (const string &name) const
259 return (((SGSubsystemGroup *)this)->get_member(name) != 0);
262 SGSubsystemGroup::Member *
263 SGSubsystemGroup::get_member (const string &name, bool create)
265 for (unsigned int i = 0; i < _members.size(); i++) {
266 if (_members[i]->name == name)
270 Member * member = new Member;
271 _members.push_back(member);
280 ////////////////////////////////////////////////////////////////////////
281 // Implementation of SGSubsystemGroup::Member
282 ////////////////////////////////////////////////////////////////////////
285 SGSubsystemGroup::Member::Member ()
290 collectTimeStats(false)
294 // This shouldn't be called due to subsystem pointer ownership issues.
295 SGSubsystemGroup::Member::Member (const Member &)
299 SGSubsystemGroup::Member::~Member ()
305 SGSubsystemGroup::Member::update (double delta_time_sec)
307 elapsed_sec += delta_time_sec;
308 if (elapsed_sec >= min_step_sec) {
309 if (!subsystem->is_suspended()) {
310 subsystem->update(elapsed_sec);
318 SGSubsystemGroup::Member::printTimingInformation(double time)
320 if (collectTimeStats) {
321 SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
322 subsystem->printTimingInformation();
326 double SGSubsystemGroup::Member::getTimeWarningThreshold()
328 return (timeStat.mean() + 3 * timeStat.stdDev());
331 void SGSubsystemGroup::Member::updateExecutionTime(double time)
333 if (collectTimeStats) {
342 ////////////////////////////////////////////////////////////////////////
343 // Implementation of SGSubsystemMgr.
344 ////////////////////////////////////////////////////////////////////////
347 SGSubsystemMgr::SGSubsystemMgr ()
351 SGSubsystemMgr::~SGSubsystemMgr ()
356 SGSubsystemMgr::init ()
358 for (int i = 0; i < MAX_GROUPS; i++)
363 SGSubsystemMgr::postinit ()
365 for (int i = 0; i < MAX_GROUPS; i++)
366 _groups[i].postinit();
370 SGSubsystemMgr::reinit ()
372 for (int i = 0; i < MAX_GROUPS; i++)
377 SGSubsystemMgr::bind ()
379 for (int i = 0; i < MAX_GROUPS; i++)
384 SGSubsystemMgr::unbind ()
386 // reverse order to prevent order dependency problems
387 for (int i = MAX_GROUPS-1; i >= 0; i--)
392 SGSubsystemMgr::update (double delta_time_sec)
394 for (int i = 0; i < MAX_GROUPS; i++) {
395 _groups[i].update(delta_time_sec);
400 SGSubsystemMgr::collectDebugTiming(bool collect)
402 for (int i = 0; i < MAX_GROUPS; i++) {
403 _groups[i].collectDebugTiming(collect);
408 SGSubsystemMgr::suspend ()
410 for (int i = 0; i < MAX_GROUPS; i++)
411 _groups[i].suspend();
415 SGSubsystemMgr::resume ()
417 for (int i = 0; i < MAX_GROUPS; i++)
422 SGSubsystemMgr::is_suspended () const
428 SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
429 GroupType group, double min_time_sec)
431 SG_LOG(SG_GENERAL, SG_INFO, "Adding subsystem " << name);
432 get_group(group)->set_subsystem(name, subsystem, min_time_sec);
434 if (_subsystem_map.find(name) != _subsystem_map.end()) {
435 SG_LOG(SG_GENERAL, SG_ALERT, "Adding duplicate subsystem " << name);
436 throw sg_exception("duplicate subsystem");
438 _subsystem_map[name] = subsystem;
442 SGSubsystemMgr::get_group (GroupType group)
444 return &(_groups[group]);
448 SGSubsystemMgr::get_subsystem (const string &name)
450 map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
452 if (s == _subsystem_map.end())