]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/subsystem_mgr.cxx
Tweak APi for GCC happiness.
[simgear.git] / simgear / structure / subsystem_mgr.cxx
index 6b50645e7508420383d0a3615ab4f641f3036e39..1e1425528e1a94f595e7b4de4e088c188b15d9a3 100644 (file)
@@ -1,3 +1,26 @@
+// Written by David Megginson, started 2000-12
+//
+// Copyright (C) 2000  David Megginson, david@megginson.com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+// $Id$
+
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/timing/timestamp.hxx>
 #include "subsystem_mgr.hxx"
 
 #include <simgear/math/SGMath.hxx>
+#include "SGSmplstat.hxx"
 
+const int SG_MAX_SUBSYSTEM_EXCEPTIONS = 4;
+
+using std::string;
 
-const int SG_MAX_SUBSYSTEM_EXCEPTIONS = 4;\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGSubsystem
 ////////////////////////////////////////////////////////////////////////
 
+SGSubsystemTimingCb SGSubsystem::reportTimingCb = NULL;
+void* SGSubsystem::reportTimingUserData = NULL;
 
 SGSubsystem::SGSubsystem ()
   : _suspended(false)
@@ -28,6 +56,13 @@ SGSubsystem::init ()
 {
 }
 
+SGSubsystem::InitStatus
+SGSubsystem::incrementalInit ()
+{
+  init();
+  return INIT_DONE;
+}
+
 void
 SGSubsystem::postinit ()
 {
@@ -38,6 +73,11 @@ SGSubsystem::reinit ()
 {
 }
 
+void
+SGSubsystem::shutdown ()
+{
+}
+
 void
 SGSubsystem::bind ()
 {
@@ -72,28 +112,6 @@ SGSubsystem::is_suspended () const
   return _suspended;
 }
 
-
-void
-SGSubsystem::printTimingInformation ()
-{
-   SGTimeStamp startTime;
-   for ( eventTimeVecIterator i = timingInfo.begin();
-          i != timingInfo.end();
-          i++) {
-       if (i == timingInfo.begin()) {
-           startTime = i->getTime();
-       } else {
-           SGTimeStamp endTime = i->getTime();
-           SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp :   "
-                  << i->getName() << " takes " << endTime - startTime
-                  << " sec.");
-          startTime = endTime;
-       }
-   }
-}
-
-
-
 void SGSubsystem::stamp(const string& name)
 {
     timingInfo.push_back(TimingInfo(name, SGTimeStamp::now()));
@@ -104,9 +122,35 @@ void SGSubsystem::stamp(const string& name)
 // Implementation of SGSubsystemGroup.
 ////////////////////////////////////////////////////////////////////////
 
+class SGSubsystemGroup::Member
+{    
+private:
+    Member (const Member &member);
+public:
+    Member ();
+    virtual ~Member ();
+    
+    virtual void update (double delta_time_sec);
+
+    void reportTiming(void) { if (reportTimingCb) reportTimingCb(reportTimingUserData, name, &timeStat); }
+    void updateExecutionTime(double time) { timeStat += time;}
+
+    SampleStatistic timeStat;
+    std::string name;
+    SGSubsystem * subsystem;
+    double min_step_sec;
+    double elapsed_sec;
+    bool collectTimeStats;
+    int exceptionCount;
+    int initTime;
+};
+
+
+
 SGSubsystemGroup::SGSubsystemGroup () :
   _fixedUpdateTime(-1.0),
-  _updateTimeRemainder(0.0)
+  _updateTimeRemainder(0.0),
+  _initPosition(0)
 {
 }
 
@@ -115,7 +159,6 @@ SGSubsystemGroup::~SGSubsystemGroup ()
     // reverse order to prevent order dependency problems
     for (unsigned int i = _members.size(); i > 0; i--)
     {
-        _members[i-1]->printTimingStatistics();
         delete _members[i-1];
     }
 }
@@ -127,6 +170,23 @@ SGSubsystemGroup::init ()
         _members[i]->subsystem->init();
 }
 
+SGSubsystem::InitStatus
+SGSubsystemGroup::incrementalInit()
+{
+  if (_initPosition >= _members.size())
+    return INIT_DONE;
+  
+  SGTimeStamp st;
+  st.stamp();
+  InitStatus memberStatus = _members[_initPosition]->subsystem->incrementalInit();
+  _members[_initPosition]->initTime += st.elapsedMSec();
+  
+  if (memberStatus == INIT_DONE)
+    ++_initPosition;
+  
+  return INIT_CONTINUE;
+}
+
 void
 SGSubsystemGroup::postinit ()
 {
@@ -141,6 +201,15 @@ 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();
+  _initPosition = 0;
+}
+
 void
 SGSubsystemGroup::bind ()
 {
@@ -170,28 +239,31 @@ SGSubsystemGroup::update (double delta_time_sec)
       delta_time_sec = _fixedUpdateTime;
     }
 
+    bool recordTime = (reportTimingCb != NULL);
+    SGTimeStamp timeStamp;
     while (loopCount-- > 0) {
       for (unsigned int i = 0; i < _members.size(); i++)
       {
-           SGTimeStamp timeStamp = SGTimeStamp::now();
-           _members[i]->update(delta_time_sec); // indirect call
-           timeStamp = timeStamp - SGTimeStamp::now();
-           double b = timeStamp.toUSecs();
-           _members[i]->updateExecutionTime(b);
-           double threshold = _members[i]->getTimeWarningThreshold();
-           if (( b > threshold ) && (b > 10000)) {
-               _members[i]->printTimingInformation(b);
-           }
+          if (recordTime)
+              timeStamp = SGTimeStamp::now();
+
+          _members[i]->update(delta_time_sec); // indirect call
+
+          if ((recordTime)&&(reportTimingCb))
+          {
+              timeStamp = SGTimeStamp::now() - timeStamp;
+              _members[i]->updateExecutionTime(timeStamp.toUSecs());
+          }
       }
     } // of multiple update loop
 }
 
