[Orxonox-commit 935] r5658 - code/branches/resource2/src/core

rgrieder at orxonox.net rgrieder at orxonox.net
Tue Aug 18 11:14:26 CEST 2009


Author: rgrieder
Date: 2009-08-18 11:14:25 +0200 (Tue, 18 Aug 2009)
New Revision: 5658

Modified:
   code/branches/resource2/src/core/Core.cc
   code/branches/resource2/src/core/Core.h
   code/branches/resource2/src/core/GUIManager.cc
   code/branches/resource2/src/core/Game.cc
   code/branches/resource2/src/core/Game.h
   code/branches/resource2/src/core/GraphicsManager.cc
Log:
Fixed two bugs:
- Incomplete exception safety in Core::loadGraphics
- When shutting down, Game would load the GraphicsManager again (due to the unloadGraphics call). Suppressed this for faster shutdown.
Resolved a little issue:
- Finally figured out a way to handle exceptions caught with catch (...) generically and implemented this function in Game::getExceptionMessage()
- Also removes the exception translation in the GUIManager and made Game catch CEGUI::Exception as well.

Modified: code/branches/resource2/src/core/Core.cc
===================================================================
--- code/branches/resource2/src/core/Core.cc	2009-08-17 19:12:54 UTC (rev 5657)
+++ code/branches/resource2/src/core/Core.cc	2009-08-18 09:14:25 UTC (rev 5658)
@@ -302,8 +302,8 @@
 
     void Core::loadGraphics()
     {
-        if (bGraphicsLoaded_)
-            return;
+        // Any exception should trigger this, even in upgradeToGraphics (see its remarks)
+        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics);
 
         // Upgrade OGRE to receive a render window
         graphicsManager_->upgradeToGraphics();
@@ -313,22 +313,18 @@
         graphicsManager_->getRenderWindow()->getCustomAttribute("WINDOW", &windowHnd);
 
         // Calls the InputManager which sets up the input devices.
-        scoped_ptr<InputManager> inputManager(new InputManager(windowHnd));
+        inputManager_.reset(new InputManager(windowHnd));
 
         // load the CEGUI interface
         guiManager_.reset(new GUIManager(graphicsManager_->getRenderWindow()));
 
-        // Dismiss scoped pointer
-        inputManager_.swap(inputManager);
+        unloader.Dismiss();
 
         bGraphicsLoaded_ = true;
     }
 
     void Core::unloadGraphics()
     {
-        if (!bGraphicsLoaded_)
-            return;
-
         this->guiManager_.reset();;
         this->inputManager_.reset();;
         this->graphicsManager_.reset();
@@ -636,55 +632,25 @@
         }
     }
 
-    bool Core::preUpdate(const Clock& time) throw()
+    void Core::preUpdate(const Clock& time)
     {
-        std::string exceptionMessage;
-        try
+        if (this->bGraphicsLoaded_)
         {
-            if (this->bGraphicsLoaded_)
-            {
-                // process input events
-                this->inputManager_->update(time);
-                // process gui events
-                this->guiManager_->update(time);
-            }
-            // process thread commands
-            this->tclThreadManager_->update(time);
+            // process input events
+            this->inputManager_->update(time);
+            // process gui events
+            this->guiManager_->update(time);
         }
-        catch (const std::exception& ex)
-        { exceptionMessage = ex.what(); }
-        catch (...)
-        { exceptionMessage = "Unknown exception"; }
-        if (!exceptionMessage.empty())
-        {
-            COUT(0) << "An exception occurred in the Core preUpdate: " << exceptionMessage << std::endl;
-            COUT(0) << "This should really never happen! Closing the program." << std::endl;
-            return false;
-        }
-        return true;
+        // process thread commands
+        this->tclThreadManager_->update(time);
     }
 
