Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/libraries/core/singleton/ScopedSingletonWrapper.h @ 10458

Last change on this file since 10458 was 10458, checked in by landauf, 9 years ago

renamed ScopedSingletonManager to ScopedSingletonWrapper. removed static maps.

  • Property svn:eol-style set to native
File size: 8.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::ScopedSingletonWrapper, orxonox::ClassScopedSingletonWrapper, and the ManageScopedSingleton macro.
33
34    ScopedSingletonWrapper 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 wrapper with orxonox::ScopeManager.
37
38    See @ref SingletonExample "this code" for an example.
39
40    @see orxonox::Singleton
41    @see orxonox::Scope
42*/
43
44#ifndef __ScopedSingletonWrapper_H__
45#define __ScopedSingletonWrapper_H__
46
47#include "core/CorePrereqs.h"
48
49#include <cassert>
50#include "util/Exception.h"
51#include "util/Singleton.h"
52#include "Scope.h"
53
54/**
55    @brief Creates an orxonox::ScopedSingletonWrapper for an orxonox::Singleton and registers it with orxonox::ScopeManager.
56    @param className The name of the singleton class
57    @param scope The scope in which the singleton should exist
58    @param allowedToFail If true, the singleton is allowed to fail and thus a try-catch block is used when creating the singleton.
59
60    If this macro is called for a singleton, it is wrapped in a ScopedSingletonWrapper and registered with ScopeManager
61    and will thus be created if its scope becomes active and destroyed if is deactivated.
62
63
64    Usually a singleton gets created automatically when it is first used, but it will never
65    be destroyed (unless the singleton explicitly deletes itself). To allow controlled
66    construction and destruction, the singleton can be put within a virtual scope. This is
67    done by registering the singleton class with orxonox::ScopeManager. To
68    do so, the ManageScopedSingleton() macro has to be called:
69
70    @code
71    ManageScopedSingleton(TestSingleton, ScopeID::Graphics, false); // muste be called in a source (*.cc) file
72    @endcode
73
74    @b Important: If you call ManageScopedSingleton(), you don't have to initialize singletonPtr_s anymore,
75    because that's already done by the macro.
76
77    Now the singleton TestSingleton gets automatically created if the scope Graphics becomes
78    active and also gets destroyed if the scope is deactivated.
79
80    Note that not all singletons must register with a scope, but it's recommended.
81
82*/
83#define ManageScopedSingleton(className, scope, allowedToFail) \
84    className* className::singletonPtr_s = NULL; \
85    static ClassScopedSingletonWrapper<className, scope, allowedToFail> className##ScopedSingletonWrapper(#className)
86
87namespace orxonox
88{
89    /**
90        @brief Base class of ClassScopedSingletonWrapper.
91    */
92    class _CoreExport ScopedSingletonWrapper
93    {
94        public:
95            /// Constructor: Initializes all the values
96            ScopedSingletonWrapper(const std::string& className, ScopeID::Value scope)
97                : className_(className)
98                , scope_(scope)
99            { }
100            virtual ~ScopedSingletonWrapper() { }
101
102        protected:
103            const std::string className_;   ///< The name of the scoped singleton class that is managed by this object
104            const ScopeID::Value scope_;    ///< The scope of the singleton that is managed by this object
105    };
106
107    /**
108        @anchor ClassScopedSingletonWrapper
109
110        @brief Manages a scoped singleton for a given scope.
111        @param T The managed singleton class
112        @param scope The scope in which the singleton @a T should be active
113        @param allowedToFail If true, a specialization of this template is used, that uses try-catch blocks to handle possible failures.
114
115        This class inherits from ScopeListener for the given scope and thus its functions
116        activated() and deactivated() are called whenever the Scope changes its state.
117
118        If the Scope is activated, a new instance of @a T (which must be a singleton) is created.
119        If the Scope is deactivated, the singleton is destroyed.
120
121        @see Singleton
122    */
123    template <class T, ScopeID::Value scope, bool allowedToFail>
124    class ClassScopedSingletonWrapper : public ScopedSingletonWrapper, public ScopeListener
125    {
126    public:
127        //! Constructor: Initializes the singleton pointer and passes the scope to ScopedSingletonWrapper and ScopeListener
128        ClassScopedSingletonWrapper(const std::string& className)
129            : ScopedSingletonWrapper(className, scope)
130            , ScopeListener(scope)
131            , singletonPtr_(NULL)
132        {
133        }
134
135        ~ClassScopedSingletonWrapper()
136        {
137        }
138
139        //! Called if the Scope of the Singleton gets active (creates the instance)
140        void activated()
141        {
142            assert(singletonPtr_ == NULL);
143            singletonPtr_ = new T();
144        }
145
146        //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
147        void deactivated()
148        {
149            assert(singletonPtr_ != NULL);
150            this->destroy(singletonPtr_);
151            singletonPtr_ = NULL;
152        }
153
154        //! Destroys the singleton instance - overloaded for Destroyable, calls Destroyable::destroy()
155        void destroy(Destroyable*)
156        {
157            singletonPtr_->destroy();
158        }
159        //! Destroys the singleton instance - overloaded for all other pointers, calls delete
160        void destroy(void*)
161        {
162            delete singletonPtr_;
163        }
164
165    private:
166        T* singletonPtr_;   ///< Unique instance of the singleton class @a T
167    };
168
169    /**
170        @brief This class partially spezializes ClassScopedSingletonWrapper for classes @a T that are allowed to fail.
171        @param T The managed singleton class
172        @param scope The scope in which the singleton @a T should be active
173
174        Because @a T could fail when being created, this partial spezialization of ClassScopedSingletonWrapper
175        uses a try-catch block to handle exceptions.
176
177        See @ref ClassScopedSingletonWrapper for a full documentation of the basis template.
178    */
179    template <class T, ScopeID::Value scope>
180    class ClassScopedSingletonWrapper<T, scope, true> : public ScopedSingletonWrapper, public ScopeListener
181    {
182    public:
183        //! Constructor: Initializes the singleton pointer and passes the scope to ScopedSingletonWrapper and ScopeListener
184        ClassScopedSingletonWrapper(const std::string& className)
185            : ScopedSingletonWrapper(className, scope)
186            , ScopeListener(scope)
187            , singletonPtr_(NULL)
188        {
189        }
190
191        ~ClassScopedSingletonWrapper()
192        {
193        }
194
195        //! Called if the Scope of the Singleton gets active (creates the instance)
196        void activated()
197        {
198            assert(singletonPtr_ == NULL);
199            try
200                { singletonPtr_ = new T(); }
201            catch (const InitialisationAbortedException& ex)
202                { orxout(internal_error) << ex.getDescription() << endl; }
203            catch (...)
204                { orxout(internal_error) << "Singleton creation failed: " << Exception::handleMessage() << endl; }
205        }
206
207        //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
208        void deactivated()
209        {
210            if (singletonPtr_ != NULL)
211            {
212                this->destroy(singletonPtr_);
213                singletonPtr_ = NULL;
214            }
215        }
216
217        //! Destroys the singleton instance - overloaded for Destroyable, calls Destroyable::destroy()
218        void destroy(Destroyable*)
219        {
220            singletonPtr_->destroy();
221        }
222        //! Destroys the singleton instance - overloaded for void*, calls delete
223        void destroy(void*)
224        {
225            delete singletonPtr_;
226        }
227
228    private:
229        T* singletonPtr_;   ///< Unique instance of the singleton class @a T
230    };
231}
232
233#endif /* __ScopedSingletonWrapper_H__ */
Note: See TracBrowser for help on using the repository browser.