-void 
-SGSubsystemGroup::collectDebugTiming(bool collect)
+void
+SGSubsystemGroup::reportTiming(void)
 {
-    for (unsigned int i = 0; i < _members.size(); i++)
+    for (unsigned int i = _members.size(); i > 0; i--)
     {
-        _members[i]->collectDebugTiming(collect);
+        _members[i-1]->reportTiming();
     }
 }
 
@@ -209,6 +281,16 @@ SGSubsystemGroup::resume ()
         _members[i]->subsystem->resume();
 }
 
+string_list
+SGSubsystemGroup::member_names() const
+{
+       string_list result;
+       for (unsigned int i = 0; i < _members.size(); i++)
+               result.push_back( _members[i]->name );
+       
+       return result;
+}
+
 bool
 SGSubsystemGroup::is_suspended () const
 {
@@ -254,26 +336,6 @@ SGSubsystemGroup::set_fixed_update_time(double dt)
   _fixedUpdateTime = dt;
 }
 
-void
-SGSubsystemGroup::Member::printTimingStatistics ()
-{
-    if (collectTimeStats) {
-        double minTime = timeStat.min()   / 1000;
-        double maxTime = timeStat.max()   / 1000;
-        double meanTime = timeStat.mean() / 1000;
-        double stddev   = timeStat.stdDev()   / 1000;
-
-        char buffer[256];
-        snprintf(buffer, 256, "Timing summary for %20s.\n"
-                              "-  mean time: %04.2f ms.\n"
-                              "-  min time : %04.2f ms.\n"
-                              "-  max time : %04.2f ms.\n"
-                              "- stddev    : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev);
-        SG_LOG(SG_GENERAL, SG_ALERT, buffer);
-    }
-}
-
-
 bool
 SGSubsystemGroup::has_subsystem (const string &name) const
 {
@@ -308,8 +370,8 @@ SGSubsystemGroup::Member::Member ()
       subsystem(0),
       min_step_sec(0),
       elapsed_sec(0),
-      collectTimeStats(false),
-      exceptionCount(0)
+      exceptionCount(0),
+      initTime(0)
 {
 }
 
@@ -351,38 +413,17 @@ SGSubsystemGroup::Member::update (double delta_time_sec)
 }
 
 
-void 
-SGSubsystemGroup::Member::printTimingInformation(double time)
-{
-     if (collectTimeStats) {
-         SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert : " << time << " " << name);
-         subsystem->printTimingInformation();
-     }
-}
-
-double SGSubsystemGroup::Member::getTimeWarningThreshold()
-{
-    return (timeStat.mean() + 3 * timeStat.stdDev());
-}
-
-void SGSubsystemGroup::Member::updateExecutionTime(double time)
-{
-    if (collectTimeStats) {
-        timeStat += time;
-    }
-}
-
-
-
-
-\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGSubsystemMgr.
 ////////////////////////////////////////////////////////////////////////
 
 
-SGSubsystemMgr::SGSubsystemMgr ()
+SGSubsystemMgr::SGSubsystemMgr () :
+  _initPosition(0)
 {
+  for (int i = 0; i < MAX_GROUPS; i++) {
+    _groups[i] = new SGSubsystemGroup;
+  }
 }
 
 SGSubsystemMgr::~SGSubsystemMgr ()
@@ -390,34 +431,62 @@ 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();
+}
+
+SGSubsystem::InitStatus
+SGSubsystemMgr::incrementalInit()
+{
+  if (_initPosition >= MAX_GROUPS)
+    return INIT_DONE;
+  
+  InitStatus memberStatus = _groups[_initPosition]->incrementalInit();  
+  if (memberStatus == INIT_DONE)
+    ++_initPosition;
+  
+  return INIT_CONTINUE;
 }
 
 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();
+  
+    _initPosition = 0;
 }
 
+
 void
 SGSubsystemMgr::bind ()
 {
     for (int i = 0; i < MAX_GROUPS; i++)
-        _groups[i].bind();
+        _groups[i]->bind();
 }
 
 void
@@ -425,22 +494,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);
-    }
-}
-
-void 
-SGSubsystemMgr::collectDebugTiming(bool collect)
-{
-    for (int i = 0; i < MAX_GROUPS; i++) {
-        _groups[i].collectDebugTiming(collect);
+        _groups[i]->update(delta_time_sec);
     }
 }
 
@@ -448,14 +509,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
@@ -491,8 +552,8 @@ SGSubsystemMgr::remove(const char* name)
   
 // 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);
+    if (_groups[i]->get_subsystem(name) == sub) {
+      _groups[i]->remove_subsystem(name);
       break;
     }
   } // of groups iteration
@@ -504,7 +565,7 @@ SGSubsystemMgr::remove(const char* name)
 SGSubsystemGroup *
 SGSubsystemMgr::get_group (GroupType group)
 {
-    return &(_groups[group]);
+    return _groups[group];
 }
 
 SGSubsystem *
@@ -518,4 +579,13 @@ SGSubsystemMgr::get_subsystem (const string &name) const
         return s->second;
 }
 
-// end of fgfs.cxx
+/** Trigger the timing callback to report data for all subsystems. */
+void
+SGSubsystemMgr::reportTiming()
+{
+    for (int i = 0; i < MAX_GROUPS; i++) {
+        _groups[i]->reportTiming();
+    } // of groups iteration
+}
+
+// end of subsystem_mgr.cxx