]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/subsystem_mgr.cxx
Formal shutdown interface on SGSubsystem.
[simgear.git] / simgear / structure / subsystem_mgr.cxx
index 26f026cd279976ecb49c876d70ced86ae0266610..387d097a091bd855ebfe189aeb38b092135ded59 100644 (file)
@@ -8,7 +8,7 @@
 #include <simgear/math/SGMath.hxx>
 
 
-\f
+const int SG_MAX_SUBSYSTEM_EXCEPTIONS = 4;\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGSubsystem
 ////////////////////////////////////////////////////////////////////////
@@ -38,6 +38,11 @@ SGSubsystem::reinit ()
 {
 }
 
+void
+SGSubsystem::shutdown ()
+{
+}
+
 void
 SGSubsystem::bind ()
 {
@@ -141,6 +146,14 @@ SGSubsystemGroup::reinit ()
         _members[i]->subsystem->reinit();
 }
 
+void
+SGSubsystemGroup::shutdown ()
+{
+    // reverse order to prevent order dependency problems
+    for (unsigned int i = _members.size(); i > 0; i--)
+        _members[i-1]->subsystem->shutdown();
+}
+
 void
 SGSubsystemGroup::bind ()
 {
@@ -308,7 +321,8 @@ SGSubsystemGroup::Member::Member ()
       subsystem(0),
       min_step_sec(0),
       elapsed_sec(0),
-      collectTimeStats(false)
+      collectTimeStats(false),
+      exceptionCount(0)
 {
 }
 
@@ -326,11 +340,26 @@ void
 SGSubsystemGroup::Member::update (double delta_time_sec)
 {
     elapsed_sec += delta_time_sec;
-    if (elapsed_sec >= min_step_sec) {
-        if (!subsystem->is_suspended()) {
-            subsystem->update(elapsed_sec);
-            elapsed_sec = 0;
-        }
+    if (elapsed_sec < min_step_sec) {
+        return;
+    }
+    
+    if (subsystem->is_suspended()) {
+        return;
+    }
+    
+    try {
+      subsystem->update(elapsed_sec);
+      elapsed_sec = 0;
+    } catch (sg_exception& e) {
+      SG_LOG(SG_GENERAL, SG_ALERT, "caught exception processing subsystem:" << name
+        << "\nmessage:" << e.getMessage());
+      
+      if (++exceptionCount > SG_MAX_SUBSYSTEM_EXCEPTIONS) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "(exceptionCount=" << exceptionCount <<
+          ", suspending)");
+        subsystem->suspend();
+      }
     }
 }
 
@@ -367,38 +396,57 @@ void SGSubsystemGroup::Member::updateExecutionTime(double time)
 
 SGSubsystemMgr::SGSubsystemMgr ()
 {
+  for (int i = 0; i < MAX_GROUPS; i++) {
+    _groups[i] = new SGSubsystemGroup;
+  }
 }
 
 SGSubsystemMgr::~SGSubsystemMgr ()
 {
+  // ensure get_subsystem returns NULL from now onwards,
+  // before the SGSubsystemGroup destructors are run
+  _subsystem_map.clear();
+  
+  for (int i = 0; i < MAX_GROUPS; i++) {
+    delete _groups[i];
+  }
 }
 
 void
 SGSubsystemMgr::init ()
 {
     for (int i = 0; i < MAX_GROUPS; i++)
-            _groups[i].init();
+            _groups[i]->init();
 }
 
 void
 SGSubsystemMgr::postinit ()
 {
     for (int i = 0; i < MAX_GROUPS; i++)
-            _groups[i].postinit();
+            _groups[i]->postinit();
 }
 
 void
 SGSubsystemMgr::reinit ()
 {
     for (int i = 0; i < MAX_GROUPS; i++)
-            _groups[i].reinit();
+            _groups[i]->reinit();
 }
 
+void
+SGSubsystemMgr::shutdown ()
+{
+    // reverse order to prevent order dependency problems
+    for (int i = MAX_GROUPS-1; i >= 0; i--)
+        _groups[i]->shutdown();
+}
+
+
 void
 SGSubsystemMgr::bind ()
 {
     for (int i = 0; i < MAX_GROUPS; i++)
-        _groups[i].bind();
+        _groups[i]->bind();
 }
 
 void
@@ -406,14 +454,14 @@ SGSubsystemMgr::unbind ()
 {
     // reverse order to prevent order dependency problems
     for (int i = MAX_GROUPS-1; i >= 0; i--)
-        _groups[i].unbind();
+        _groups[i]->unbind();
 }
 
 void
 SGSubsystemMgr::update (double delta_time_sec)
 {
     for (int i = 0; i < MAX_GROUPS; i++) {
-        _groups[i].update(delta_time_sec);
+        _groups[i]->update(delta_time_sec);
     }
 }
 
@@ -421,7 +469,7 @@ void
 SGSubsystemMgr::collectDebugTiming(bool collect)
 {
     for (int i = 0; i < MAX_GROUPS; i++) {
-        _groups[i].collectDebugTiming(collect);
+        _groups[i]->collectDebugTiming(collect);
     }
 }
 
@@ -429,14 +477,14 @@ void
 SGSubsystemMgr::suspend ()
 {
     for (int i = 0; i < MAX_GROUPS; i++)
-        _groups[i].suspend();
+        _groups[i]->suspend();
 }
 
 void
 SGSubsystemMgr::resume ()
 {
     for (int i = 0; i < MAX_GROUPS; i++)
-        _groups[i].resume();
+        _groups[i]->resume();
 }
 
 bool
@@ -459,16 +507,39 @@ SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
     _subsystem_map[name] = subsystem;
 }
 
+SGSubsystem* 
+SGSubsystemMgr::remove(const char* name)
+{
+  SubsystemDict::iterator s =_subsystem_map.find(name);
+  if (s == _subsystem_map.end()) {
+    return NULL;
+  }
+  
+  SGSubsystem* sub = s->second;
+  _subsystem_map.erase(s);
+  
+// tedious part - we don't know which group the subsystem belongs too
+  for (int i = 0; i < MAX_GROUPS; i++) {
+    if (_groups[i]->get_subsystem(name) == sub) {
+      _groups[i]->remove_subsystem(name);
+      break;
+    }
+  } // of groups iteration
+  
+  return sub;
+}
+
+
 SGSubsystemGroup *
 SGSubsystemMgr::get_group (GroupType group)
 {
-    return &(_groups[group]);
+    return _groups[group];
 }
 
 SGSubsystem *
-SGSubsystemMgr::get_subsystem (const string &name)
+SGSubsystemMgr::get_subsystem (const string &name) const
 {
-    map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
+    SubsystemDict::const_iterator s =_subsystem_map.find(name);
 
     if (s == _subsystem_map.end())
         return 0;