-    bool Core::postUpdate(const Clock& time) throw()
+    void Core::postUpdate(const Clock& time)
     {
-        std::string exceptionMessage;
-        try
+        if (this->bGraphicsLoaded_)
         {
-            if (this->bGraphicsLoaded_)
-            {
-                // Render (doesn't throw)
-                this->graphicsManager_->update(time);
-            }
+            // Render (doesn't throw)
+            this->graphicsManager_->update(time);
         }
-        catch (const std::exception& ex)
-        { exceptionMessage = ex.what(); }
-        catch (...)
-        { exceptionMessage = "Unknown exception"; }
-        if (!exceptionMessage.empty())
-        {
-            COUT(0) << "An exception occurred in the Core postUpdate: " << exceptionMessage << std::endl;
-            COUT(0) << "This should really never happen! Closing the program." << std::endl;
-            return false;
-        }
-        return true;
     }
 }

Modified: code/branches/resource2/src/core/Core.h
===================================================================
--- code/branches/resource2/src/core/Core.h	2009-08-17 19:12:54 UTC (rev 5657)
+++ code/branches/resource2/src/core/Core.h	2009-08-18 09:14:25 UTC (rev 5658)
@@ -64,6 +64,7 @@
     {
         typedef Loki::ScopeGuardImpl0<void (*)()> SimpleScopeGuard;
         friend class Singleton<Core>;
+        friend class Game;
 
         public:
             /**
@@ -78,12 +79,6 @@
 
             void setConfigValues();
 
-            bool preUpdate(const Clock& time) throw();
-            bool postUpdate(const Clock& time) throw();
-
-            void loadGraphics();
-            void unloadGraphics();
-
             static int   getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
             static void  setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
             static const std::string& getLanguage();
@@ -116,6 +111,12 @@
         private:
             Core(const Core&); //!< Don't use (undefined symbol)
 
+            void preUpdate(const Clock& time);
+            void postUpdate(const Clock& time);
+
+            void loadGraphics();
+            void unloadGraphics();
+
             void checkDevBuild();
             void setExecutablePath();
             void createDirectories();

Modified: code/branches/resource2/src/core/GUIManager.cc
===================================================================
--- code/branches/resource2/src/core/GUIManager.cc	2009-08-17 19:12:54 UTC (rev 5657)
+++ code/branches/resource2/src/core/GUIManager.cc	2009-08-18 09:14:25 UTC (rev 5658)
@@ -108,43 +108,31 @@
 
         COUT(3) << "Initialising CEGUI." << std::endl;
 
-        try
-        {
-            // Note: No SceneManager specified yet
-            guiRenderer_.reset(new OgreCEGUIRenderer(renderWindow_, Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
-            resourceProvider_ = guiRenderer_->createResourceProvider();
-            resourceProvider_->setDefaultResourceGroup("GUI");
+        // Note: No SceneManager specified yet
+        guiRenderer_.reset(new OgreCEGUIRenderer(renderWindow_, Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
+        resourceProvider_ = guiRenderer_->createResourceProvider();
+        resourceProvider_->setDefaultResourceGroup("GUI");
 
-            // setup scripting
-            scriptModule_.reset(new LuaScriptModule());
-            luaState_ = scriptModule_->getLuaState();
+        // setup scripting
+        scriptModule_.reset(new LuaScriptModule());
+        luaState_ = scriptModule_->getLuaState();
 
-            // Create our own logger to specify the filepath
-            std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
-            ceguiLogger->setLogFilename(Core::getLogPathString() + "cegui.log");
-            // set the log level according to ours (translate by subtracting 1)
-            ceguiLogger->setLoggingLevel(
-                static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
-            this->ceguiLogger_ = ceguiLogger.release();
+        // Create our own logger to specify the filepath
+        std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
+        ceguiLogger->setLogFilename(Core::getLogPathString() + "cegui.log");
+        // set the log level according to ours (translate by subtracting 1)
+        ceguiLogger->setLoggingLevel(
+            static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
+        this->ceguiLogger_ = ceguiLogger.release();
 
-            // create the CEGUI system singleton
-            guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
+        // create the CEGUI system singleton
+        guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
 
-            // do this after 'new CEGUI::Sytem' because that creates the lua state in the first place
-            LuaState::openToluaInterfaces(this->luaState_);
+        // do this after 'new CEGUI::Sytem' because that creates the lua state in the first place
+        LuaState::openToluaInterfaces(this->luaState_);
 
-            // initialise the basic lua code
-            this->loadLuaCode();
-        }
-        catch (CEGUI::Exception& ex)
-        {
-#if CEGUI_VERSION_MAJOR == 0 && CEGUI_VERSION_MINOR < 6
-            throw GeneralException(ex.getMessage().c_str());
-#else
-            throw GeneralException(ex.getMessage().c_str(), ex.getLine(),
-                ex.getFileName().c_str(), ex.getName().c_str());
-#endif
-        }
+        // initialise the basic lua code
+        this->loadLuaCode();
     }
 
     /**

Modified: code/branches/resource2/src/core/Game.cc
===================================================================
--- code/branches/resource2/src/core/Game.cc	2009-08-17 19:12:54 UTC (rev 5657)
+++ code/branches/resource2/src/core/Game.cc	2009-08-18 09:14:25 UTC (rev 5658)
@@ -36,6 +36,7 @@
 
 #include <exception>
 #include <boost/weak_ptr.hpp>
+#include <CEGUIExceptions.h>
 
 #include "util/Debug.h"
 #include "util/Exception.h"
@@ -196,8 +197,12 @@
             this->updateGameStateStack();
 
             // Core preUpdate (doesn't throw)
-            if (!this->core_->preUpdate(*this->gameClock_))
+            try
+                { this->core_->preUpdate(*this->gameClock_); }
+            catch (...)
             {
+                COUT(0) << "An exception occurred in the Core preUpdate: " << Game::getExceptionMessage() << std::endl;
+                COUT(0) << "This should really never happen! Closing the program." << std::endl;
                 this->stop();
                 break;
             }
@@ -206,8 +211,12 @@
             this->updateGameStates();
 
             // Core postUpdate (doesn't throw)
-            if (!this->core_->postUpdate(*this->gameClock_))
+            try
+                { this->core_->postUpdate(*this->gameClock_); }
+            catch (...)
             {
+            COUT(0) << "An exception occurred in the Core postUpdate: " << Game::getExceptionMessage() << std::endl;
+            COUT(0) << "This should really never happen! Closing the program." << std::endl;
                 this->stop();
                 break;
             }
@@ -240,12 +249,12 @@
                 {
                     this->loadState(requestedStateNode->name_);
                 }
-                catch (const std::exception& ex)
+                catch (...)
                 {
-                    COUT(1) << "Error: Loading GameState '" << requestedStateNode->name_ << "' failed: " << ex.what() << std::endl;
+                    COUT(1) << "Error: Loading GameState '" << requestedStateNode->name_ << "' failed: " << Game::getExceptionMessage() << std::endl;
                     // All scheduled operations have now been rendered inert --> flush them and issue a warning
                     if (this->requestedStateNodes_.size() > 1)
-                        COUT(1) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << std::endl;
+                        COUT(4) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << std::endl;
                     this->requestedStateNodes_.clear();
                     break;
                 }
@@ -261,7 +270,6 @@
         for (GameStateVector::const_iterator it = this->loadedStates_.begin() + 1;
             it != this->loadedStates_.end(); ++it)
         {
-            std::string exceptionMessage;
             try
             {
                 // Add tick time for most of the states
@@ -272,13 +280,9 @@
                 if ((*it)->getInfo().bIgnoreTickTime)
                     this->subtractTickTime(static_cast<int32_t>(this->gameClock_->getRealMicroseconds() - timeBeforeTick));
             }
-            catch (const std::exception& ex)
-            { exceptionMessage = ex.what(); }
             catch (...)
-            { exceptionMessage = "Unknown exception"; }
-            if (!exceptionMessage.empty())
             {
-                COUT(1) << "An exception occurred while updating '" << (*it)->getName() << "': " << exceptionMessage << std::endl;
+                COUT(1) << "An exception occurred while updating '" << (*it)->getName() << "': " << Game::getExceptionMessage() << std::endl;
                 COUT(1) << "This should really never happen!" << std::endl;
                 COUT(1) << "Unloading all GameStates depending on the one that crashed." << std::endl;
                 shared_ptr<GameStateTreeNode> current = this->loadedTopStateNode_;
@@ -584,20 +588,50 @@
                 this->loadedStates_.back()->activity_.topState = true;
             state->deactivate();
         }
-        catch (const std::exception& ex)
+        catch (...)
         {
-            COUT(2) << "Warning: Unloading GameState '" << name << "' threw an exception: " << ex.what() << std::endl;
+            COUT(2) << "Warning: Unloading GameState '" << name << "' threw an exception: " << Game::getExceptionMessage() << std::endl;
             COUT(2) << "         There might be potential resource leaks involved! To avoid this, improve exception-safety." << std::endl;
         }
         // Check if graphics is still required
-        bool graphicsRequired = false;
-        for (unsigned i = 0; i < loadedStates_.size(); ++i)
-            graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
-        if (!graphicsRequired)
-            this->unloadGraphics();
+        if (!bAbort_)
+        {
+            bool graphicsRequired = false;
+            for (unsigned i = 0; i < loadedStates_.size(); ++i)
+                graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
+            if (!graphicsRequired)
+                this->unloadGraphics();
+        }
         this->bChangingState_ = false;
     }
 
+    /*static*/ std::string Game::getExceptionMessage()
+    {
+        std::string exceptionMessage;
+        try
+        {
+            // rethrow
+            throw;
+        }
+        catch (const std::exception& ex)
+        {
+            return ex.what();
+        }
+        catch (const CEGUI::Exception& ex)
+        {
+#if CEGUI_VERSION_MAJOR == 0 && CEGUI_VERSION_MINOR < 6
+            return GeneralException(ex.getMessage().c_str()).getDescription();
+#else
+            return GeneralException(ex.getMessage().c_str(), ex.getLine(),
+                ex.getFileName().c_str(), ex.getName().c_str()).getDescription();
+#endif
+        }
+        catch (...)
+        {
+            return "Unknown exception";
+        }
+    }
+
     std::map<std::string, shared_ptr<Game::GameStateFactory> > Game::GameStateFactory::factories_s;
 
     /*static*/ shared_ptr<GameState> Game::GameStateFactory::fabricate(const GameStateInfo& info)

Modified: code/branches/resource2/src/core/Game.h
===================================================================
--- code/branches/resource2/src/core/Game.h	2009-08-17 19:12:54 UTC (rev 5657)
+++ code/branches/resource2/src/core/Game.h	2009-08-18 09:14:25 UTC (rev 5658)
@@ -150,6 +150,13 @@
 
         // ScopeGuard helper function
         void resetChangingState() { this->bChangingState_ = false; }
+        /**
+        @brief
+            Retrieves information from an exception caught with "..."
+        @remarks
+            Never ever call this function without an exception in the stack!
+        */
+        static std::string getExceptionMessage();
 
         scoped_ptr<Clock>                  gameClock_;
         scoped_ptr<Core>                   core_;

Modified: code/branches/resource2/src/core/GraphicsManager.cc
===================================================================
--- code/branches/resource2/src/core/GraphicsManager.cc	2009-08-17 19:12:54 UTC (rev 5657)
+++ code/branches/resource2/src/core/GraphicsManager.cc	2009-08-18 09:14:25 UTC (rev 5658)
@@ -151,6 +151,8 @@
         Loads the renderer and creates the render window if not yet done so.
     @remarks
         This operation is irreversible without recreating the GraphicsManager!
+        So if it throws you HAVE to recreate the GraphicsManager!!!
+        It therefore offers almost no exception safety.
     */
     void GraphicsManager::upgradeToGraphics()
     {




More information about the Orxonox-commit mailing list