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