Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 5, 2009, 1:34:10 AM (15 years ago)
Author:
rgrieder
Message:

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.

Location:
code/branches/core5/src/libraries
Files:
5 edited

Legend:

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

    r5876 r5877  
    434434    {
    435435        // singletons from other libraries
    436         ScopedSingletonManager::update(time, ScopeID::Root);
     436        ScopedSingletonManager::update<ScopeID::Root>(time);
    437437        if (this->bGraphicsLoaded_)
    438438        {
     
    442442            this->guiManager_->update(time);
    443443            // graphics singletons from other libraries
    444             ScopedSingletonManager::update(time, ScopeID::Graphics);
     444            ScopedSingletonManager::update<ScopeID::Graphics>(time);
    445445        }
    446446        // process thread commands
  • code/branches/core5/src/libraries/core/ScopedSingletonManager.h

    r5867 r5877  
    3434#include <cassert>
    3535#include <map>
     36#include "util/Exception.h"
    3637#include "util/Scope.h"
    3738#include "util/Singleton.h"
    3839
    39 #define ManageScopedSingleton(className, scope) \
    40     static ClassScopedSingletonManager<className, scope> className##ScopedSingletonManager(#className)
     40#define ManageScopedSingleton(className, scope, allowedToFail) \
     41    static ClassScopedSingletonManager<className, scope, allowedToFail> className##ScopedSingletonManager(#className)
    4142
    4243namespace orxonox
     
    5354            static void removeManager(ScopedSingletonManager* manager);
    5455
    55             static void update(const Clock& time, ScopeID::Value scope)
     56            template<ScopeID::Value scope>
     57            static void update(const Clock& time)
    5658            {
     59                assert(Scope<scope>::isActive());
    5760                for (ManagerMultiMap::iterator it = getManagersByScope().lower_bound(scope); it != getManagersByScope().upper_bound(scope); ++it)
    5861                    it->second->update(time);
     
    6972    };
    7073
    71     template <class T, ScopeID::Value scope>
     74    template <class T, ScopeID::Value scope, bool allowedToFail>
    7275    class ClassScopedSingletonManager : public ScopedSingletonManager, public ScopeListener
    7376    {
     
    8386        ~ClassScopedSingletonManager()
    8487        {
     88            assert(singletonPtr_ == NULL);
    8589            ScopedSingletonManager::removeManager(this);
    8690        }
     
    101105        }
    102106
     107        void destroy(OrxonoxClass*)
     108        {
     109            singletonPtr_->destroy();
     110        }
     111        void destroy(void*)
     112        {
     113            delete singletonPtr_;
     114        }
     115
     116        //! Called every frame by the ScopedSingletonManager
     117        void update(const Clock& time)
     118        {
     119            assert(Scope<scope>::isActive());
     120            // assuming T inherits Singleton<T>
     121            singletonPtr_->updateSingleton(time);
     122        }
     123
     124    private:
     125        T* singletonPtr_;
     126    };
     127
     128    template <class T, ScopeID::Value scope>
     129    class ClassScopedSingletonManager<T, scope, true> : public ScopedSingletonManager, public ScopeListener
     130    {
     131    public:
     132        ClassScopedSingletonManager(const std::string& className)
     133            : ScopedSingletonManager(className, scope)
     134            , ScopeListener(scope)
     135            , singletonPtr_(NULL)
     136        {
     137            ScopedSingletonManager::addManager(this);
     138        }
     139
     140        ~ClassScopedSingletonManager()
     141        {
     142            assert(singletonPtr_ == NULL);
     143            ScopedSingletonManager::removeManager(this);
     144        }
     145
     146        //! Called if the Scope of the Singleton gets active (creates the instance)
     147        void activated()
     148        {
     149            assert(singletonPtr_ == NULL);
     150            try
     151                { singletonPtr_ = new T(); }
     152            catch (...)
     153                { COUT(1) << "Singleton creation failed: " << Exception::handleMessage() << std::endl; }
     154        }
     155
     156        //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
     157        void deactivated()
     158        {
     159            if (singletonPtr_ != NULL)
     160            {
     161                this->destroy(singletonPtr_);
     162                singletonPtr_ = NULL;
     163            }
     164        }
     165
    103166        void destroy(OrxonoxClass* ptr)
    104167        {
     
    113176        void update(const Clock& time)
    114177        {
     178            assert(Scope<scope>::isActive());
    115179            // assuming T inherits Singleton<T>
    116             singletonPtr_->updateSingleton(time);
     180            if (singletonPtr_ != NULL)
     181                singletonPtr_->updateSingleton(time);
    117182        }
    118183
  • code/branches/core5/src/libraries/core/input/KeyBinderManager.cc

    r5869 r5877  
    4141{
    4242    KeyBinderManager* KeyBinderManager::singletonPtr_s = 0;
    43     ManageScopedSingleton(KeyBinderManager, ScopeID::Graphics);
     43    ManageScopedSingleton(KeyBinderManager, ScopeID::Graphics, false);
    4444
    4545    KeyBinderManager::KeyBinderManager()
  • code/branches/core5/src/libraries/core/input/KeyDetector.cc

    r5869 r5877  
    4040    std::string KeyDetector::callbackCommand_s = "KeyDetectorKeyPressed";
    4141    KeyDetector* KeyDetector::singletonPtr_s = 0;
    42     ManageScopedSingleton(KeyDetector, ScopeID::Graphics);
     42    ManageScopedSingleton(KeyDetector, ScopeID::Graphics, false);
    4343
    4444    KeyDetector::KeyDetector()
  • code/branches/core5/src/libraries/util/Scope.h

    r5867 r5877  
    3535#include <map>
    3636#include <set>
     37
    3738#include "Debug.h"
     39#include "ScopeGuard.h"
    3840
    3941namespace orxonox
     
    6365        protected:
    6466            //! Constructor: Registers the instance.
    65             ScopeListener(ScopeID::Value scope) : scope_(scope)
     67            ScopeListener(ScopeID::Value scope) : scope_(scope), bActivated_(false)
    6668                { ScopeManager::listeners_s[this->scope_].insert(this); }
    6769            //! Destructor: Unregisters the instance.
     
    7678        private:
    7779            ScopeID::Value scope_; //!< Store the scope to unregister on destruction
     80            bool bActivated_;
    7881    };
    7982
     
    9194            Scope()
    9295            {
    93                 ScopeManager::instanceCounts_s[scope]++;
    94                 assert(ScopeManager::instanceCounts_s[scope] > 0);
    95                 if (ScopeManager::instanceCounts_s[scope] == 1)
     96                try
    9697                {
    97                     for (typename std::set<ScopeListener*>::iterator it = ScopeManager::listeners_s[scope].begin(); it != ScopeManager::listeners_s[scope].end(); )
    98                         (*(it++))->activated();
     98                    ScopeManager::instanceCounts_s[scope]++;
     99                    assert(ScopeManager::instanceCounts_s[scope] > 0);
     100                    if (ScopeManager::instanceCounts_s[scope] == 1)
     101                    {
     102                        Loki::ScopeGuard deactivator = Loki::MakeObjGuard(*this, &Scope::deactivateListeners);
     103                        for (typename std::set<ScopeListener*>::iterator it = ScopeManager::listeners_s[scope].begin(); it != ScopeManager::listeners_s[scope].end(); )
     104                        {
     105                            (*it)->activated();
     106                            (*(it++))->bActivated_ = true;
     107                        }
     108                        deactivator.Dismiss();
     109                    }
     110                }
     111                catch (...)
     112                {
     113                    ScopeManager::instanceCounts_s[scope]--;
     114                    throw;
    99115                }
    100116            }
     
    111127
    112128                if (ScopeManager::instanceCounts_s[scope] == 0)
     129                    this->deactivateListeners();
     130            }
     131
     132            void deactivateListeners()
     133            {
     134                for (typename std::set<ScopeListener*>::iterator it = ScopeManager::listeners_s[scope].begin(); it != ScopeManager::listeners_s[scope].end(); )
    113135                {
    114                     for (typename std::set<ScopeListener*>::iterator it = ScopeManager::listeners_s[scope].begin(); it != ScopeManager::listeners_s[scope].end(); )
    115                         (*(it++))->deactivated();
     136                    if ((*it)->bActivated_)
     137                    {
     138                        try
     139                            { (*it)->deactivated(); }
     140                        catch (...)
     141                            { COUT(0) << "ScopeListener::deactivated() failed! This MUST NOT happen, fix it!" << std::endl; }
     142                        (*(it++))->bActivated_ = false;
     143                    }
     144                    else
     145                        ++it;
    116146                }
    117147            }
Note: See TracChangeset for help on using the changeset viewer.