diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2012-07-18 16:31:22 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2012-07-18 16:31:22 -0400 | 
| commit | 5e1e44ca7ea6fdbfb34a3a3968d5f07fc0ff3d7a (patch) | |
| tree | 3b8d3431d65bb32dfc7454526a1e66f2e5a5d451 /indra/llcommon | |
| parent | 7f609b6a6958f519bb1becb604132b583ada3fad (diff) | |
| parent | 55a7bdf8d3f59b0d1973d1ec22d3c8770a077723 (diff) | |
MAINT-1175: merge backout LLRegistrySingleton<std::type_info::name()>
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/llinitparam.h | 32 | ||||
| -rw-r--r-- | indra/llcommon/llregistry.h | 18 | ||||
| -rw-r--r-- | indra/llcommon/lltypeinfolookup.h | 132 | 
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*)¶m); +			    return (*found_it)(*this, (void*)¶m);  		    }  		    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*)¶m, name_stack); +			    return (*found_it)(*this, (const void*)¶m, 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;  }; | 
