PageRenderTime 29ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llxuixml/llregistry.h

https://bitbucket.org/lindenlab/viewer-beta/
C Header | 351 lines | 262 code | 56 blank | 33 comment | 27 complexity | 3a249c905a007b02cbaa70fe88d91438 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llregistry.h
  3. * @brief template classes for registering name, value pairs in nested scopes, statically, etc.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LL_LLREGISTRY_H
  27. #define LL_LLREGISTRY_H
  28. #include <list>
  29. #include <boost/type_traits.hpp>
  30. #include "llsingleton.h"
  31. template <typename T>
  32. class LLRegistryDefaultComparator
  33. {
  34. bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; }
  35. };
  36. template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
  37. class LLRegistry
  38. {
  39. public:
  40. typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
  41. typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type ref_const_key_t;
  42. typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type ref_const_value_t;
  43. typedef typename boost::add_reference<VALUE>::type ref_value_t;
  44. typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type ptr_const_value_t;
  45. typedef typename boost::add_pointer<VALUE>::type ptr_value_t;
  46. class Registrar
  47. {
  48. friend class LLRegistry<KEY, VALUE, COMPARATOR>;
  49. public:
  50. typedef typename std::map<KEY, VALUE> registry_map_t;
  51. bool add(ref_const_key_t key, ref_const_value_t value)
  52. {
  53. if (mMap.insert(std::make_pair(key, value)).second == false)
  54. {
  55. llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
  56. return false;
  57. }
  58. return true;
  59. }
  60. void remove(ref_const_key_t key)
  61. {
  62. mMap.erase(key);
  63. }
  64. void replace(ref_const_key_t key, ref_const_value_t value)
  65. {
  66. mMap[key] = value;
  67. }
  68. typename registry_map_t::const_iterator beginItems() const
  69. {
  70. return mMap.begin();
  71. }
  72. typename registry_map_t::const_iterator endItems() const
  73. {
  74. return mMap.end();
  75. }
  76. protected:
  77. ptr_value_t getValue(ref_const_key_t key)
  78. {
  79. typename registry_map_t::iterator found_it = mMap.find(key);
  80. if (found_it != mMap.end())
  81. {
  82. return &(found_it->second);
  83. }
  84. return NULL;
  85. }
  86. ptr_const_value_t getValue(ref_const_key_t key) const
  87. {
  88. typename registry_map_t::const_iterator found_it = mMap.find(key);
  89. if (found_it != mMap.end())
  90. {
  91. return &(found_it->second);
  92. }
  93. return NULL;
  94. }
  95. // if the registry is used to store pointers, and null values are valid entries
  96. // then use this function to check the existence of an entry
  97. bool exists(ref_const_key_t key) const
  98. {
  99. return mMap.find(key) != mMap.end();
  100. }
  101. bool empty() const
  102. {
  103. return mMap.empty();
  104. }
  105. protected:
  106. // use currentRegistrar() or defaultRegistrar()
  107. Registrar() {}
  108. ~Registrar() {}
  109. private:
  110. registry_map_t mMap;
  111. };
  112. typedef typename std::list<Registrar*> scope_list_t;
  113. typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
  114. typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
  115. LLRegistry()
  116. {}
  117. ~LLRegistry() {}
  118. ptr_value_t getValue(ref_const_key_t key)
  119. {
  120. for(scope_list_iterator_t it = mActiveScopes.begin();
  121. it != mActiveScopes.end();
  122. ++it)
  123. {
  124. ptr_value_t valuep = (*it)->getValue(key);
  125. if (valuep != NULL) return valuep;
  126. }
  127. return mDefaultRegistrar.getValue(key);
  128. }
  129. ptr_const_value_t getValue(ref_const_key_t key) const
  130. {
  131. for(scope_list_const_iterator_t it = mActiveScopes.begin();
  132. it != mActiveScopes.end();
  133. ++it)
  134. {
  135. ptr_value_t valuep = (*it)->getValue(key);
  136. if (valuep != NULL) return valuep;
  137. }
  138. return mDefaultRegistrar.getValue(key);
  139. }
  140. bool exists(ref_const_key_t key) const
  141. {
  142. for(scope_list_const_iterator_t it = mActiveScopes.begin();
  143. it != mActiveScopes.end();
  144. ++it)
  145. {
  146. if ((*it)->exists(key)) return true;
  147. }
  148. return mDefaultRegistrar.exists(key);
  149. }
  150. bool empty() const
  151. {
  152. for(scope_list_const_iterator_t it = mActiveScopes.begin();
  153. it != mActiveScopes.end();
  154. ++it)
  155. {
  156. if (!(*it)->empty()) return false;
  157. }
  158. return mDefaultRegistrar.empty();
  159. }
  160. Registrar& defaultRegistrar()
  161. {
  162. return mDefaultRegistrar;
  163. }
  164. const Registrar& defaultRegistrar() const
  165. {
  166. return mDefaultRegistrar;
  167. }
  168. Registrar& currentRegistrar()
  169. {
  170. if (!mActiveScopes.empty())
  171. {
  172. return *mActiveScopes.front();
  173. }
  174. return mDefaultRegistrar;
  175. }
  176. const Registrar& currentRegistrar() const
  177. {
  178. if (!mActiveScopes.empty())
  179. {
  180. return *mActiveScopes.front();
  181. }
  182. return mDefaultRegistrar;
  183. }
  184. protected:
  185. void addScope(Registrar* scope)
  186. {
  187. // newer scopes go up front
  188. mActiveScopes.insert(mActiveScopes.begin(), scope);
  189. }
  190. void removeScope(Registrar* scope)
  191. {
  192. // O(N) but should be near the beggining and N should be small and this is safer than storing iterators
  193. scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
  194. if (iter != mActiveScopes.end())
  195. {
  196. mActiveScopes.erase(iter);
  197. }
  198. }
  199. private:
  200. scope_list_t mActiveScopes;
  201. Registrar mDefaultRegistrar;
  202. };
  203. template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
  204. class LLRegistrySingleton
  205. : public LLRegistry<KEY, VALUE, COMPARATOR>,
  206. public LLSingleton<DERIVED_TYPE>
  207. {
  208. friend class LLSingleton<DERIVED_TYPE>;
  209. public:
  210. typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
  211. typedef const KEY& ref_const_key_t;
  212. typedef const VALUE& ref_const_value_t;
  213. typedef VALUE* ptr_value_t;
  214. typedef const VALUE* ptr_const_value_t;
  215. typedef LLSingleton<DERIVED_TYPE> singleton_t;
  216. class ScopedRegistrar : public registry_t::Registrar
  217. {
  218. public:
  219. ScopedRegistrar(bool push_scope = true)
  220. {
  221. if (push_scope)
  222. {
  223. pushScope();
  224. }
  225. }
  226. ~ScopedRegistrar()
  227. {
  228. if (!singleton_t::destroyed())
  229. {
  230. popScope();
  231. }
  232. }
  233. void pushScope()
  234. {
  235. singleton_t::instance().addScope(this);
  236. }
  237. void popScope()
  238. {
  239. singleton_t::instance().removeScope(this);
  240. }
  241. ptr_value_t getValueFromScope(ref_const_key_t key)
  242. {
  243. return getValue(key);
  244. }
  245. ptr_const_value_t getValueFromScope(ref_const_key_t key) const
  246. {
  247. return getValue(key);
  248. }
  249. private:
  250. typename std::list<typename registry_t::Registrar*>::iterator mListIt;
  251. };
  252. class StaticRegistrar : public registry_t::Registrar
  253. {
  254. public:
  255. virtual ~StaticRegistrar() {}
  256. StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
  257. {
  258. singleton_t::instance().mStaticScope->add(key, value);
  259. }
  260. };
  261. // convenience functions
  262. typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
  263. static ref_registrar_t currentRegistrar()
  264. {
  265. return singleton_t::instance().registry_t::currentRegistrar();
  266. }
  267. static ref_registrar_t defaultRegistrar()
  268. {
  269. return singleton_t::instance().registry_t::defaultRegistrar();
  270. }
  271. static ptr_value_t getValue(ref_const_key_t key)
  272. {
  273. return singleton_t::instance().registry_t::getValue(key);
  274. }
  275. protected:
  276. // DERIVED_TYPE needs to derive from LLRegistrySingleton
  277. LLRegistrySingleton()
  278. : mStaticScope(NULL)
  279. {}
  280. virtual void initSingleton()
  281. {
  282. mStaticScope = new ScopedRegistrar();
  283. }
  284. virtual ~LLRegistrySingleton()
  285. {
  286. delete mStaticScope;
  287. }
  288. private:
  289. ScopedRegistrar* mStaticScope;
  290. };
  291. // helper macro for doing static registration
  292. #define GLUED_TOKEN(x, y) x ## y
  293. #define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
  294. #define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE);
  295. #endif