1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4 
5 This file is part of GtkRadiant.
6 
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21 
22 #if !defined(INCLUDED_GENERIC_STATIC_H)
23 #define INCLUDED_GENERIC_STATIC_H
24 
25 /// \file
26 /// \brief Template techniques for instantiating singletons.
27 
28 #include <cstddef>
29 
30 class Null {
31 };
32 
33 /// \brief A singleton which is statically initialised.
34 ///
35 /// \param Type The singleton object type.
36 /// \param Type The type distinguishing this instance from others of the same type.
37 ///
38 /// \skipline Static example
39 /// \until end example
40 template < typename Type, typename Context = Null >
41 class Static {
42 	static Type m_instance;
43 public:
instance()44 	static Type& instance() {
45 		return m_instance;
46 	}
47 };
48 
49 template<typename Type, typename Context>
50 Type Static<Type, Context>::m_instance;
51 
52 
53 /// \brief A singleton which is lazily initialised.
54 /// The instance is constructed the first time it is referenced, and is never destroyed.
55 ///
56 /// \param Type The singleton object type.
57 /// \param Type The type distinguishing this instance from others of the same type.
58 ///
59 /// \skipline LazyStatic example
60 /// \until end example
61 template < typename Type, typename Context = Null >
62 class LazyStatic {
63 	static Type* m_instance; // this will be initialised to 0 by the CRT, according to the c++ standard
64 public:
instance()65 	static Type& instance() {
66 		if (m_instance == 0) {
67 			m_instance = new Type; // allocate using 'new' to get the correct alignment
68 		}
69 		return *m_instance;
70 	}
71 };
72 
73 template<typename Type, typename Context>
74 Type* LazyStatic<Type, Context>::m_instance;
75 
76 
77 /// \brief A singleton which keeps a count of the number of times it is referenced.
78 ///
79 /// The instance is constructed when its reference count changes from 0 to 1 and destroyed when its reference count changes from 1 to 0.
80 /// Use with SmartStatic.
81 ///
82 /// \param Type The singleton object type.
83 /// \param Type The type distinguishing this instance from others of the same type.
84 template < typename Type, typename Context = Null >
85 class CountedStatic {
86 	static std::size_t m_refcount; // this will be initialised to 0 by the CRT, according to the c++ standard
87 	static Type* m_instance;
88 public:
instance()89 	static Type& instance() {
90 		return *m_instance;
91 	}
capture()92 	static void capture() {
93 		if (++m_refcount == 1) {
94 			m_instance = new Type; // allocate using 'new' to get the correct alignment
95 		}
96 	}
release()97 	static void release() {
98 		if (--m_refcount == 0) {
99 			delete m_instance;
100 		}
101 	}
102 };
103 
104 template<typename Type, typename Context>
105 std::size_t CountedStatic<Type, Context>::m_refcount; // this will be initialised to 0 by the CRT, according to the c++ standard
106 template<typename Type, typename Context>
107 Type* CountedStatic<Type, Context>::m_instance;
108 
109 /// \brief A reference to a CountedStatic.
110 /// Guarantees that CountedStatic<Type> will be constructed for the lifetime of this object.
111 ///
112 /// \param Type The type parameter of the CountedStatic to reference.
113 /// \param Type The type distinguishing this instance from others of the same type.
114 ///
115 /// \skipline SmartStatic example
116 /// \until end example
117 template < typename Type, typename Context = Null >
118 class SmartStatic {
119 public:
SmartStatic()120 	SmartStatic() {
121 		CountedStatic<Type, Context>::capture();
122 	}
~SmartStatic()123 	~SmartStatic() {
124 		CountedStatic<Type, Context>::release();
125 	}
instance()126 	Type& instance() {
127 		return CountedStatic<Type, Context>::instance();
128 	}
129 };
130 
131 
132 #endif
133