summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2012-07-18 16:31:22 -0400
committerNat Goodspeed <nat@lindenlab.com>2012-07-18 16:31:22 -0400
commit5e1e44ca7ea6fdbfb34a3a3968d5f07fc0ff3d7a (patch)
tree3b8d3431d65bb32dfc7454526a1e66f2e5a5d451 /indra/llcommon
parent7f609b6a6958f519bb1becb604132b583ada3fad (diff)
parent55a7bdf8d3f59b0d1973d1ec22d3c8770a077723 (diff)
MAINT-1175: merge backout LLRegistrySingleton<std::type_info::name()>
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llinitparam.h32
-rw-r--r--indra/llcommon/llregistry.h18
-rw-r--r--indra/llcommon/lltypeinfolookup.h132
3 files changed, 95 insertions, 87 deletions
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 99983a19cb..66c72c2d9f 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -212,14 +212,6 @@ namespace LLInitParam
public:
- struct CompareTypeID
- {
- bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
- {
- return lhs->before(*rhs);
- }
- };
-
typedef std::vector<std::pair<std::string, bool> > name_stack_t;
typedef std::pair<name_stack_t::iterator, name_stack_t::iterator> name_stack_range_t;
typedef std::vector<std::string> possible_values_t;
@@ -242,20 +234,20 @@ namespace LLInitParam
template <typename T> bool readValue(T& param)
{
- parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
- if (found_it != mParserReadFuncs->end())
+ boost::optional<parser_read_func_t> found_it = mParserReadFuncs->find<T>();
+ if (found_it)
{
- return found_it->second(*this, (void*)&param);
+ return (*found_it)(*this, (void*)&param);
}
return false;
}
template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
{
- parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
- if (found_it != mParserWriteFuncs->end())
+ boost::optional<parser_write_func_t> found_it = mParserWriteFuncs->find<T>();
+ if (found_it)
{
- return found_it->second(*this, (const void*)&param, name_stack);
+ return (*found_it)(*this, (const void*)&param, name_stack);
}
return false;
}
@@ -263,10 +255,10 @@ namespace LLInitParam
// dispatch inspection to registered inspection functions, for each parameter in a param block
template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
{
- parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
- if (found_it != mParserInspectFuncs->end())
+ boost::optional<parser_inspect_func_t> found_it = mParserInspectFuncs->find<T>();
+ if (found_it)
{
- found_it->second(name_stack, min_count, max_count, possible_values);
+ (*found_it)(name_stack, min_count, max_count, possible_values);
return true;
}
return false;
@@ -281,14 +273,14 @@ namespace LLInitParam
template <typename T>
void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
{
- mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
- mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
+ mParserReadFuncs->insert<T>(read_func);
+ mParserWriteFuncs->insert<T>(write_func);
}
template <typename T>
void registerInspectFunc(parser_inspect_func_t inspect_func)
{
- mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
+ mParserInspectFuncs->insert<T>(inspect_func);
}
bool mParseSilently;
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index 36d7f7a44c..2df9bc6541 100644
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -34,9 +34,21 @@
#include "lltypeinfolookup.h"
template <typename T>
-class LLRegistryDefaultComparator
+struct LLRegistryDefaultComparator
{
- bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; }
+ // It would be Bad if this comparison were used for const char*
+ BOOST_STATIC_ASSERT(! (boost::is_same<typename boost::remove_const<typename boost::remove_pointer<T>::type>::type, char>::value));
+ bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; }
+};
+
+// comparator for const char* registry keys
+template <>
+struct LLRegistryDefaultComparator<const char*>
+{
+ bool operator()(const char* lhs, const char* rhs) const
+ {
+ return strcmp(lhs, rhs) < 0;
+ }
};
template <typename KEY, typename VALUE>
@@ -72,7 +84,7 @@ public:
{
friend class LLRegistry<KEY, VALUE, COMPARATOR>;
public:
- typedef typename LLRegistryMapSelector<KEY, VALUE>::type registry_map_t;
+ typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
bool add(ref_const_key_t key, ref_const_value_t value)
{
diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h
index 679cc51f1d..0b6862444e 100644
--- a/indra/llcommon/lltypeinfolookup.h
+++ b/indra/llcommon/lltypeinfolookup.h
@@ -13,11 +13,47 @@
#define LL_LLTYPEINFOLOOKUP_H
#include <boost/unordered_map.hpp>
-#include <boost/function.hpp>
-#include <boost/mem_fn.hpp>
-#include <boost/iterator/transform_iterator.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/optional.hpp>
+#include <functional> // std::binary_function
#include <typeinfo>
-#include <map>
+
+/**
+ * The following helper classes are based on the Boost.Unordered documentation:
+ * http://www.boost.org/doc/libs/1_45_0/doc/html/unordered/hash_equality.html
+ */
+
+/**
+ * Compute hash for a string passed as const char*
+ */
+struct const_char_star_hash: public std::unary_function<const char*, std::size_t>
+{
+ std::size_t operator()(const char* str) const
+ {
+ std::size_t seed = 0;
+ for ( ; *str; ++str)
+ {
+ boost::hash_combine(seed, *str);
+ }
+ return seed;
+ }
+};
+
+/**
+ * Compute equality for strings passed as const char*
+ *
+ * I (nat) suspect that this is where the default behavior breaks for the
+ * const char* values returned from std::type_info::name(). If you compare the
+ * two const char* pointer values, as a naive, unspecialized implementation
+ * will surely do, they'll compare unequal.
+ */
+struct const_char_star_equal: public std::binary_function<const char*, const char*, bool>
+{
+ bool operator()(const char* lhs, const char* rhs) const
+ {
+ return strcmp(lhs, rhs) == 0;
+ }
+};
/**
* LLTypeInfoLookup is specifically designed for use cases for which you might
@@ -26,87 +62,55 @@
* you can't rely on always getting the same std::type_info* for a given type:
* different load modules will produce different std::type_info*.
* LLTypeInfoLookup contains a workaround to address this issue.
+ *
+ * The API deliberately diverges from std::map in several respects:
+ * * It avoids iterators, not only begin()/end() but also as return values
+ * from insert() and find(). This bypasses transform_iterator overhead.
+ * * Since we literally use compile-time types as keys, the essential insert()
+ * and find() methods accept the key type as a @em template parameter,
+ * accepting and returning value_type as a normal runtime value. This is to
+ * permit future optimization (e.g. compile-time type hashing) without
+ * changing the API.
*/
template <typename VALUE>
class LLTypeInfoLookup
{
- // We present an interface like this:
- typedef std::map<const std::type_info*, VALUE> intf_map_type;
// Use this for our underlying implementation: lookup by
- // std::type_info::name() string. Note that we must store a std::pair<const
- // std::type_info*, VALUE> -- in other words, an intf_map_type::value_type
- // pair -- so we can present iterators that do the right thing.
- // (This might result in a lookup with one std::type_info* returning an
- // iterator to a different std::type_info*, but frankly, my dear, we don't
- // give a damn.)
- typedef boost::unordered_map<std::string, typename intf_map_type::value_type> impl_map_type;
- // Iterator shorthand
- typedef typename intf_map_type::iterator intf_iterator;
- typedef typename intf_map_type::const_iterator intf_const_iterator;
- typedef typename intf_map_type::value_type intf_value_type;
- typedef typename impl_map_type::iterator impl_iterator;
- typedef typename impl_map_type::const_iterator impl_const_iterator;
- typedef typename impl_map_type::value_type impl_value_type;
- // Type of function that transforms impl_value_type to intf_value_type
- typedef boost::function<intf_value_type&(impl_value_type&)> iterfunc;
- typedef boost::function<const intf_value_type&(const impl_value_type&)> const_iterfunc;
+ // std::type_info::name() string. This is one of the rare cases in which I
+ // dare use const char* directly, rather than std::string, because I'm
+ // sure that every value returned by std::type_info::name() is static.
+ // HOWEVER, specify our own hash + equality functors: naively comparing
+ // distinct const char* values won't work.
+ typedef boost::unordered_map<const char*, VALUE,
+ const_char_star_hash, const_char_star_equal> impl_map_type;
public:
- typedef LLTypeInfoLookup<VALUE> self;
- typedef typename intf_map_type::key_type key_type;
- typedef typename intf_map_type::mapped_type mapped_type;
- typedef intf_value_type value_type;
-
- // Iterators are different because we have to transform
- // impl_map_type::iterator to intf_map_type::iterator.
- typedef boost::transform_iterator<iterfunc, impl_iterator> iterator;
- typedef boost::transform_iterator<const_iterfunc, impl_const_iterator> const_iterator;
+ typedef VALUE value_type;
LLTypeInfoLookup() {}
- iterator begin() { return transform(mMap.begin()); }
- iterator end() { return transform(mMap.end()); }
- const_iterator begin() const { return const_transform(mMap.begin()); }
- const_iterator end() const { return const_transform(mMap.end()); }
bool empty() const { return mMap.empty(); }
std::size_t size() const { return mMap.size(); }
- // Shorthand -- I've always wished std::map supported this signature.
- std::pair<iterator, bool> insert(const std::type_info* key, const VALUE& value)
- {
- return insert(value_type(key, value));
- }
-
- std::pair<iterator, bool> insert(const value_type& pair)
+ template <typename KEY>
+ bool insert(const value_type& value)
{
// Obtain and store the std::type_info::name() string as the key.
- // Save the whole incoming pair as the value!
- std::pair<impl_iterator, bool>
- inserted(mMap.insert(impl_value_type(pair.first->name(), pair)));
- // Have to transform the iterator before returning.
- return std::pair<iterator, bool>(transform(inserted.first), inserted.second);
- }
-
- iterator find(const std::type_info* key)
- {
- return transform(mMap.find(key->name()));
+ // Return just the bool from std::map::insert()'s return pair.
+ return mMap.insert(typename impl_map_type::value_type(typeid(KEY).name(), value)).second;
}
- const_iterator find(const std::type_info* key) const
+ template <typename KEY>
+ boost::optional<value_type> find() const
{
- return const_transform(mMap.find(key->name()));
+ // Use the std::type_info::name() string as the key.
+ typename impl_map_type::const_iterator found = mMap.find(typeid(KEY).name());
+ if (found == mMap.end())
+ return boost::optional<value_type>();
+ return found->second;
}
private:
- iterator transform(impl_iterator iter)
- {
- return iterator(iter, boost::mem_fn(&impl_value_type::second));
- }
- const_iterator const_transform(impl_const_iterator iter)
- {
- return const_iterator(iter, boost::mem_fn(&impl_value_type::second));
- }
-
impl_map_type mMap;
};