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;
78 for ( eventTimeVecIterator i = timingInfo.begin();
79 i != timingInfo.end();
81 if (i == timingInfo.begin()) {
82 startTime = i->getTime();
84 SGTimeStamp endTime = i->getTime();
85 SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp : "
86 << i->getName() << " takes " << endTime - startTime
95 void SGSubsystem::stamp(const string& name)
97 timingInfo.push_back(TimingInfo(name, SGTimeStamp::now()));
101 ////////////////////////////////////////////////////////////////////////
102 // Implementation of SGSubsystemGroup.
103 ////////////////////////////////////////////////////////////////////////
105 SGSubsystemGroup::SGSubsystemGroup ()
109 SGSubsystemGroup::~SGSubsystemGroup ()
111 for (unsigned int i = 0; i < _members.size(); i++)
113 _members[i]->printTimingStatistics();
119 SGSubsystemGroup::init ()
121 for (unsigned int i = 0; i < _members.size(); i++)
122 _members[i]->subsystem->init();
126 SGSubsystemGroup::postinit ()
128 for (unsigned int i = 0; i < _members.size(); i++)
129 _members[i]->subsystem->postinit();
133 SGSubsystemGroup::reinit ()
135 for (unsigned int i = 0; i < _members.size(); i++)
136 _members[i]->subsystem->reinit();
140 SGSubsystemGroup::bind ()
142 for (unsigned int i = 0; i < _members.size(); i++)
143 _members[i]->subsystem->bind();
147 SGSubsystemGroup::unbind ()
149 for (unsigned int i = 0; i < _members.size(); i++)
150 _members[i]->subsystem->unbind();
154 SGSubsystemGroup::update (double delta_time_sec)
156 for (unsigned int i = 0; i < _members.size(); i++)
158 SGTimeStamp timeStamp = SGTimeStamp::now();
159 _members[i]->update(delta_time_sec); // indirect call
160 timeStamp = timeStamp - SGTimeStamp::now();
161 double b = timeStamp.toUSecs();
162 _members[i]->updateExecutionTime(b);
163 double threshold = _members[i]->getTimeWarningThreshold();
164 if (( b > threshold ) && (b > 10000)) {
165 _members[i]->printTimingInformation(b);
171 SGSubsystemGroup::collectDebugTiming(bool collect)
173 for (unsigned int i = 0; i < _members.size(); i++)
175 _members[i]->collectDebugTiming(collect);
180 SGSubsystemGroup::suspend ()
182 for (unsigned int i = 0; i < _members.size(); i++)
183 _members[i]->subsystem->suspend();
187 SGSubsystemGroup::resume ()
189 for (unsigned int i = 0; i < _members.size(); i++)
190 _members[i]->subsystem->resume();
194 SGSubsystemGroup::is_suspended () const
200 SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
203 Member * member = get_member(name, true);
204 if (member->subsystem != 0)
205 delete member->subsystem;
207 member->subsystem = subsystem;
208 member->min_step_sec = min_step_sec;
212 SGSubsystemGroup::get_subsystem (const string &name)
214 Member * member = get_member(name);
216 return member->subsystem;
222 SGSubsystemGroup::remove_subsystem (const string &name)
224 for (unsigned int i = 0; i < _members.size(); i++) {
225 if (name == _members[i]->name) {
226 _members.erase(_members.begin() + i);
233 SGSubsystemGroup::Member::printTimingStatistics ()
235 if (collectTimeStats) {
236 double minTime = timeStat.min() / 1000;
237 double maxTime = timeStat.max() / 1000;
238 double meanTime = timeStat.mean() / 1000;
239 double stddev = timeStat.stdDev() / 1000;
242 snprintf(buffer, 256, "Timing summary for %20s.\n"
243 "- mean time: %04.2f ms.\n"
244 "- min time : %04.2f ms.\n"
245 "- max time : %04.2f ms.\n"
246 "- stddev : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev);
247 SG_LOG(SG_GENERAL, SG_ALERT, buffer);
253 SGSubsystemGroup::has_subsystem (const string &name) const
255 return (((SGSubsystemGroup *)this)->get_member(name) != 0);
258 SGSubsystemGroup::Member *
259 SGSubsystemGroup::get_member (const string &name, bool create)
261 for (unsigned int i = 0; i < _members.size(); i++) {
262 if (_members[i]->name == name)
266 Member * member = new Member;
267 _members.push_back(member);
276 ////////////////////////////////////////////////////////////////////////
277 // Implementation of SGSubsystemGroup::Member
278 ////////////////////////////////////////////////////////////////////////
281 SGSubsystemGroup::Member::Member ()
286 collectTimeStats(false)
290 // This shouldn't be called due to subsystem pointer ownership issues.
291 SGSubsystemGroup::Member::Member (const Member &)
295 SGSubsystemGroup::Member::~Member ()
301 SGSubsystemGroup::Member::update (double delta_time_sec)
303 elapsed_sec += delta_time_sec;
304 if (elapsed_sec >= min_step_sec) {
305 if (!subsystem->is_suspended()) {
306 subsystem->update(elapsed_sec);
314 SGSubsystemGroup::Member::printTimingInformation(double time)
316 if (collectTimeStats) {
317 SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
318 subsystem->printTimingInformation();
322 double SGSubsystemGroup::Member::getTimeWarningThreshold()
324 return (timeStat.mean() + 3 * timeStat.stdDev());
327 void SGSubsystemGroup::Member::updateExecutionTime(double time)
329 if (collectTimeStats) {
338 ////////////////////////////////////////////////////////////////////////
339 // Implementation of SGSubsystemMgr.
340 ////////////////////////////////////////////////////////////////////////
343 SGSubsystemMgr::SGSubsystemMgr ()
347 SGSubsystemMgr::~SGSubsystemMgr ()
352 SGSubsystemMgr::init ()
354 for (int i = 0; i < MAX_GROUPS; i++)
359 SGSubsystemMgr::postinit ()
361 for (int i = 0; i < MAX_GROUPS; i++)
362 _groups[i].postinit();
366 SGSubsystemMgr::reinit ()
368 for (int i = 0; i < MAX_GROUPS; i++)
373 SGSubsystemMgr::bind ()
375 for (int i = 0; i < MAX_GROUPS; i++)
380 SGSubsystemMgr::unbind ()
382 for (int i = 0; i < MAX_GROUPS; i++)
387 SGSubsystemMgr::update (double delta_time_sec)
389 for (int i = 0; i < MAX_GROUPS; i++) {
390 _groups[i].update(delta_time_sec);
395 SGSubsystemMgr::collectDebugTiming(bool collect)
397 for (int i = 0; i < MAX_GROUPS; i++) {
398 _groups[i].collectDebugTiming(collect);
403 SGSubsystemMgr::suspend ()
405 for (int i = 0; i < MAX_GROUPS; i++)
406 _groups[i].suspend();
410 SGSubsystemMgr::resume ()
412 for (int i = 0; i < MAX_GROUPS; i++)
417 SGSubsystemMgr::is_suspended () const
423 SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
424 GroupType group, double min_time_sec)
426 SG_LOG(SG_GENERAL, SG_INFO, "Adding subsystem " << name);
427 get_group(group)->set_subsystem(name, subsystem, min_time_sec);
429 if (_subsystem_map.find(name) != _subsystem_map.end()) {
430 SG_LOG(SG_GENERAL, SG_ALERT, "Adding duplicate subsystem " << name);
431 throw sg_exception("duplicate subsystem");
433 _subsystem_map[name] = subsystem;
437 SGSubsystemMgr::get_group (GroupType group)
439 return &(_groups[group]);
443 SGSubsystemMgr::get_subsystem (const string &name)
445 map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
447 if (s == _subsystem_map.end())