]> git.mxchange.org Git - simgear.git/blob - simgear/structure/subsystem_mgr.cxx
Merge branch 'ehofman/sound'
[simgear.git] / simgear / structure / subsystem_mgr.cxx
1
2 #include <simgear/debug/logstream.hxx>
3 #include <simgear/timing/timestamp.hxx>
4
5 #include "exception.hxx"
6 #include "subsystem_mgr.hxx"
7
8 #include <simgear/math/SGMath.hxx>
9
10
11 \f
12 ////////////////////////////////////////////////////////////////////////
13 // Implementation of SGSubsystem
14 ////////////////////////////////////////////////////////////////////////
15
16
17 SGSubsystem::SGSubsystem ()
18   : _suspended(false)
19 {
20 }
21
22 SGSubsystem::~SGSubsystem ()
23 {
24 }
25
26 void
27 SGSubsystem::init ()
28 {
29 }
30
31 void
32 SGSubsystem::postinit ()
33 {
34 }
35
36 void
37 SGSubsystem::reinit ()
38 {
39 }
40
41 void
42 SGSubsystem::bind ()
43 {
44 }
45
46 void
47 SGSubsystem::unbind ()
48 {
49 }
50
51 void
52 SGSubsystem::suspend ()
53 {
54   _suspended = true;
55 }
56
57 void
58 SGSubsystem::suspend (bool suspended)
59 {
60   _suspended = suspended;
61 }
62
63 void
64 SGSubsystem::resume ()
65 {
66   _suspended = false;
67 }
68
69 bool
70 SGSubsystem::is_suspended () const
71 {
72   return _suspended;
73 }
74
75
76 void
77 SGSubsystem::printTimingInformation ()
78 {
79    SGTimeStamp startTime;
80    for ( eventTimeVecIterator i = timingInfo.begin();
81           i != timingInfo.end();
82           i++) {
83        if (i == timingInfo.begin()) {
84            startTime = i->getTime();
85        } else {
86            SGTimeStamp endTime = i->getTime();
87            SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp :   "
88                   << i->getName() << " takes " << endTime - startTime
89                   << " sec.");
90            startTime = endTime;
91        }
92    }
93 }
94
95
96
97 void SGSubsystem::stamp(const string& name)
98 {
99     timingInfo.push_back(TimingInfo(name, SGTimeStamp::now()));
100 }
101
102 \f
103 ////////////////////////////////////////////////////////////////////////
104 // Implementation of SGSubsystemGroup.
105 ////////////////////////////////////////////////////////////////////////
106
107 SGSubsystemGroup::SGSubsystemGroup ()
108 {
109 }
110
111 SGSubsystemGroup::~SGSubsystemGroup ()
112 {
113     // reverse order to prevent order dependency problems
114     for (unsigned int i = _members.size(); i > 0; i--)
115     {
116         _members[i-1]->printTimingStatistics();
117         delete _members[i-1];
118     }
119 }
120
121 void
122 SGSubsystemGroup::init ()
123 {
124     for (unsigned int i = 0; i < _members.size(); i++)
125         _members[i]->subsystem->init();
126 }
127
128 void
129 SGSubsystemGroup::postinit ()
130 {
131     for (unsigned int i = 0; i < _members.size(); i++)
132         _members[i]->subsystem->postinit();
133 }
134
135 void
136 SGSubsystemGroup::reinit ()
137 {
138     for (unsigned int i = 0; i < _members.size(); i++)
139         _members[i]->subsystem->reinit();
140 }
141
142 void
143 SGSubsystemGroup::bind ()
144 {
145     for (unsigned int i = 0; i < _members.size(); i++)
146         _members[i]->subsystem->bind();
147 }
148
149 void
150 SGSubsystemGroup::unbind ()
151 {
152     // reverse order to prevent order dependency problems
153     for (unsigned int i = _members.size(); i > 0; i--)
154        _members[i-1]->subsystem->unbind();
155 }
156
157 void
158 SGSubsystemGroup::update (double delta_time_sec)
159 {
160     for (unsigned int i = 0; i < _members.size(); i++)
161     {
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);
170          }
171     }
172 }
173
174 void 
175 SGSubsystemGroup::collectDebugTiming(bool collect)
176 {
177     for (unsigned int i = 0; i < _members.size(); i++)
178     {
179         _members[i]->collectDebugTiming(collect);
180     }
181 }
182
183 void
184 SGSubsystemGroup::suspend ()
185 {
186     for (unsigned int i = 0; i < _members.size(); i++)
187         _members[i]->subsystem->suspend();
188 }
189
190 void
191 SGSubsystemGroup::resume ()
192 {
193     for (unsigned int i = 0; i < _members.size(); i++)
194         _members[i]->subsystem->resume();
195 }
196
197 bool
198 SGSubsystemGroup::is_suspended () const
199 {
200     return false;
201 }
202
203 void
204 SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
205                                  double min_step_sec)
206 {
207     Member * member = get_member(name, true);
208     if (member->subsystem != 0)
209         delete member->subsystem;
210     member->name = name;
211     member->subsystem = subsystem;
212     member->min_step_sec = min_step_sec;
213 }
214
215 SGSubsystem *
216 SGSubsystemGroup::get_subsystem (const string &name)
217 {
218     Member * member = get_member(name);
219     if (member != 0)
220         return member->subsystem;
221     else
222         return 0;
223 }
224
225 void
226 SGSubsystemGroup::remove_subsystem (const string &name)
227 {
228     for (unsigned int i = 0; i < _members.size(); i++) {
229         if (name == _members[i]->name) {
230             _members.erase(_members.begin() + i);
231             return;
232         }
233     }
234 }
235
236 void
237 SGSubsystemGroup::Member::printTimingStatistics ()
238 {
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;
244
245         char buffer[256];
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);
252     }
253 }
254
255
256 bool
257 SGSubsystemGroup::has_subsystem (const string &name) const
258 {
259     return (((SGSubsystemGroup *)this)->get_member(name) != 0);
260 }
261
262 SGSubsystemGroup::Member *
263 SGSubsystemGroup::get_member (const string &name, bool create)
264 {
265     for (unsigned int i = 0; i < _members.size(); i++) {
266         if (_members[i]->name == name)
267             return _members[i];
268     }
269     if (create) {
270         Member * member = new Member;
271         _members.push_back(member);
272         return member;
273     } else {
274         return 0;
275     }
276 }
277
278
279 \f
280 ////////////////////////////////////////////////////////////////////////
281 // Implementation of SGSubsystemGroup::Member
282 ////////////////////////////////////////////////////////////////////////
283
284
285 SGSubsystemGroup::Member::Member ()
286     : name(""),
287       subsystem(0),
288       min_step_sec(0),
289       elapsed_sec(0),
290       collectTimeStats(false)
291 {
292 }
293
294 // This shouldn't be called due to subsystem pointer ownership issues.
295 SGSubsystemGroup::Member::Member (const Member &)
296 {
297 }
298
299 SGSubsystemGroup::Member::~Member ()
300 {
301     delete subsystem;
302 }
303
304 void
305 SGSubsystemGroup::Member::update (double delta_time_sec)
306 {
307     elapsed_sec += delta_time_sec;
308     if (elapsed_sec >= min_step_sec) {
309         if (!subsystem->is_suspended()) {
310             subsystem->update(elapsed_sec);
311             elapsed_sec = 0;
312         }
313     }
314 }
315
316
317 void 
318 SGSubsystemGroup::Member::printTimingInformation(double time)
319 {
320      if (collectTimeStats) {
321          SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
322          subsystem->printTimingInformation();
323      }
324 }
325
326 double SGSubsystemGroup::Member::getTimeWarningThreshold()
327 {
328     return (timeStat.mean() + 3 * timeStat.stdDev());
329 }
330
331 void SGSubsystemGroup::Member::updateExecutionTime(double time)
332 {
333     if (collectTimeStats) {
334         timeStat += time;
335     }
336 }
337
338
339
340
341 \f
342 ////////////////////////////////////////////////////////////////////////
343 // Implementation of SGSubsystemMgr.
344 ////////////////////////////////////////////////////////////////////////
345
346
347 SGSubsystemMgr::SGSubsystemMgr ()
348 {
349 }
350
351 SGSubsystemMgr::~SGSubsystemMgr ()
352 {
353 }
354
355 void
356 SGSubsystemMgr::init ()
357 {
358     for (int i = 0; i < MAX_GROUPS; i++)
359             _groups[i].init();
360 }
361
362 void
363 SGSubsystemMgr::postinit ()
364 {
365     for (int i = 0; i < MAX_GROUPS; i++)
366             _groups[i].postinit();
367 }
368
369 void
370 SGSubsystemMgr::reinit ()
371 {
372     for (int i = 0; i < MAX_GROUPS; i++)
373             _groups[i].reinit();
374 }
375
376 void
377 SGSubsystemMgr::bind ()
378 {
379     for (int i = 0; i < MAX_GROUPS; i++)
380         _groups[i].bind();
381 }
382
383 void
384 SGSubsystemMgr::unbind ()
385 {
386     // reverse order to prevent order dependency problems
387     for (int i = MAX_GROUPS-1; i >= 0; i--)
388         _groups[i].unbind();
389 }
390
391 void
392 SGSubsystemMgr::update (double delta_time_sec)
393 {
394     for (int i = 0; i < MAX_GROUPS; i++) {
395         _groups[i].update(delta_time_sec);
396     }
397 }
398
399 void 
400 SGSubsystemMgr::collectDebugTiming(bool collect)
401 {
402     for (int i = 0; i < MAX_GROUPS; i++) {
403         _groups[i].collectDebugTiming(collect);
404     }
405 }
406
407 void
408 SGSubsystemMgr::suspend ()
409 {
410     for (int i = 0; i < MAX_GROUPS; i++)
411         _groups[i].suspend();
412 }
413
414 void
415 SGSubsystemMgr::resume ()
416 {
417     for (int i = 0; i < MAX_GROUPS; i++)
418         _groups[i].resume();
419 }
420
421 bool
422 SGSubsystemMgr::is_suspended () const
423 {
424     return false;
425 }
426
427 void
428 SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
429                      GroupType group, double min_time_sec)
430 {
431     SG_LOG(SG_GENERAL, SG_INFO, "Adding subsystem " << name);
432     get_group(group)->set_subsystem(name, subsystem, min_time_sec);
433
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");
437     }
438     _subsystem_map[name] = subsystem;
439 }
440
441 SGSubsystemGroup *
442 SGSubsystemMgr::get_group (GroupType group)
443 {
444     return &(_groups[group]);
445 }
446
447 SGSubsystem *
448 SGSubsystemMgr::get_subsystem (const string &name)
449 {
450     map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
451
452     if (s == _subsystem_map.end())
453         return 0;
454     else
455         return s->second;
456 }
457
458 // end of fgfs.cxx