]> git.mxchange.org Git - simgear.git/blob - simgear/structure/subsystem_mgr.cxx
Merge branch 'frohlich/weak' into next
[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     for (unsigned int i = 0; i < _members.size(); i++)
114     {
115         _members[i]->printTimingStatistics();
116         delete _members[i];
117     }
118 }
119
120 void
121 SGSubsystemGroup::init ()
122 {
123     for (unsigned int i = 0; i < _members.size(); i++)
124         _members[i]->subsystem->init();
125 }
126
127 void
128 SGSubsystemGroup::postinit ()
129 {
130     for (unsigned int i = 0; i < _members.size(); i++)
131         _members[i]->subsystem->postinit();
132 }
133
134 void
135 SGSubsystemGroup::reinit ()
136 {
137     for (unsigned int i = 0; i < _members.size(); i++)
138         _members[i]->subsystem->reinit();
139 }
140
141 void
142 SGSubsystemGroup::bind ()
143 {
144     for (unsigned int i = 0; i < _members.size(); i++)
145         _members[i]->subsystem->bind();
146 }
147
148 void
149 SGSubsystemGroup::unbind ()
150 {
151     for (unsigned int i = 0; i < _members.size(); i++)
152         _members[i]->subsystem->unbind();
153 }
154
155 void
156 SGSubsystemGroup::update (double delta_time_sec)
157 {
158     for (unsigned int i = 0; i < _members.size(); i++)
159     {
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);
168          }
169     }
170 }
171
172 void 
173 SGSubsystemGroup::collectDebugTiming(bool collect)
174 {
175     for (unsigned int i = 0; i < _members.size(); i++)
176     {
177         _members[i]->collectDebugTiming(collect);
178     }
179 }
180
181 void
182 SGSubsystemGroup::suspend ()
183 {
184     for (unsigned int i = 0; i < _members.size(); i++)
185         _members[i]->subsystem->suspend();
186 }
187
188 void
189 SGSubsystemGroup::resume ()
190 {
191     for (unsigned int i = 0; i < _members.size(); i++)
192         _members[i]->subsystem->resume();
193 }
194
195 bool
196 SGSubsystemGroup::is_suspended () const
197 {
198     return false;
199 }
200
201 void
202 SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
203                                  double min_step_sec)
204 {
205     Member * member = get_member(name, true);
206     if (member->subsystem != 0)
207         delete member->subsystem;
208     member->name = name;
209     member->subsystem = subsystem;
210     member->min_step_sec = min_step_sec;
211 }
212
213 SGSubsystem *
214 SGSubsystemGroup::get_subsystem (const string &name)
215 {
216     Member * member = get_member(name);
217     if (member != 0)
218         return member->subsystem;
219     else
220         return 0;
221 }
222
223 void
224 SGSubsystemGroup::remove_subsystem (const string &name)
225 {
226     for (unsigned int i = 0; i < _members.size(); i++) {
227         if (name == _members[i]->name) {
228             _members.erase(_members.begin() + i);
229             return;
230         }
231     }
232 }
233
234 void
235 SGSubsystemGroup::Member::printTimingStatistics ()
236 {
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;
242
243         char buffer[256];
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);
250     }
251 }
252
253
254 bool
255 SGSubsystemGroup::has_subsystem (const string &name) const
256 {
257     return (((SGSubsystemGroup *)this)->get_member(name) != 0);
258 }
259
260 SGSubsystemGroup::Member *
261 SGSubsystemGroup::get_member (const string &name, bool create)
262 {
263     for (unsigned int i = 0; i < _members.size(); i++) {
264         if (_members[i]->name == name)
265             return _members[i];
266     }
267     if (create) {
268         Member * member = new Member;
269         _members.push_back(member);
270         return member;
271     } else {
272         return 0;
273     }
274 }
275
276
277 \f
278 ////////////////////////////////////////////////////////////////////////
279 // Implementation of SGSubsystemGroup::Member
280 ////////////////////////////////////////////////////////////////////////
281
282
283 SGSubsystemGroup::Member::Member ()
284     : name(""),
285       subsystem(0),
286       min_step_sec(0),
287       elapsed_sec(0),
288       collectTimeStats(false)
289 {
290 }
291
292 // This shouldn't be called due to subsystem pointer ownership issues.
293 SGSubsystemGroup::Member::Member (const Member &)
294 {
295 }
296
297 SGSubsystemGroup::Member::~Member ()
298 {
299     delete subsystem;
300 }
301
302 void
303 SGSubsystemGroup::Member::update (double delta_time_sec)
304 {
305     elapsed_sec += delta_time_sec;
306     if (elapsed_sec >= min_step_sec) {
307         if (!subsystem->is_suspended()) {
308             subsystem->update(elapsed_sec);
309             elapsed_sec = 0;
310         }
311     }
312 }
313
314
315 void 
316 SGSubsystemGroup::Member::printTimingInformation(double time)
317 {
318      if (collectTimeStats) {
319          SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
320          subsystem->printTimingInformation();
321      }
322 }
323
324 double SGSubsystemGroup::Member::getTimeWarningThreshold()
325 {
326     return (timeStat.mean() + 3 * timeStat.stdDev());
327 }
328
329 void SGSubsystemGroup::Member::updateExecutionTime(double time)
330 {
331     if (collectTimeStats) {
332         timeStat += time;
333     }
334 }
335
336
337
338
339 \f
340 ////////////////////////////////////////////////////////////////////////
341 // Implementation of SGSubsystemMgr.
342 ////////////////////////////////////////////////////////////////////////
343
344
345 SGSubsystemMgr::SGSubsystemMgr ()
346 {
347 }
348
349 SGSubsystemMgr::~SGSubsystemMgr ()
350 {
351 }
352
353 void
354 SGSubsystemMgr::init ()
355 {
356     for (int i = 0; i < MAX_GROUPS; i++)
357             _groups[i].init();
358 }
359
360 void
361 SGSubsystemMgr::postinit ()
362 {
363     for (int i = 0; i < MAX_GROUPS; i++)
364             _groups[i].postinit();
365 }
366
367 void
368 SGSubsystemMgr::reinit ()
369 {
370     for (int i = 0; i < MAX_GROUPS; i++)
371             _groups[i].reinit();
372 }
373
374 void
375 SGSubsystemMgr::bind ()
376 {
377     for (int i = 0; i < MAX_GROUPS; i++)
378         _groups[i].bind();
379 }
380
381 void
382 SGSubsystemMgr::unbind ()
383 {
384     for (int i = 0; i < MAX_GROUPS; i++)
385         _groups[i].unbind();
386 }
387
388 void
389 SGSubsystemMgr::update (double delta_time_sec)
390 {
391     for (int i = 0; i < MAX_GROUPS; i++) {
392         _groups[i].update(delta_time_sec);
393     }
394 }
395
396 void 
397 SGSubsystemMgr::collectDebugTiming(bool collect)
398 {
399     for (int i = 0; i < MAX_GROUPS; i++) {
400         _groups[i].collectDebugTiming(collect);
401     }
402 }
403
404 void
405 SGSubsystemMgr::suspend ()
406 {
407     for (int i = 0; i < MAX_GROUPS; i++)
408         _groups[i].suspend();
409 }
410
411 void
412 SGSubsystemMgr::resume ()
413 {
414     for (int i = 0; i < MAX_GROUPS; i++)
415         _groups[i].resume();
416 }
417
418 bool
419 SGSubsystemMgr::is_suspended () const
420 {
421     return false;
422 }
423
424 void
425 SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
426                      GroupType group, double min_time_sec)
427 {
428     SG_LOG(SG_GENERAL, SG_INFO, "Adding subsystem " << name);
429     get_group(group)->set_subsystem(name, subsystem, min_time_sec);
430
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");
434     }
435     _subsystem_map[name] = subsystem;
436 }
437
438 SGSubsystemGroup *
439 SGSubsystemMgr::get_group (GroupType group)
440 {
441     return &(_groups[group]);
442 }
443
444 SGSubsystem *
445 SGSubsystemMgr::get_subsystem (const string &name)
446 {
447     map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
448
449     if (s == _subsystem_map.end())
450         return 0;
451     else
452         return s->second;
453 }
454
455 // end of fgfs.cxx