[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