PixelLightAPI
.
|
00001 /*********************************************************\ 00002 * File: Singleton.h * 00003 * 00004 * Copyright (C) 2002-2011 The PixelLight Team (http://www.pixellight.org/) 00005 * 00006 * This file is part of PixelLight. 00007 * 00008 * PixelLight is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * PixelLight is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with PixelLight. If not, see <http://www.gnu.org/licenses/>. 00020 \*********************************************************/ 00021 00022 00023 #ifndef __PLCORE_SINGLETON_H__ 00024 #define __PLCORE_SINGLETON_H__ 00025 #pragma once 00026 00027 00028 //[-------------------------------------------------------] 00029 //[ Includes ] 00030 //[-------------------------------------------------------] 00031 #include "PLCore/PLCore.h" 00032 00033 00034 //[-------------------------------------------------------] 00035 //[ Compiler settings ] 00036 //[-------------------------------------------------------] 00037 PL_WARNING_PUSH 00038 PL_WARNING_DISABLE(4251) // "'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'" 00039 00040 00041 //[-------------------------------------------------------] 00042 //[ Namespace ] 00043 //[-------------------------------------------------------] 00044 namespace PLCore { 00045 00046 00047 //[-------------------------------------------------------] 00048 //[ Classes ] 00049 //[-------------------------------------------------------] 00050 /** 00051 * @brief 00052 * Singleton template 00053 * 00054 * @remarks 00055 * If you want to export a class based on this template by creating e.g. a dynamic library, you have to explicitly 00056 * instantiate that template class, so that the compiler can import it instead of creating an own class base 00057 * on the class template. If you don't do this, a call to ::GetInstance() will result in different objects 00058 * being created for each module, e.g. the library will then get another Singleton-instance than an application using 00059 * that library. This is of course not desired. 00060 * To instantiate and export a class, use the export-macros which are defined in each PL-library. 00061 * Because it seems that according to the ISO/IEC standard 14882 par. 17.4.3 (http://www.kuzbass.ru:8086/docs/isocpp/template.html) 00062 * instantiation of a template (which is defined in an namespace) inside another namespace is forbidden, use the 00063 * export macros like this: 00064 * namespace PLCore { 00065 * class System; 00066 * } 00067 * extern template class Singleton<System>; 00068 * 00069 * Please note that the example above may not be compatible with each legacy compiler like GCC 4.2.1 used on Mac OS X 10.6. 00070 * -> The C++11 feature "extern template" (C++11, see e.g. http://www2.research.att.com/~bs/C++0xFAQ.html#extern-templates) can only be used on modern compilers like GCC 4.6 00071 * -> In PixelLight itself, we can't break legacy compiler support, especially when only the singletons are responsible for the break 00072 * -> As workaround, singleton implementations adding "GetInstance()" and "HasInstance()" within their interface 00073 * 00074 * @note 00075 * - As the class same indicates, this is an implementation of the singleton design pattern 00076 * - Do only use singletons, if they *really* make sense - not just because it's comfortable to have a global instance, this may lead to a shaky design... 00077 */ 00078 template <class AType> class PLCORE_TMPL Singleton { 00079 00080 00081 //[-------------------------------------------------------] 00082 //[ Public functions ] 00083 //[-------------------------------------------------------] 00084 public: 00085 /** 00086 * @brief 00087 * Returns the class instance 00088 * 00089 * @return 00090 * Pointer to the instance, assumed to be never a null pointer 00091 * 00092 * @note 00093 * - Returns a pointer to the singleton instance. 00094 * The instance will be created if it has not been created before. 00095 * - The returned pointer can be a null pointer if the instance has already 00096 * been destroyed, that is on deinitialization of the program. 00097 * So be careful when using a singleton during deinitialization 00098 * of the program, or better - don't do it :-) 00099 */ 00100 static AType *GetInstance(); 00101 00102 /** 00103 * @brief 00104 * Returns whether or not there's an instance 00105 * 00106 * @return 00107 * 'true' if there's an instance, else 'false' 00108 */ 00109 static bool HasInstance(); 00110 00111 00112 //[-------------------------------------------------------] 00113 //[ Protected functions ] 00114 //[-------------------------------------------------------] 00115 protected: 00116 /** 00117 * @brief 00118 * Constructor 00119 */ 00120 Singleton(); 00121 00122 /** 00123 * @brief 00124 * Destructor 00125 */ 00126 virtual ~Singleton(); 00127 00128 00129 //[-------------------------------------------------------] 00130 //[ Private data ] 00131 //[-------------------------------------------------------] 00132 private: 00133 /** 00134 * @brief 00135 * Destruction guard, deletes a singleton on deinitialization 00136 */ 00137 class __Destruction_Guard { 00138 public: 00139 __Destruction_Guard() 00140 { 00141 } 00142 ~__Destruction_Guard() 00143 { 00144 if (Singleton<AType>::__Instance) { 00145 // Don't use reinterpret_cast in here or hell breaks loose when starting programs 00146 delete static_cast<Singleton<AType>*>(Singleton<AType>::__Instance); 00147 } 00148 } 00149 inline void init() {} 00150 }; 00151 00152 // Static data 00153 static __Destruction_Guard __Guard; /**< Destroys the object on shutdown */ 00154 static AType *__Instance; /**< Pointer to the singleton instance, can be a null pointer */ 00155 static bool __Destroyed; /**< Destruction flag - set only on shutdown */ 00156 00157 // Undefined methods to prevent usage 00158 Singleton(const Singleton&); 00159 Singleton& operator =(Singleton); 00160 00161 00162 }; 00163 00164 00165 //[-------------------------------------------------------] 00166 //[ Namespace ] 00167 //[-------------------------------------------------------] 00168 } // PLCore 00169 00170 00171 //[-------------------------------------------------------] 00172 //[ Implementation ] 00173 //[-------------------------------------------------------] 00174 #include "PLCore/Core/Singleton.inl" 00175 00176 00177 //[-------------------------------------------------------] 00178 //[ Compiler settings ] 00179 //[-------------------------------------------------------] 00180 PL_WARNING_POP 00181 00182 00183 #endif // __PLCORE_SINGLETON_H__
|