Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 5658


Ignore:
Timestamp:
Aug 18, 2009, 11:14:25 AM (15 years ago)
Author:
rgrieder
Message:

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.
Location:
code/branches/resource2/src/core
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • code/branches/resource2/src/core/Core.cc

    r5655 r5658  
    303303    void Core::loadGraphics()
    304304    {
    305         if (bGraphicsLoaded_)
    306             return;
     305        // Any exception should trigger this, even in upgradeToGraphics (see its remarks)
     306        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics);
    307307
    308308        // Upgrade OGRE to receive a render window
     
    314314
    315315        // Calls the InputManager which sets up the input devices.
    316         scoped_ptr<InputManager> inputManager(new InputManager(windowHnd));
     316        inputManager_.reset(new InputManager(windowHnd));
    317317
    318318        // load the CEGUI interface
    319319        guiManager_.reset(new GUIManager(graphicsManager_->getRenderWindow()));
    320320
    321         // Dismiss scoped pointer
    322         inputManager_.swap(inputManager);
     321        unloader.Dismiss();
    323322
    324323        bGraphicsLoaded_ = true;
     
    327326    void Core::unloadGraphics()
    328327    {
    329         if (!bGraphicsLoaded_)
    330             return;
    331 
    332328        this->guiManager_.reset();;
    333329        this->inputManager_.reset();;
     
    637633    }
    638634
    639     bool Core::preUpdate(const Clock& time) throw()
    640     {
    641         std::string exceptionMessage;
    642         try
    643         {
    644             if (this->bGraphicsLoaded_)
    645             {
    646                 // process input events
    647                 this->inputManager_->update(time);
    648                 // process gui events
    649                 this->guiManager_->update(time);
    650             }
    651             // process thread commands
    652             this->tclThreadManager_->update(time);
    653         }
    654         catch (const std::exception& ex)
    655         { exceptionMessage = ex.what(); }
    656         catch (...)
    657         { exceptionMessage = "Unknown exception"; }
    658         if (!exceptionMessage.empty())
    659         {
    660             COUT(0) << "An exception occurred in the Core preUpdate: " << exceptionMessage << std::endl;
    661             COUT(0) << "This should really never happen! Closing the program." << std::endl;
    662             return false;
    663         }
    664         return true;
    665     }
    666 
    667     bool Core::postUpdate(const Clock& time) throw()
    668     {
    669         std::string exceptionMessage;
    670         try
    671         {
    672             if (this->bGraphicsLoaded_)
    673             {
    674                 // Render (doesn't throw)
    675                 this->graphicsManager_->update(time);
    676             }
    677         }
    678         catch (const std::exception& ex)
    679         { exceptionMessage = ex.what(); }
    680         catch (...)
    681         { exceptionMessage = "Unknown exception"; }
    682         if (!exceptionMessage.empty())
    683         {
    684             COUT(0) << "An exception occurred in the Core postUpdate: " << exceptionMessage << std::endl;
    685             COUT(0) << "This should really never happen! Closing the program." << std::endl;
    686             return false;
    687         }
    688         return true;
     635    void Core::preUpdate(const Clock& time)
     636    {
     637        if (this->bGraphicsLoaded_)
     638        {
     639            // process input events
     640            this->inputManager_->update(time);
     641            // process gui events
     642            this->guiManager_->update(time);
     643        }
     644        // process thread commands
     645        this->tclThreadManager_->update(time);
     646    }
     647
     648    void Core::postUpdate(const Clock& time)
     649    {
     650        if (this->bGraphicsLoaded_)
     651        {
     652            // Render (doesn't throw)
     653            this->graphicsManager_->update(time);
     654        }
    689655    }
    690656}
  • code/branches/resource2/src/core/Core.h

    r5654 r5658  
    6565        typedef Loki::ScopeGuardImpl0<void (*)()> SimpleScopeGuard;
    6666        friend class Singleton<Core>;
     67        friend class Game;
    6768
    6869        public:
     
    7879
    7980            void setConfigValues();
    80 
    81             bool preUpdate(const Clock& time) throw();
    82             bool postUpdate(const Clock& time) throw();
    83 
    84             void loadGraphics();
    85             void unloadGraphics();
    8681
    8782            static int   getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
     
    117112            Core(const Core&); //!< Don't use (undefined symbol)
    118113
     114            void preUpdate(const Clock& time);
     115            void postUpdate(const Clock& time);
     116
     117            void loadGraphics();
     118            void unloadGraphics();
     119
    119120            void checkDevBuild();
    120121            void setExecutablePath();
  • code/branches/resource2/src/core/GUIManager.cc

    r5654 r5658  
    109109        COUT(3) << "Initialising CEGUI." << std::endl;
    110110
    111         try
    112         {
    113             // Note: No SceneManager specified yet
    114             guiRenderer_.reset(new OgreCEGUIRenderer(renderWindow_, Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
    115             resourceProvider_ = guiRenderer_->createResourceProvider();
    116             resourceProvider_->setDefaultResourceGroup("GUI");
    117 
    118             // setup scripting
    119             scriptModule_.reset(new LuaScriptModule());
    120             luaState_ = scriptModule_->getLuaState();
    121 
    122             // Create our own logger to specify the filepath
    123             std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
    124             ceguiLogger->setLogFilename(Core::getLogPathString() + "cegui.log");
    125             // set the log level according to ours (translate by subtracting 1)
    126             ceguiLogger->setLoggingLevel(
    127                 static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
    128             this->ceguiLogger_ = ceguiLogger.release();
    129 
    130             // create the CEGUI system singleton
    131             guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
    132 
    133             // do this after 'new CEGUI::Sytem' because that creates the lua state in the first place
    134             LuaState::openToluaInterfaces(this->luaState_);
    135 
    136             // initialise the basic lua code
    137             this->loadLuaCode();
    138         }
    139         catch (CEGUI::Exception& ex)
    140         {
    141 #if CEGUI_VERSION_MAJOR == 0 && CEGUI_VERSION_MINOR < 6
    142             throw GeneralException(ex.getMessage().c_str());
    143 #else
    144             throw GeneralException(ex.getMessage().c_str(), ex.getLine(),
    145                 ex.getFileName().c_str(), ex.getName().c_str());
    146 #endif
    147         }
     111        // Note: No SceneManager specified yet
     112        guiRenderer_.reset(new OgreCEGUIRenderer(renderWindow_, Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
     113        resourceProvider_ = guiRenderer_->createResourceProvider();
     114        resourceProvider_->setDefaultResourceGroup("GUI");
     115
     116        // setup scripting
     117        scriptModule_.reset(new LuaScriptModule());
     118        luaState_ = scriptModule_->getLuaState();
     119
     120        // Create our own logger to specify the filepath
     121        std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
     122        ceguiLogger->setLogFilename(Core::getLogPathString() + "cegui.log");
     123        // set the log level according to ours (translate by subtracting 1)
     124        ceguiLogger->setLoggingLevel(
     125            static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
     126        this->ceguiLogger_ = ceguiLogger.release();
     127
     128        // create the CEGUI system singleton
     129        guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
     130
     131        // do this after 'new CEGUI::Sytem' because that creates the lua state in the first place
     132        LuaState::openToluaInterfaces(this->luaState_);
     133
     134        // initialise the basic lua code
     135        this->loadLuaCode();
    148136    }
    149137
  • code/branches/resource2/src/core/Game.cc

    r5651 r5658  
    3737#include <exception>
    3838#include <boost/weak_ptr.hpp>
     39#include <CEGUIExceptions.h>
    3940
    4041#include "util/Debug.h"
     
    197198
    198199            // Core preUpdate (doesn't throw)
    199             if (!this->core_->preUpdate(*this->gameClock_))
    200             {
     200            try
     201                { this->core_->preUpdate(*this->gameClock_); }
     202            catch (...)
     203            {
     204                COUT(0) << "An exception occurred in the Core preUpdate: " << Game::getExceptionMessage() << std::endl;
     205                COUT(0) << "This should really never happen! Closing the program." << std::endl;
    201206                this->stop();
    202207                break;
     
    207212
    208213            // Core postUpdate (doesn't throw)
    209             if (!this->core_->postUpdate(*this->gameClock_))
    210             {
     214            try
     215                { this->core_->postUpdate(*this->gameClock_); }
     216            catch (...)
     217            {
     218            COUT(0) << "An exception occurred in the Core postUpdate: " << Game::getExceptionMessage() << std::endl;
     219            COUT(0) << "This should really never happen! Closing the program." << std::endl;
    211220                this->stop();
    212221                break;
     
    241250                    this->loadState(requestedStateNode->name_);
    242251                }
    243                 catch (const std::exception& ex)
     252                catch (...)
    244253                {
    245                     COUT(1) << "Error: Loading GameState '" << requestedStateNode->name_ << "' failed: " << ex.what() << std::endl;
     254                    COUT(1) << "Error: Loading GameState '" << requestedStateNode->name_ << "' failed: " << Game::getExceptionMessage() << std::endl;
    246255                    // All scheduled operations have now been rendered inert --> flush them and issue a warning
    247256                    if (this->requestedStateNodes_.size() > 1)
    248                         COUT(1) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << std::endl;
     257                        COUT(4) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << std::endl;
    249258                    this->requestedStateNodes_.clear();
    250259                    break;
     
    262271            it != this->loadedStates_.end(); ++it)
    263272        {
    264             std::string exceptionMessage;
    265273            try
    266274            {
     
    273281                    this->subtractTickTime(static_cast<int32_t>(this->gameClock_->getRealMicroseconds() - timeBeforeTick));
    274282            }
    275             catch (const std::exception& ex)
    276             { exceptionMessage = ex.what(); }
    277283            catch (...)
    278             { exceptionMessage = "Unknown exception"; }
    279             if (!exceptionMessage.empty())
    280             {
    281                 COUT(1) << "An exception occurred while updating '" << (*it)->getName() << "': " << exceptionMessage << std::endl;
     284            {
     285                COUT(1) << "An exception occurred while updating '" << (*it)->getName() << "': " << Game::getExceptionMessage() << std::endl;
    282286                COUT(1) << "This should really never happen!" << std::endl;
    283287                COUT(1) << "Unloading all GameStates depending on the one that crashed." << std::endl;
     
    585589            state->deactivate();
    586590        }
     591        catch (...)
     592        {
     593            COUT(2) << "Warning: Unloading GameState '" << name << "' threw an exception: " << Game::getExceptionMessage() << std::endl;
     594            COUT(2) << "         There might be potential resource leaks involved! To avoid this, improve exception-safety." << std::endl;
     595        }
     596        // Check if graphics is still required
     597        if (!bAbort_)
     598        {
     599            bool graphicsRequired = false;
     600            for (unsigned i = 0; i < loadedStates_.size(); ++i)
     601                graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
     602            if (!graphicsRequired)
     603                this->unloadGraphics();
     604        }
     605        this->bChangingState_ = false;
     606    }
     607
     608    /*static*/ std::string Game::getExceptionMessage()
     609    {
     610        std::string exceptionMessage;
     611        try
     612        {
     613            // rethrow
     614            throw;
     615        }
    587616        catch (const std::exception& ex)
    588617        {
    589             COUT(2) << "Warning: Unloading GameState '" << name << "' threw an exception: " << ex.what() << std::endl;
    590             COUT(2) << "         There might be potential resource leaks involved! To avoid this, improve exception-safety." << std::endl;
    591         }
    592         // Check if graphics is still required
    593         bool graphicsRequired = false;
    594         for (unsigned i = 0; i < loadedStates_.size(); ++i)
    595             graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
    596         if (!graphicsRequired)
    597             this->unloadGraphics();
    598         this->bChangingState_ = false;
     618            return ex.what();
     619        }
     620        catch (const CEGUI::Exception& ex)
     621        {
     622#if CEGUI_VERSION_MAJOR == 0 && CEGUI_VERSION_MINOR < 6
     623            return GeneralException(ex.getMessage().c_str()).getDescription();
     624#else
     625            return GeneralException(ex.getMessage().c_str(), ex.getLine(),
     626                ex.getFileName().c_str(), ex.getName().c_str()).getDescription();
     627#endif
     628        }
     629        catch (...)
     630        {
     631            return "Unknown exception";
     632        }
    599633    }
    600634
  • code/branches/resource2/src/core/Game.h

    r5651 r5658  
    151151        // ScopeGuard helper function
    152152        void resetChangingState() { this->bChangingState_ = false; }
     153        /**
     154        @brief
     155            Retrieves information from an exception caught with "..."
     156        @remarks
     157            Never ever call this function without an exception in the stack!
     158        */
     159        static std::string getExceptionMessage();
    153160
    154161        scoped_ptr<Clock>                  gameClock_;
  • code/branches/resource2/src/core/GraphicsManager.cc

    r5657 r5658  
    152152    @remarks
    153153        This operation is irreversible without recreating the GraphicsManager!
     154        So if it throws you HAVE to recreate the GraphicsManager!!!
     155        It therefore offers almost no exception safety.
    154156    */
    155157    void GraphicsManager::upgradeToGraphics()
Note: See TracChangeset for help on using the changeset viewer.