diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2012-07-11 08:20:14 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2012-07-11 08:20:14 -0400 |
commit | 578d70dec0a01b5ed7b461c38503c082ac1a3608 (patch) | |
tree | cc044993b989c727597d57e42af14f13e6783b2f /indra | |
parent | 18bd525d00ee3ce16164900293ee6ea8c2204589 (diff) |
MAINT-1175: Change LLTypeInfoLookup API for future optimizations.
Per discussion with Richard, accept the type key for insert() and find() as a
template parameter rather than as std::type_info*. This permits (e.g.) some
sort of compile-time prehashing for common types, without changing the API.
Eliminate iterators from the API altogether, thus avoiding costs associated
with transform_iterator.
Fix existing references in llinitparam.h.
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llcommon/llinitparam.h | 24 | ||||
-rw-r--r-- | indra/llcommon/lltypeinfolookup.h | 90 |
2 files changed, 38 insertions, 76 deletions
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 99983a19cb..c0170e533b 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -242,20 +242,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 +263,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 +281,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/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h index 679cc51f1d..5267e3d2fb 100644 --- a/indra/llcommon/lltypeinfolookup.h +++ b/indra/llcommon/lltypeinfolookup.h @@ -13,11 +13,8 @@ #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/optional.hpp> #include <typeinfo> -#include <map> /** * LLTypeInfoLookup is specifically designed for use cases for which you might @@ -26,87 +23,52 @@ * 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. + typedef boost::unordered_map<const char*, VALUE> 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; }; |