Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core5/src/libraries/core/ScopedSingletonManager.h @ 5877

Last change on this file since 5877 was 5877, checked in by rgrieder, 15 years ago

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.

  • Property svn:eol-style set to native
File size: 5.8 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#ifndef __ScopedSingletonManager_H__
30#define __ScopedSingletonManager_H__
31
32#include "CorePrereqs.h"
33
34#include <cassert>
35#include <map>
36#include "util/Exception.h"
37#include "util/Scope.h"
38#include "util/Singleton.h"
39
40#define ManageScopedSingleton(className, scope, allowedToFail) \
41    static ClassScopedSingletonManager<className, scope, allowedToFail> className##ScopedSingletonManager(#className)
42
43namespace orxonox
44{
45    class _CoreExport ScopedSingletonManager
46    {
47        public:
48            ScopedSingletonManager(const std::string& className, ScopeID::Value scope)
49                : className_(className)
50                , scope_(scope)
51            { }
52            virtual ~ScopedSingletonManager() { }
53            static void addManager(ScopedSingletonManager* manager);
54            static void removeManager(ScopedSingletonManager* manager);
55
56            template<ScopeID::Value scope>
57            static void update(const Clock& time)
58            {
59                assert(Scope<scope>::isActive());
60                for (ManagerMultiMap::iterator it = getManagersByScope().lower_bound(scope); it != getManagersByScope().upper_bound(scope); ++it)
61                    it->second->update(time);
62            }
63            virtual void update(const Clock& time) = 0;
64
65            static std::map<std::string, ScopedSingletonManager*>& getManagers();
66            typedef std::multimap<ScopeID::Value, ScopedSingletonManager*> ManagerMultiMap;
67            static ManagerMultiMap& getManagersByScope();
68
69        protected:
70            const std::string className_;
71            const ScopeID::Value scope_;
72    };
73
74    template <class T, ScopeID::Value scope, bool allowedToFail>
75    class ClassScopedSingletonManager : public ScopedSingletonManager, public ScopeListener
76    {
77    public:
78        ClassScopedSingletonManager(const std::string& className)
79            : ScopedSingletonManager(className, scope)
80            , ScopeListener(scope)
81            , singletonPtr_(NULL)
82        {
83            ScopedSingletonManager::addManager(this);
84        }
85
86        ~ClassScopedSingletonManager()
87        {
88            assert(singletonPtr_ == NULL);
89            ScopedSingletonManager::removeManager(this);
90        }
91
92        //! Called if the Scope of the Singleton gets active (creates the instance)
93        void activated()
94        {
95            assert(singletonPtr_ == NULL);
96            singletonPtr_ = new T();
97        }
98
99        //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
100        void deactivated()
101        {
102            assert(singletonPtr_ != NULL);
103            this->destroy(singletonPtr_);
104            singletonPtr_ = NULL;
105        }
106
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
166        void destroy(OrxonoxClass* ptr)
167        {
168            singletonPtr_->destroy();
169        }
170        void destroy(void* ptr)
171        {
172            delete singletonPtr_;
173        }
174
175        //! Called every frame by the ScopedSingletonManager
176        void update(const Clock& time)
177        {
178            assert(Scope<scope>::isActive());
179            // assuming T inherits Singleton<T>
180            if (singletonPtr_ != NULL)
181                singletonPtr_->updateSingleton(time);
182        }
183
184    private:
185        T* singletonPtr_;
186    };
187}
188
189#endif /* __ScopedSingletonManager_H__ */
Note: See TracBrowser for help on using the repository browser.