Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/util/ScopedSingletonManager.h @ 9667

Last change on this file since 9667 was 9667, checked in by landauf, 11 years ago

merged core6 back to trunk

  • Property svn:eol-style set to native
File size: 10.6 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/**
30    @file
31    @ingroup SingletonScope
32    @brief Definition of orxonox::ScopedSingletonManager, orxonox::ClassScopedSingletonManager, and the ManageScopedSingleton macro.
33
34    ScopedSingletonManager is used to create and destroy Singletons that belong to
35    a given Scope. For each one of these singletons, the macro ManageScopedSingleton()
36    has to be called to register the singleton with orxonox::ScopedSingletonManager.
37
38    See @ref SingletonExample "this code" for an example.
39
40    @see orxonox::Singleton
41    @see orxonox::Scope
42*/
43
44#ifndef __ScopedSingletonManager_H__
45#define __ScopedSingletonManager_H__
46
47#include "UtilPrereqs.h"
48
49#include <cassert>
50#include <map>
51#include "util/Exception.h"
52#include "util/Scope.h"
53#include "util/Singleton.h"
54
55/**
56    @brief Registers an orxonox::Singleton with orxonox::ScopedSingletonManager.
57    @param className The name of the singleton class
58    @param scope The scope in which the singleton should exist
59    @param allowedToFail If true, the singleton is allowed to fail and thus a try-catch block is used when creating the singleton.
60
61    If this macro is called for a singleton, it is registered with ScopedSingletonManager
62    and will thus be created if its scope becomes active and destroyed if is deactivated.
63*/
64#define ManageScopedSingleton(className, scope, allowedToFail) \
65    className* className::singletonPtr_s = NULL; \
66    static ClassScopedSingletonManager<className, scope, allowedToFail> className##ScopedSingletonManager(#className)
67
68namespace orxonox
69{
70    class Destroyable;
71
72    /**
73        @brief Base class of ClassScopedSingletonManager, implements some static functions
74        used to dispatch calls to preUpdate and postUpdate to all instances of this class.
75        It also keeps track of all existing ScopedSingletonManagers and stores them in a
76        map, sorted by the scope they belong to.
77    */
78    class _UtilExport ScopedSingletonManager
79    {
80        public:
81            /// Constructor: Initializes all the values
82            ScopedSingletonManager(const std::string& className, ScopeID::Value scope)
83                : className_(className)
84                , scope_(scope)
85            { }
86            virtual ~ScopedSingletonManager() { }
87
88            /// Adds a new instance of ScopedSingletonManager to the map.
89            static void addManager(ScopedSingletonManager* manager);
90
91            /// Calls preUpdate in all instances of ScopedSingletonManager that are registered in the map.
92            template<ScopeID::Value scope>
93            static void preUpdate(const Clock& time)
94            {
95                assert(Scope<scope>::isActive());
96                for (ManagerMultiMap::iterator it = getManagersByScope().lower_bound(scope); it != getManagersByScope().upper_bound(scope); ++it)
97                    it->second->preUpdate(time);
98            }
99            virtual void preUpdate(const Clock& time) = 0;
100
101            /// Calls postUpdate in all instances of ScopedSingletonManager that are registered in the map.
102            template<ScopeID::Value scope>
103            static void postUpdate(const Clock& time)
104            {
105                assert(Scope<scope>::isActive());
106                for (ManagerMultiMap::iterator it = getManagersByScope().lower_bound(scope); it != getManagersByScope().upper_bound(scope); ++it)
107                    it->second->postUpdate(time);
108            }
109            virtual void postUpdate(const Clock& time) = 0;
110
111            static std::map<std::string, ScopedSingletonManager*>& getManagers();
112            typedef std::multimap<ScopeID::Value, ScopedSingletonManager*> ManagerMultiMap;
113            static ManagerMultiMap& getManagersByScope();
114
115        protected:
116            const std::string className_;   ///< The name of the scoped singleton class that is managed by this object
117            const ScopeID::Value scope_;    ///< The scope of the singleton that is managed by this object
118    };
119
120    /**
121        @anchor ClassScopedSingletonManager
122
123        @brief Manages a scoped singleton for a given scope.
124        @param T The managed singleton class
125        @param scope The scope in which the singleton @a T should be active
126        @param allowedToFail If true, a specialization of this template is used, that uses try-catch blocks to handle possible failures.
127
128        This class inherits from ScopeListener for the given scope and thus its functions
129        activated() and deactivated() are called whenever the Scope changes its state.
130
131        If the Scope is activated, a new instance of @a T (which must be a singleton) is created.
132        If the Scope is deactivated, the singleton is destroyed.
133
134        @see Singleton
135    */
136    template <class T, ScopeID::Value scope, bool allowedToFail>
137    class ClassScopedSingletonManager : public ScopedSingletonManager, public ScopeListener
138    {
139    public:
140        //! Constructor: Initializes the singleton pointer and passes the scope to ScopedSingletonManager and ScopeListener
141        ClassScopedSingletonManager(const std::string& className)
142            : ScopedSingletonManager(className, scope)
143            , ScopeListener(scope)
144            , singletonPtr_(NULL)
145        {
146            ScopedSingletonManager::addManager(this);
147        }
148
149        ~ClassScopedSingletonManager()
150        {
151        }
152
153        //! Called if the Scope of the Singleton gets active (creates the instance)
154        void activated()
155        {
156            assert(singletonPtr_ == NULL);
157            singletonPtr_ = new T();
158        }
159
160        //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
161        void deactivated()
162        {
163            assert(singletonPtr_ != NULL);
164            this->destroy(singletonPtr_);
165            singletonPtr_ = NULL;
166        }
167
168        //! Destroys the singleton instance - overloaded for Destroyable, calls Destroyable::destroy()
169        void destroy(Destroyable*)
170        {
171            singletonPtr_->destroy();
172        }
173        //! Destroys the singleton instance - overloaded for all other pointers, calls delete
174        void destroy(void*)
175        {
176            delete singletonPtr_;
177        }
178
179        //! Called every frame by the ScopedSingletonManager
180        void preUpdate(const Clock& time)
181        {
182            assert(Scope<scope>::isActive());
183            // assuming T inherits Singleton<T>
184            singletonPtr_->preUpdateSingleton(time);
185        }
186
187        //! Called every frame by the ScopedSingletonManager
188        void postUpdate(const Clock& time)
189        {
190            assert(Scope<scope>::isActive());
191            // assuming T inherits Singleton<T>
192            singletonPtr_->postUpdateSingleton(time);
193        }
194
195    private:
196        T* singletonPtr_;   ///< Unique instance of the singleton class @a T
197    };
198
199    /**
200        @brief This class partially spezializes ClassScopedSingletonManager for classes @a T that are allowed to fail.
201        @param T The managed singleton class
202        @param scope The scope in which the singleton @a T should be active
203
204        Because @a T could fail when being created, this partial spezialization of ClassScopedSingletonManager
205        uses a try-catch block to handle exceptions.
206
207        See @ref ClassScopedSingletonManager for a full documentation of the basis template.
208    */
209    template <class T, ScopeID::Value scope>
210    class ClassScopedSingletonManager<T, scope, true> : public ScopedSingletonManager, public ScopeListener
211    {
212    public:
213        //! Constructor: Initializes the singleton pointer and passes the scope to ScopedSingletonManager and ScopeListener
214        ClassScopedSingletonManager(const std::string& className)
215            : ScopedSingletonManager(className, scope)
216            , ScopeListener(scope)
217            , singletonPtr_(NULL)
218        {
219            ScopedSingletonManager::addManager(this);
220        }
221
222        ~ClassScopedSingletonManager()
223        {
224        }
225
226        //! Called if the Scope of the Singleton gets active (creates the instance)
227        void activated()
228        {
229            assert(singletonPtr_ == NULL);
230            try
231                { singletonPtr_ = new T(); }
232            catch (const InitialisationAbortedException& ex)
233                { orxout(internal_error) << ex.getDescription() << endl; }
234            catch (...)
235                { orxout(internal_error) << "Singleton creation failed: " << Exception::handleMessage() << endl; }
236        }
237
238        //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
239        void deactivated()
240        {
241            if (singletonPtr_ != NULL)
242            {
243                this->destroy(singletonPtr_);
244                singletonPtr_ = NULL;
245            }
246        }
247
248        //! Destroys the singleton instance - overloaded for Destroyable, calls Destroyable::destroy()
249        void destroy(Destroyable*)
250        {
251            singletonPtr_->destroy();
252        }
253        //! Destroys the singleton instance - overloaded for void*, calls delete
254        void destroy(void*)
255        {
256            delete singletonPtr_;
257        }
258
259        //! Called every frame by the ScopedSingletonManager
260        void preUpdate(const Clock& time)
261        {
262            assert(Scope<scope>::isActive());
263            // assuming T inherits Singleton<T>
264            if (singletonPtr_ != NULL)
265                singletonPtr_->preUpdateSingleton(time);
266        }
267
268        //! Called every frame by the ScopedSingletonManager
269        void postUpdate(const Clock& time)
270        {
271            assert(Scope<scope>::isActive());
272            // assuming T inherits Singleton<T>
273            if (singletonPtr_ != NULL)
274                singletonPtr_->postUpdateSingleton(time);
275        }
276
277    private:
278        T* singletonPtr_;   ///< Unique instance of the singleton class @a T
279    };
280}
281
282#endif /* __ScopedSingletonManager_H__ */
Note: See TracBrowser for help on using the repository browser.