[Orxonox-commit 1156] r5877 - in code/branches/core5/src: libraries/core libraries/core/input libraries/util modules/questsystem modules/questsystem/notifications orxonox orxonox/overlays orxonox/sound
rgrieder at orxonox.net
rgrieder at orxonox.net
Mon Oct 5 01:34:10 CEST 2009
Author: rgrieder
Date: 2009-10-05 01:34:10 +0200 (Mon, 05 Oct 2009)
New Revision: 5877
Modified:
code/branches/core5/src/libraries/core/Core.cc
code/branches/core5/src/libraries/core/ScopedSingletonManager.h
code/branches/core5/src/libraries/core/input/KeyBinderManager.cc
code/branches/core5/src/libraries/core/input/KeyDetector.cc
code/branches/core5/src/libraries/util/Scope.h
code/branches/core5/src/modules/questsystem/QuestManager.cc
code/branches/core5/src/modules/questsystem/notifications/NotificationManager.cc
code/branches/core5/src/orxonox/CameraManager.cc
code/branches/core5/src/orxonox/LevelManager.cc
code/branches/core5/src/orxonox/PlayerManager.cc
code/branches/core5/src/orxonox/overlays/InGameConsole.cc
code/branches/core5/src/orxonox/sound/SoundManager.cc
Log:
Added new an option for the ScopedSingletonManager that can allow the Singleton to fail (throw an exception).
Also improved exception-safety in Scope so that when for a Singleton fails, the Scope will deactivate all activated listeners and properly destroy itself.
Modified: code/branches/core5/src/libraries/core/Core.cc
===================================================================
--- code/branches/core5/src/libraries/core/Core.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/libraries/core/Core.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -433,7 +433,7 @@
void Core::preUpdate(const Clock& time)
{
// singletons from other libraries
- ScopedSingletonManager::update(time, ScopeID::Root);
+ ScopedSingletonManager::update<ScopeID::Root>(time);
if (this->bGraphicsLoaded_)
{
// process input events
@@ -441,7 +441,7 @@
// process gui events
this->guiManager_->update(time);
// graphics singletons from other libraries
- ScopedSingletonManager::update(time, ScopeID::Graphics);
+ ScopedSingletonManager::update<ScopeID::Graphics>(time);
}
// process thread commands
this->tclThreadManager_->update(time);
Modified: code/branches/core5/src/libraries/core/ScopedSingletonManager.h
===================================================================
--- code/branches/core5/src/libraries/core/ScopedSingletonManager.h 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/libraries/core/ScopedSingletonManager.h 2009-10-04 23:34:10 UTC (rev 5877)
@@ -33,11 +33,12 @@
#include <cassert>
#include <map>
+#include "util/Exception.h"
#include "util/Scope.h"
#include "util/Singleton.h"
-#define ManageScopedSingleton(className, scope) \
- static ClassScopedSingletonManager<className, scope> className##ScopedSingletonManager(#className)
+#define ManageScopedSingleton(className, scope, allowedToFail) \
+ static ClassScopedSingletonManager<className, scope, allowedToFail> className##ScopedSingletonManager(#className)
namespace orxonox
{
@@ -52,8 +53,10 @@
static void addManager(ScopedSingletonManager* manager);
static void removeManager(ScopedSingletonManager* manager);
- static void update(const Clock& time, ScopeID::Value scope)
+ template<ScopeID::Value scope>
+ static void update(const Clock& time)
{
+ assert(Scope<scope>::isActive());
for (ManagerMultiMap::iterator it = getManagersByScope().lower_bound(scope); it != getManagersByScope().upper_bound(scope); ++it)
it->second->update(time);
}
@@ -68,7 +71,7 @@
const ScopeID::Value scope_;
};
- template <class T, ScopeID::Value scope>
+ template <class T, ScopeID::Value scope, bool allowedToFail>
class ClassScopedSingletonManager : public ScopedSingletonManager, public ScopeListener
{
public:
@@ -82,6 +85,7 @@
~ClassScopedSingletonManager()
{
+ assert(singletonPtr_ == NULL);
ScopedSingletonManager::removeManager(this);
}
@@ -100,6 +104,65 @@
singletonPtr_ = NULL;
}
+ void destroy(OrxonoxClass*)
+ {
+ singletonPtr_->destroy();
+ }
+ void destroy(void*)
+ {
+ delete singletonPtr_;
+ }
+
+ //! Called every frame by the ScopedSingletonManager
+ void update(const Clock& time)
+ {
+ assert(Scope<scope>::isActive());
+ // assuming T inherits Singleton<T>
+ singletonPtr_->updateSingleton(time);
+ }
+
+ private:
+ T* singletonPtr_;
+ };
+
+ template <class T, ScopeID::Value scope>
+ class ClassScopedSingletonManager<T, scope, true> : public ScopedSingletonManager, public ScopeListener
+ {
+ public:
+ ClassScopedSingletonManager(const std::string& className)
+ : ScopedSingletonManager(className, scope)
+ , ScopeListener(scope)
+ , singletonPtr_(NULL)
+ {
+ ScopedSingletonManager::addManager(this);
+ }
+
+ ~ClassScopedSingletonManager()
+ {
+ assert(singletonPtr_ == NULL);
+ ScopedSingletonManager::removeManager(this);
+ }
+
+ //! Called if the Scope of the Singleton gets active (creates the instance)
+ void activated()
+ {
+ assert(singletonPtr_ == NULL);
+ try
+ { singletonPtr_ = new T(); }
+ catch (...)
+ { COUT(1) << "Singleton creation failed: " << Exception::handleMessage() << std::endl; }
+ }
+
+ //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
+ void deactivated()
+ {
+ if (singletonPtr_ != NULL)
+ {
+ this->destroy(singletonPtr_);
+ singletonPtr_ = NULL;
+ }
+ }
+
void destroy(OrxonoxClass* ptr)
{
singletonPtr_->destroy();
@@ -112,8 +175,10 @@
//! Called every frame by the ScopedSingletonManager
void update(const Clock& time)
{
+ assert(Scope<scope>::isActive());
// assuming T inherits Singleton<T>
- singletonPtr_->updateSingleton(time);
+ if (singletonPtr_ != NULL)
+ singletonPtr_->updateSingleton(time);
}
private:
Modified: code/branches/core5/src/libraries/core/input/KeyBinderManager.cc
===================================================================
--- code/branches/core5/src/libraries/core/input/KeyBinderManager.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/libraries/core/input/KeyBinderManager.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -40,7 +40,7 @@
namespace orxonox
{
KeyBinderManager* KeyBinderManager::singletonPtr_s = 0;
- ManageScopedSingleton(KeyBinderManager, ScopeID::Graphics);
+ ManageScopedSingleton(KeyBinderManager, ScopeID::Graphics, false);
KeyBinderManager::KeyBinderManager()
: currentBinder_(NULL)
Modified: code/branches/core5/src/libraries/core/input/KeyDetector.cc
===================================================================
--- code/branches/core5/src/libraries/core/input/KeyDetector.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/libraries/core/input/KeyDetector.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -39,7 +39,7 @@
{
std::string KeyDetector::callbackCommand_s = "KeyDetectorKeyPressed";
KeyDetector* KeyDetector::singletonPtr_s = 0;
- ManageScopedSingleton(KeyDetector, ScopeID::Graphics);
+ ManageScopedSingleton(KeyDetector, ScopeID::Graphics, false);
KeyDetector::KeyDetector()
: KeyBinder("")
Modified: code/branches/core5/src/libraries/util/Scope.h
===================================================================
--- code/branches/core5/src/libraries/util/Scope.h 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/libraries/util/Scope.h 2009-10-04 23:34:10 UTC (rev 5877)
@@ -34,7 +34,9 @@
#include <cassert>
#include <map>
#include <set>
+
#include "Debug.h"
+#include "ScopeGuard.h"
namespace orxonox
{
@@ -62,7 +64,7 @@
protected:
//! Constructor: Registers the instance.
- ScopeListener(ScopeID::Value scope) : scope_(scope)
+ ScopeListener(ScopeID::Value scope) : scope_(scope), bActivated_(false)
{ ScopeManager::listeners_s[this->scope_].insert(this); }
//! Destructor: Unregisters the instance.
virtual ~ScopeListener()
@@ -75,6 +77,7 @@
private:
ScopeID::Value scope_; //!< Store the scope to unregister on destruction
+ bool bActivated_;
};
/**
@@ -90,13 +93,26 @@
//! Constructor: Increases the instance counter and activates the scope if the count went from 0 to 1. Counts >1 don't change anything.
Scope()
{
- ScopeManager::instanceCounts_s[scope]++;
- assert(ScopeManager::instanceCounts_s[scope] > 0);
- if (ScopeManager::instanceCounts_s[scope] == 1)
+ try
{
- for (typename std::set<ScopeListener*>::iterator it = ScopeManager::listeners_s[scope].begin(); it != ScopeManager::listeners_s[scope].end(); )
- (*(it++))->activated();
+ ScopeManager::instanceCounts_s[scope]++;
+ assert(ScopeManager::instanceCounts_s[scope] > 0);
+ if (ScopeManager::instanceCounts_s[scope] == 1)
+ {
+ Loki::ScopeGuard deactivator = Loki::MakeObjGuard(*this, &Scope::deactivateListeners);
+ for (typename std::set<ScopeListener*>::iterator it = ScopeManager::listeners_s[scope].begin(); it != ScopeManager::listeners_s[scope].end(); )
+ {
+ (*it)->activated();
+ (*(it++))->bActivated_ = true;
+ }
+ deactivator.Dismiss();
+ }
}
+ catch (...)
+ {
+ ScopeManager::instanceCounts_s[scope]--;
+ throw;
+ }
}
//! Destructor: Decreases the instance counter and deactivates the scope if the count went from 1 to 0. Counts >0 don't change anything.
@@ -110,9 +126,23 @@
ScopeManager::instanceCounts_s[scope] = 0;
if (ScopeManager::instanceCounts_s[scope] == 0)
+ this->deactivateListeners();
+ }
+
+ void deactivateListeners()
+ {
+ for (typename std::set<ScopeListener*>::iterator it = ScopeManager::listeners_s[scope].begin(); it != ScopeManager::listeners_s[scope].end(); )
{
- for (typename std::set<ScopeListener*>::iterator it = ScopeManager::listeners_s[scope].begin(); it != ScopeManager::listeners_s[scope].end(); )
- (*(it++))->deactivated();
+ if ((*it)->bActivated_)
+ {
+ try
+ { (*it)->deactivated(); }
+ catch (...)
+ { COUT(0) << "ScopeListener::deactivated() failed! This MUST NOT happen, fix it!" << std::endl; }
+ (*(it++))->bActivated_ = false;
+ }
+ else
+ ++it;
}
}
Modified: code/branches/core5/src/modules/questsystem/QuestManager.cc
===================================================================
--- code/branches/core5/src/modules/questsystem/QuestManager.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/modules/questsystem/QuestManager.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -56,7 +56,7 @@
//! Pointer to the current (and single) instance of this class.
/*static*/ QuestManager* QuestManager::singletonPtr_s = NULL;
- ManageScopedSingleton(QuestManager, ScopeID::Root);
+ ManageScopedSingleton(QuestManager, ScopeID::Root, false);
/**
@brief
Modified: code/branches/core5/src/modules/questsystem/notifications/NotificationManager.cc
===================================================================
--- code/branches/core5/src/modules/questsystem/notifications/NotificationManager.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/modules/questsystem/notifications/NotificationManager.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -47,7 +47,7 @@
const std::string NotificationManager::NONE = "none";
NotificationManager* NotificationManager::singletonPtr_s = NULL;
- ManageScopedSingleton(NotificationManager, ScopeID::Root);
+ ManageScopedSingleton(NotificationManager, ScopeID::Root, false);
/**
@brief
Modified: code/branches/core5/src/orxonox/CameraManager.cc
===================================================================
--- code/branches/core5/src/orxonox/CameraManager.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/orxonox/CameraManager.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -44,8 +44,8 @@
namespace orxonox
{
- ManageScopedSingleton(CameraManager, ScopeID::Graphics);
CameraManager* CameraManager::singletonPtr_s = 0;
+ ManageScopedSingleton(CameraManager, ScopeID::Graphics, false);
CameraManager::CameraManager()
: viewport_(GraphicsManager::getInstance().getViewport())
Modified: code/branches/core5/src/orxonox/LevelManager.cc
===================================================================
--- code/branches/core5/src/orxonox/LevelManager.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/orxonox/LevelManager.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -43,8 +43,8 @@
{
SetCommandLineArgument(level, "").shortcut("l").information("Default level file (overrides LevelManager::defaultLevelName_ configValue)");
- ManageScopedSingleton(LevelManager, ScopeID::Root);
LevelManager* LevelManager::singletonPtr_s = 0;
+ ManageScopedSingleton(LevelManager, ScopeID::Root, false);
LevelManager::LevelManager()
{
Modified: code/branches/core5/src/orxonox/PlayerManager.cc
===================================================================
--- code/branches/core5/src/orxonox/PlayerManager.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/orxonox/PlayerManager.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -38,7 +38,7 @@
namespace orxonox
{
PlayerManager* PlayerManager::singletonPtr_s = 0;
- ManageScopedSingleton(PlayerManager, ScopeID::Root);
+ ManageScopedSingleton(PlayerManager, ScopeID::Root, false);
PlayerManager::PlayerManager()
{
Modified: code/branches/core5/src/orxonox/overlays/InGameConsole.cc
===================================================================
--- code/branches/core5/src/orxonox/overlays/InGameConsole.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/orxonox/overlays/InGameConsole.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -61,7 +61,7 @@
SetConsoleCommand(InGameConsole, closeConsole, true);
InGameConsole* InGameConsole::singletonPtr_s = 0;
- ManageScopedSingleton(InGameConsole, ScopeID::Graphics);
+ ManageScopedSingleton(InGameConsole, ScopeID::Graphics, false);
/**
@brief Constructor: Creates and initializes the InGameConsole.
Modified: code/branches/core5/src/orxonox/sound/SoundManager.cc
===================================================================
--- code/branches/core5/src/orxonox/sound/SoundManager.cc 2009-10-04 21:08:14 UTC (rev 5876)
+++ code/branches/core5/src/orxonox/sound/SoundManager.cc 2009-10-04 23:34:10 UTC (rev 5877)
@@ -39,7 +39,7 @@
namespace orxonox
{
SoundManager* SoundManager::singletonPtr_s = NULL;
- ManageScopedSingleton(SoundManager, ScopeID::Graphics);
+ ManageScopedSingleton(SoundManager, ScopeID::Graphics, true);
/**
* Default constructor
More information about the Orxonox-commit
mailing list