PageRenderTime 18ms CodeModel.GetById 1ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 1ms

/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
  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
 27#ifndef LL_LLREGISTRY_H
 28#define LL_LLREGISTRY_H
 29
 30#include <list>
 31
 32#include <boost/type_traits.hpp>
 33#include "llsingleton.h"
 34
 35template <typename T>
 36class LLRegistryDefaultComparator
 37{
 38	bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; }
 39};
 40
 41template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
 42class LLRegistry
 43{
 44public:
 45	typedef LLRegistry<KEY, VALUE, COMPARATOR>											registry_t;
 46	typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type	ref_const_key_t;
 47	typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type	ref_const_value_t;
 48	typedef typename boost::add_reference<VALUE>::type									ref_value_t;
 49	typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type	ptr_const_value_t;
 50	typedef typename boost::add_pointer<VALUE>::type									ptr_value_t;
 51
 52	class Registrar
 53	{
 54		friend class LLRegistry<KEY, VALUE, COMPARATOR>;
 55	public:
 56		typedef typename std::map<KEY, VALUE> registry_map_t;
 57
 58		bool add(ref_const_key_t key, ref_const_value_t value)
 59		{
 60			if (mMap.insert(std::make_pair(key, value)).second == false)
 61			{
 62				llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
 63				return false;
 64			}
 65			return true;
 66		}
 67
 68		void remove(ref_const_key_t key)
 69		{
 70			mMap.erase(key);
 71		}
 72
 73		void replace(ref_const_key_t key, ref_const_value_t value)
 74		{
 75			mMap[key] = value;
 76		}
 77
 78		typename registry_map_t::const_iterator beginItems() const
 79		{
 80			return mMap.begin();
 81		}
 82
 83		typename registry_map_t::const_iterator endItems() const
 84		{
 85			return mMap.end();
 86		}
 87
 88	protected:
 89		ptr_value_t getValue(ref_const_key_t key)
 90		{
 91			typename registry_map_t::iterator found_it = mMap.find(key);
 92			if (found_it != mMap.end())
 93			{
 94				return &(found_it->second);
 95			}
 96			return NULL;
 97		}
 98
 99		ptr_const_value_t getValue(ref_const_key_t key) const
100		{
101			typename registry_map_t::const_iterator found_it = mMap.find(key);
102			if (found_it != mMap.end())
103			{
104				return &(found_it->second);
105			}
106			return NULL;
107		}
108
109		// if the registry is used to store pointers, and null values are valid entries
110		// then use this function to check the existence of an entry
111		bool exists(ref_const_key_t key) const
112		{
113			return mMap.find(key) != mMap.end();
114		}
115
116		bool empty() const
117		{
118			return mMap.empty();
119		}
120
121	protected:
122		// use currentRegistrar() or defaultRegistrar()
123		Registrar() {}
124		~Registrar() {}
125
126	private:
127		registry_map_t											mMap;
128	};
129	
130	typedef typename std::list<Registrar*> scope_list_t;
131	typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
132	typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
133	
134	LLRegistry() 
135	{}
136
137	~LLRegistry() {}
138
139	ptr_value_t getValue(ref_const_key_t key)
140	{
141		for(scope_list_iterator_t it = mActiveScopes.begin();
142			it != mActiveScopes.end();
143			++it)
144		{
145			ptr_value_t valuep = (*it)->getValue(key);
146			if (valuep != NULL) return valuep;
147		}
148		return mDefaultRegistrar.getValue(key);
149	}
150
151	ptr_const_value_t getValue(ref_const_key_t key) const
152	{
153		for(scope_list_const_iterator_t it = mActiveScopes.begin();
154			it != mActiveScopes.end();
155			++it)
156		{
157			ptr_value_t valuep = (*it)->getValue(key);
158			if (valuep != NULL) return valuep;
159		}
160		return mDefaultRegistrar.getValue(key);
161	}
162
163	bool exists(ref_const_key_t key) const
164	{
165		for(scope_list_const_iterator_t it = mActiveScopes.begin();
166			it != mActiveScopes.end();
167			++it)
168		{
169			if ((*it)->exists(key)) return true;
170		}
171
172		return mDefaultRegistrar.exists(key);
173	}
174
175	bool empty() const
176	{
177		for(scope_list_const_iterator_t it = mActiveScopes.begin();
178			it != mActiveScopes.end();
179			++it)
180		{
181			if (!(*it)->empty()) return false;
182		}
183
184		return mDefaultRegistrar.empty();
185	}
186
187
188	Registrar& defaultRegistrar()
189	{
190		return mDefaultRegistrar;
191	}
192
193	const Registrar& defaultRegistrar() const
194	{
195		return mDefaultRegistrar;
196	}
197
198
199	Registrar& currentRegistrar()
200	{
201		if (!mActiveScopes.empty()) 
202		{
203			return *mActiveScopes.front();
204		}
205
206		return mDefaultRegistrar;
207	}
208
209	const Registrar& currentRegistrar() const
210	{
211		if (!mActiveScopes.empty()) 
212		{
213			return *mActiveScopes.front();
214		}
215
216		return mDefaultRegistrar;
217	}
218
219
220protected:
221	void addScope(Registrar* scope)
222	{
223		// newer scopes go up front
224		mActiveScopes.insert(mActiveScopes.begin(), scope);
225	}
226
227	void removeScope(Registrar* scope)
228	{
229		// O(N) but should be near the beggining and N should be small and this is safer than storing iterators
230		scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
231		if (iter != mActiveScopes.end())
232		{
233			mActiveScopes.erase(iter);
234		}
235	}
236
237private:
238	scope_list_t	mActiveScopes;
239	Registrar		mDefaultRegistrar;
240};
241
242template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
243class LLRegistrySingleton
244	:	public LLRegistry<KEY, VALUE, COMPARATOR>,
245		public LLSingleton<DERIVED_TYPE>
246{
247	friend class LLSingleton<DERIVED_TYPE>;
248public:
249	typedef LLRegistry<KEY, VALUE, COMPARATOR>		registry_t;
250	typedef const KEY&								ref_const_key_t;
251	typedef const VALUE&							ref_const_value_t;
252	typedef VALUE*									ptr_value_t;
253	typedef const VALUE*							ptr_const_value_t;
254	typedef LLSingleton<DERIVED_TYPE>				singleton_t;
255
256	class ScopedRegistrar : public registry_t::Registrar
257	{
258	public:
259		ScopedRegistrar(bool push_scope = true) 
260		{
261			if (push_scope)
262			{
263				pushScope();
264			}
265		}
266
267		~ScopedRegistrar()
268		{
269			if (!singleton_t::destroyed())
270			{
271				popScope();
272			}
273		}
274
275		void pushScope()
276		{
277			singleton_t::instance().addScope(this);
278		}
279		
280		void popScope()
281		{
282			singleton_t::instance().removeScope(this);
283		}
284		
285		ptr_value_t getValueFromScope(ref_const_key_t key)
286		{
287			return getValue(key);
288		}
289
290		ptr_const_value_t getValueFromScope(ref_const_key_t key) const
291		{
292			return getValue(key);
293		}
294
295	private:
296		typename std::list<typename registry_t::Registrar*>::iterator	mListIt;
297	};
298
299	class StaticRegistrar : public registry_t::Registrar
300	{
301	public:
302		virtual ~StaticRegistrar() {}
303		StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
304		{
305			singleton_t::instance().mStaticScope->add(key, value);
306		}
307	};
308
309	// convenience functions
310	typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
311	static ref_registrar_t currentRegistrar()
312	{
313		return singleton_t::instance().registry_t::currentRegistrar();
314	}
315
316	static ref_registrar_t defaultRegistrar()
317	{
318		return singleton_t::instance().registry_t::defaultRegistrar();
319	}
320	
321	static ptr_value_t getValue(ref_const_key_t key)
322	{
323		return singleton_t::instance().registry_t::getValue(key);
324	}
325
326protected:
327	// DERIVED_TYPE needs to derive from LLRegistrySingleton
328	LLRegistrySingleton()
329		: mStaticScope(NULL)
330	{}
331
332	virtual void initSingleton()
333	{
334		mStaticScope = new ScopedRegistrar();
335	}
336
337	virtual ~LLRegistrySingleton() 
338	{
339		delete mStaticScope;
340	}
341
342private:
343	ScopedRegistrar*	mStaticScope;
344};
345
346// helper macro for doing static registration
347#define GLUED_TOKEN(x, y) x ## y
348#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
349#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE);
350
351#endif