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 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 timeStamp = SGTimeStamp::now();
161 _members[i]->update(delta_time_sec); // indirect call
162 timeStamp = timeStamp - SGTimeStamp::now();
163 double b = timeStamp.toUSecs();
164 _members[i]->updateExecutionTime(b);
165 double threshold = _members[i]->getTimeWarningThreshold();
166 if (( b > threshold ) && (b > 10000)) {
167 _members[i]->printTimingInformation(b);
173 SGSubsystemGroup::collectDebugTiming(bool collect)
175 for (unsigned int i = 0; i < _members.size(); i++)
177 _members[i]->collectDebugTiming(collect);
182 SGSubsystemGroup::suspend ()
184 for (unsigned int i = 0; i < _members.size(); i++)
185 _members[i]->subsystem->suspend();
189 SGSubsystemGroup::resume ()
191 for (unsigned int i = 0; i < _members.size(); i++)
192 _members[i]->subsystem->resume();
196 SGSubsystemGroup::is_suspended () const
202 SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
205 Member * member = get_member(name, true);
206 if (member->subsystem != 0)
207 delete member->subsystem;
209 member->subsystem = subsystem;
210 member->min_step_sec = min_step_sec;
214 SGSubsystemGroup::get_subsystem (const string &name)
216 Member * member = get_member(name);
218 return member->subsystem;
224 SGSubsystemGroup::remove_subsystem (const string &name)
226 for (unsigned int i = 0; i < _members.size(); i++) {
227 if (name == _members[i]->name) {
228 _members.erase(_members.begin() + i);
235 SGSubsystemGroup::Member::printTimingStatistics ()
237 if (collectTimeStats) {
238 double minTime = timeStat.min() / 1000;
239 double maxTime = timeStat.max() / 1000;
240 double meanTime = timeStat.mean() / 1000;
241 double stddev = timeStat.stdDev() / 1000;
244 snprintf(buffer, 256, "Timing summary for %20s.\n"
245 "- mean time: %04.2f ms.\n"
246 "- min time : %04.2f ms.\n"
247 "- max time : %04.2f ms.\n"
248 "- stddev : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev);
249 SG_LOG(SG_GENERAL, SG_ALERT, buffer);
255 SGSubsystemGroup::has_subsystem (const string &name) const
257 return (((SGSubsystemGroup *)this)->get_member(name) != 0);
260 SGSubsystemGroup::Member *
261 SGSubsystemGroup::get_member (const string &name, bool create)
263 for (unsigned int i = 0; i < _members.size(); i++) {
264 if (_members[i]->name == name)
268 Member * member = new Member;
269 _members.push_back(member);
278 ////////////////////////////////////////////////////////////////////////
279 // Implementation of SGSubsystemGroup::Member
280 ////////////////////////////////////////////////////////////////////////
283 SGSubsystemGroup::Member::Member ()
288 collectTimeStats(false)
292 // This shouldn't be called due to subsystem pointer ownership issues.
293 SGSubsystemGroup::Member::Member (const Member &)
297 SGSubsystemGroup::Member::~Member ()
303 SGSubsystemGroup::Member::update (double delta_time_sec)
305 elapsed_sec += delta_time_sec;
306 if (elapsed_sec >= min_step_sec) {
307 if (!subsystem->is_suspended()) {
308 subsystem->update(elapsed_sec);
316 SGSubsystemGroup::Member::printTimingInformation(double time)
318 if (collectTimeStats) {
319 SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
320 subsystem->printTimingInformation();
324 double SGSubsystemGroup::Member::getTimeWarningThreshold()
326 return (timeStat.mean() + 3 * timeStat.stdDev());
329 void SGSubsystemGroup::Member::updateExecutionTime(double time)
331 if (collectTimeStats) {
340 ////////////////////////////////////////////////////////////////////////
341 // Implementation of SGSubsystemMgr.
342 ////////////////////////////////////////////////////////////////////////
345 SGSubsystemMgr::SGSubsystemMgr ()
349 SGSubsystemMgr::~SGSubsystemMgr ()
354 SGSubsystemMgr::init ()
356 for (int i = 0; i < MAX_GROUPS; i++)
361 SGSubsystemMgr::postinit ()
363 for (int i = 0; i < MAX_GROUPS; i++)
364 _groups[i].postinit();
368 SGSubsystemMgr::reinit ()
370 for (int i = 0; i < MAX_GROUPS; i++)
375 SGSubsystemMgr::bind ()
377 for (int i = 0; i < MAX_GROUPS; i++)
382 SGSubsystemMgr::unbind ()
384 for (int i = 0; i < MAX_GROUPS; i++)
389 SGSubsystemMgr::update (double delta_time_sec)
391 for (int i = 0; i < MAX_GROUPS; i++) {
392 _groups[i].update(delta_time_sec);
397 SGSubsystemMgr::collectDebugTiming(bool collect)
399 for (int i = 0; i < MAX_GROUPS; i++) {
400 _groups[i].collectDebugTiming(collect);
405 SGSubsystemMgr::suspend ()
407 for (int i = 0; i < MAX_GROUPS; i++)
408 _groups[i].suspend();
412 SGSubsystemMgr::resume ()
414 for (int i = 0; i < MAX_GROUPS; i++)
419 SGSubsystemMgr::is_suspended () const
425 SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
426 GroupType group, double min_time_sec)
428 SG_LOG(SG_GENERAL, SG_INFO, "Adding subsystem " << name);
429 get_group(group)->set_subsystem(name, subsystem, min_time_sec);
431 if (_subsystem_map.find(name) != _subsystem_map.end()) {
432 SG_LOG(SG_GENERAL, SG_ALERT, "Adding duplicate subsystem " << name);
433 throw sg_exception("duplicate subsystem");
435 _subsystem_map[name] = subsystem;
439 SGSubsystemMgr::get_group (GroupType group)
441 return &(_groups[group]);
445 SGSubsystemMgr::get_subsystem (const string &name)
447 map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
449 if (s == _subsystem_map.end())