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