1 //------------------------------------------------------------------------------
2 // File : SkySingleton.hpp
3 //------------------------------------------------------------------------------
4 // SkyWorks : Copyright 2002 Mark J. Harris and
5 // The University of North Carolina at Chapel Hill
6 //------------------------------------------------------------------------------
7 // Permission to use, copy, modify, distribute and sell this software and its
8 // documentation for any purpose is hereby granted without fee, provided that
9 // the above copyright notice appear in all copies and that both that copyright
10 // notice and this permission notice appear in supporting documentation.
11 // Binaries may be compiled with this software without any royalties or
14 // The author(s) and The University of North Carolina at Chapel Hill make no
15 // representations about the suitability of this software for any purpose.
16 // It is provided "as is" without express or
19 * @file SkySingleton.hpp
21 * A generic singleton template wrapper to make classes into singletons
23 #ifndef __SKYSINGLETON_HPP__
24 #define __SKYSINGLETON_HPP__
26 #include "SkyUtil.hpp"
30 //------------------------------------------------------------------------------
33 * @brief A singleton template class.
35 * Usage : Use this template container class to make any class into a
36 * singleton. I usually do this:
42 * // normal class stuff, but don't put ctor/dtor here.
43 * int GetData() { return _someData; }
45 * // Make the ctor(s)/dtor protected, so this can only be
46 * // instantiated as a singleton. Note: singleton will still
47 * // work on classes that do not follow this (public ctors)
48 * // but violation of the singleton is possible then, since non-
49 * // singleton versions of the class can be instantiated.
50 * MyClass() : _someData(5) {}
51 * MyClass(int arg) : _someData(arg) {} // etc...
52 * // don't implement the copy constructor, because singletons
53 * // shouldn't be copied!
54 * MyClass(const MyClass& mc) {}
60 * // now create a singleton of MyClass
61 * typedef SkySingleton<MyClass> MyClassSingleton;
64 * Later, in your program code, you can instantiate the singleton and access
65 * its members like so:
70 * // instantiate the MyClassSingleton
71 * MyClassSingleton::Instantiate();
72 * // could also call MyClassSingleton::Instantiate(10);
73 * // since we have a constructor of that form in MyClass.
75 * // access the methods in MyClass:
76 * int data1 = MyClassSingleton::InstancePtr()->GetData();
78 * int data2 = MyClassSingleton::InstanceRef().GetData();
80 * // now destroy the singleton
81 * MyClassSingleton::Destroy();
86 class SkySingleton : protected T
90 //------------------------------------------------------------------------------
91 // Function : Instantiate
93 //------------------------------------------------------------------------------
96 * @brief Creates the singleton instance for class T.
98 * Assures (by assertion) that the instance will only be created once.
99 * This works for default constructors.
101 static void Instantiate()
103 assert(!s_pInstance);
104 s_pInstance = new SkySingleton();
107 //------------------------------------------------------------------------------
108 // Function : Destroy
110 //------------------------------------------------------------------------------
112 * @fn Destroy() { SAFE_DELETE(s_pInstance); }
113 * @brief Destructor, deletes the instance
115 static void Destroy() { SAFE_DELETE(s_pInstance); }
117 //------------------------------------------------------------------------------
118 // Function : InstancePtr
120 //------------------------------------------------------------------------------
122 * @fn InstancePtr() { assert(s_pInstance); return s_pInstance; }
123 * @brief Returns a pointer to the instance
125 static T* InstancePtr() { assert(s_pInstance); return s_pInstance; }
127 //------------------------------------------------------------------------------
128 // Function : InstanceRef
130 //------------------------------------------------------------------------------
132 * @fn InstanceRef() { assert(s_pInstance); return *s_pInstance; }
133 * @brief Returns a reference to the instance
135 static T& InstanceRef() { assert(s_pInstance); return *s_pInstance; }
137 //------------------------------------------------------------------------------
138 // Function : static void Instantiate
140 //------------------------------------------------------------------------------
142 * @fn static void Instantiate(const A& a)
143 * @brief Instantiates class of type T that have constructors with an argument
145 * This might be a source of confusion. These templatized
146 * functions are used to instantiate classes of type T that
147 * have constructors with arguments. For n arguments, you
148 * to add a function below with n arguments. Note, these will
149 * only be created if they are used, since they are templates.
150 * I've added 4 below, for 1-4 arguments. If you get a
151 * compilation error, add one for the number of arguments you
152 * need. Also need a SkySingleton protected constructor with
153 * the same number of arguments.
156 static void Instantiate(const A& a)
158 assert(!s_pInstance);
159 s_pInstance = new SkySingleton(a);
162 //------------------------------------------------------------------------------
163 // Function : Instantiate
165 //------------------------------------------------------------------------------
167 * @fn Instantiate(const A& a, const B& b)
168 * @brief Instantiates class of type T that have constructors with 2 args
170 template<class A, class B>
171 static void Instantiate(const A& a, const B& b)
173 assert(!s_pInstance);
174 s_pInstance = new SkySingleton(a, b);
177 //------------------------------------------------------------------------------
178 // Function : Instantiate
180 //------------------------------------------------------------------------------
182 * @fn Instantiate(const A& a, const B& b, const C& c)
183 * @brief Instantiates class of type T that have constructors with 3 args
185 template<class A, class B, class C>
186 static void Instantiate(const A& a, const B& b, const C& c)
188 assert(!s_pInstance);
189 s_pInstance = new SkySingleton(a, b, c);
192 //------------------------------------------------------------------------------
193 // Function : Instantiate
195 //------------------------------------------------------------------------------
197 * @fn Instantiate(const A& a, const B& b, const C& c, const D& d)
198 * @brief Instantiates class of type T that have constructors with 4 args
200 template<class A, class B, class C, class D>
201 static void Instantiate(const A& a, const B& b, const C& c, const D& d)
203 assert(!s_pInstance);
204 s_pInstance = new SkySingleton(a, b, c, d);
208 // although the instance is of type SkySingleton<T>, the Instance***() funcs
209 // above implicitly cast it to type T.
210 static SkySingleton* s_pInstance;
214 //------------------------------------------------------------------------------
215 // Function : SkySingleton
217 //------------------------------------------------------------------------------
220 * @brief Hidden so that the singleton can only be instantiated via public static Instantiate function.
222 SkySingleton() : T() {}
224 //------------------------------------------------------------------------------
225 // Function : Singleton
227 //------------------------------------------------------------------------------
229 * @fn Singleton(const A& a)
230 * @brief Used by the templatized public Instantiate() functions.
233 SkySingleton(const A& a) : T(a) {}
235 //------------------------------------------------------------------------------
236 // Function : Singleton
238 //------------------------------------------------------------------------------
240 * @fn Singleton(const A& a, const B& b)
241 * @brief Used by the templatized public Instantiate() functions.
243 template<class A, class B>
244 SkySingleton(const A& a, const B& b) : T(a, b) {}
246 //------------------------------------------------------------------------------
247 // Function : Singleton
249 //------------------------------------------------------------------------------
251 * @fn Singleton(const A& a, const B& b, const C& c)
252 * @brief Used by the templatized public Instantiate() functions.
254 template<class A, class B, class C>
255 SkySingleton(const A& a, const B& b, const C& c) : T(a, b, c) {}
257 //------------------------------------------------------------------------------
258 // Function : Singleton
260 //------------------------------------------------------------------------------
262 * @fn Singleton(const A& a, const B& b, const C &c, const D& d)
263 * @brief Used by the templatized public Instantiate() functions.
265 template<class A, class B, class C, class D>
266 SkySingleton(const A& a, const B& b, const C &c, const D& d) : T(a, b, c, d) {}
268 //------------------------------------------------------------------------------
269 // Function : SkySingleton
271 //------------------------------------------------------------------------------
273 * @fn SkySingleton(const SkySingleton&)
274 * @brief Hidden because you can't copy a singleton!
276 SkySingleton(const SkySingleton&) {} // hide the copy ctor: singletons can'
278 //------------------------------------------------------------------------------
279 // Function : ~SkySingleton
281 //------------------------------------------------------------------------------
283 * @fn ~SkySingleton()
284 * @brief Destructor, hidden, destroy via the public static Destroy() method.
286 ~SkySingleton() {} // hide the dtor:
289 // declare the static instance pointer
290 template<class T> SkySingleton<T>* SkySingleton<T>::s_pInstance = NULL;
292 #endif //__SKYSINGLETON_HPP__