llsingleton.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:6k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llsingleton.h
  3.  *
  4.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  5.  * 
  6.  * Copyright (c) 2002-2010, Linden Research, Inc.
  7.  * 
  8.  * Second Life Viewer Source Code
  9.  * The source code in this file ("Source Code") is provided by Linden Lab
  10.  * to you under the terms of the GNU General Public License, version 2.0
  11.  * ("GPL"), unless you have obtained a separate licensing agreement
  12.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  13.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15.  * 
  16.  * There are special exceptions to the terms and conditions of the GPL as
  17.  * it is applied to this Source Code. View the full text of the exception
  18.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  19.  * online at
  20.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21.  * 
  22.  * By copying, modifying or distributing this software, you acknowledge
  23.  * that you have read and understood your obligations described above,
  24.  * and agree to abide by those obligations.
  25.  * 
  26.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28.  * COMPLETENESS OR PERFORMANCE.
  29.  * $/LicenseInfo$
  30.  */
  31. #ifndef LLSINGLETON_H
  32. #define LLSINGLETON_H
  33. #include "llerror.h" // *TODO: eliminate this
  34. #include <typeinfo>
  35. #include <boost/noncopyable.hpp>
  36. /// @brief A global registry of all singletons to prevent duplicate allocations
  37. /// across shared library boundaries
  38. class LL_COMMON_API LLSingletonRegistry {
  39. private:
  40. typedef std::map<std::string, void *> TypeMap;
  41. static TypeMap * sSingletonMap;
  42. static void checkInit()
  43. {
  44. if(sSingletonMap == NULL)
  45. {
  46. sSingletonMap = new TypeMap();
  47. }
  48. }
  49. public:
  50. template<typename T> static void * & get()
  51. {
  52. std::string name(typeid(T).name());
  53. checkInit();
  54. // the first entry of the pair returned by insert will be either the existing
  55. // iterator matching our key, or the newly inserted NULL initialized entry
  56. // see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
  57. TypeMap::iterator result =
  58. sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
  59. return result->second;
  60. }
  61. };
  62. // LLSingleton implements the getInstance() method part of the Singleton
  63. // pattern. It can't make the derived class constructors protected, though, so
  64. // you have to do that yourself.
  65. //
  66. // There are two ways to use LLSingleton. The first way is to inherit from it
  67. // while using the typename that you'd like to be static as the template
  68. // parameter, like so:
  69. //
  70. //   class Foo: public LLSingleton<Foo>{};
  71. //
  72. //   Foo& instance = Foo::instance();
  73. //
  74. // The second way is to use the singleton class directly, without inheritance:
  75. //
  76. //   typedef LLSingleton<Foo> FooSingleton;
  77. //
  78. //   Foo& instance = FooSingleton::instance();
  79. //
  80. // In this case, the class being managed as a singleton needs to provide an
  81. // initSingleton() method since the LLSingleton virtual method won't be
  82. // available
  83. //
  84. // As currently written, it is not thread-safe.
  85. template <typename DERIVED_TYPE>
  86. class LLSingleton : private boost::noncopyable
  87. {
  88. private:
  89. typedef enum e_init_state
  90. {
  91. UNINITIALIZED,
  92. CONSTRUCTING,
  93. INITIALIZING,
  94. INITIALIZED,
  95. DELETED
  96. } EInitState;
  97. static void deleteSingleton()
  98. {
  99. delete getData().mSingletonInstance;
  100. getData().mSingletonInstance = NULL;
  101. }
  102. // stores pointer to singleton instance
  103. // and tracks initialization state of singleton
  104. struct SingletonInstanceData
  105. {
  106. EInitState mInitState;
  107. DERIVED_TYPE* mSingletonInstance;
  108. SingletonInstanceData()
  109. : mSingletonInstance(NULL),
  110. mInitState(UNINITIALIZED)
  111. {}
  112. ~SingletonInstanceData()
  113. {
  114. deleteSingleton();
  115. }
  116. };
  117. public:
  118. virtual ~LLSingleton()
  119. {
  120. SingletonInstanceData& data = getData();
  121. data.mSingletonInstance = NULL;
  122. data.mInitState = DELETED;
  123. }
  124. static SingletonInstanceData& getData()
  125. {
  126. // this is static to cache the lookup results
  127. static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
  128. // *TODO - look into making this threadsafe
  129. if(NULL == registry)
  130. {
  131. static SingletonInstanceData data;
  132. registry = &data;
  133. }
  134. return *static_cast<SingletonInstanceData *>(registry);
  135. }
  136. static DERIVED_TYPE* getInstance()
  137. {
  138. SingletonInstanceData& data = getData();
  139. if (data.mInitState == CONSTRUCTING)
  140. {
  141. llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
  142. }
  143. if (data.mInitState == DELETED)
  144. {
  145. llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
  146. }
  147. if (!data.mSingletonInstance) 
  148. {
  149. data.mInitState = CONSTRUCTING;
  150. data.mSingletonInstance = new DERIVED_TYPE(); 
  151. data.mInitState = INITIALIZING;
  152. data.mSingletonInstance->initSingleton(); 
  153. data.mInitState = INITIALIZED;
  154. }
  155. return data.mSingletonInstance;
  156. }
  157. // Reference version of getInstance()
  158. // Preferred over getInstance() as it disallows checking for NULL
  159. static DERIVED_TYPE& instance()
  160. {
  161. return *getInstance();
  162. }
  163. // Has this singleton been created uet?
  164. // Use this to avoid accessing singletons before the can safely be constructed
  165. static bool instanceExists()
  166. {
  167. return getData().mInitState == INITIALIZED;
  168. }
  169. // Has this singleton already been deleted?
  170. // Use this to avoid accessing singletons from a static object's destructor
  171. static bool destroyed()
  172. {
  173. return getData().mInitState == DELETED;
  174. }
  175. private:
  176. virtual void initSingleton() {}
  177. };
  178. #endif