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