From: Roland McGrath Date: Tue, 1 Sep 2009 02:21:08 +0000 (-0700) Subject: Add specialized dynamic_equality_set class for attributes in the collector. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ffd982f4b0f05522e868f1bd34466f3c521105d6;p=thirdparty%2Felfutils.git Add specialized dynamic_equality_set class for attributes in the collector. --- diff --git a/libdw/ChangeLog b/libdw/ChangeLog index ba4241634..1b2ac1917 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,8 @@ +2009-08-31 Roland McGrath + + * c++/subr.hh (subr::dynamic_equality_set): New template class. + * c++/dwarf_output (dwarf_output_collector): Use it for _m_attr_sets. + 2009-08-27 Roland McGrath * c++/dwarf_output (dwarf_output::dwarf_output): Add a variant with a diff --git a/libdw/c++/dwarf_output b/libdw/c++/dwarf_output index 747e8f8bc..027fd7f16 100644 --- a/libdw/c++/dwarf_output +++ b/libdw/c++/dwarf_output @@ -890,11 +890,11 @@ namespace elfutils } // Set of attribute maps. - subr::identity_set _m_attr_sets; + subr::dynamic_equality_set _m_attr_sets; inline const attrs_type *add_attributes (const attrs_type &candidate) { - return &*_m_attr_sets.insert (candidate).first; + return _m_attr_sets.add (candidate); // XXX pass custom predicate } // Set of children lists. diff --git a/libdw/c++/subr.hh b/libdw/c++/subr.hh index 5d4df089e..903ed7e15 100644 --- a/libdw/c++/subr.hh +++ b/libdw/c++/subr.hh @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,7 @@ namespace elfutils { size_t operator () (const T &v) const { - return subr::hash_this (v); + return hash_this (v); } }; @@ -91,7 +92,7 @@ namespace elfutils inline size_t operator () (const std::pair &x) const { size_t h = 0; - subr::hash_combine (h, x); + hash_combine (h, x); return h; } }; @@ -105,7 +106,7 @@ namespace elfutils inline hasher (size_t init = 0) : _m_hash (init) {} inline void operator () (const typename T::value_type &x) { - subr::hash_combine (_m_hash, hash_this (x)); + hash_combine (_m_hash, hash_this (x)); } }; @@ -496,7 +497,7 @@ namespace elfutils hashit (size_t &h) : _m_hash (h) {} inline void operator () (const elt_type &p) { - subr::hash_combine (_m_hash, p); + hash_combine (_m_hash, p); } }; std::for_each (_base::begin (), _base::end (), hashit (_m_hash)); @@ -567,8 +568,8 @@ namespace elfutils inline void operator () (const typename _base::value_type &p) { - subr::hash_combine (_m_hash, hash_this (p.first)); - subr::hash_combine (_m_hash, p.second.first); + hash_combine (_m_hash, hash_this (p.first)); + hash_combine (_m_hash, p.second.first); } }; std::for_each (_base::begin (), _base::end (), hashit (_m_hash)); @@ -795,7 +796,7 @@ namespace elfutils : _m_maker (c) {} - typedef subr::wrapped_input_iterator const_iterator; + typedef wrapped_input_iterator const_iterator; inline const_iterator operator () (const inny &i) { @@ -957,6 +958,53 @@ namespace elfutils is > {}; + /* This is like an unordered_set, but the equality predicate cannot + be fixed statically. Instead, each insertion call must pass in + the specific predicate to match against existing elements for + that insertion. */ + template > + class dynamic_equality_set + { + private: + typedef size_t hash_type; + typedef std::deque bucket_type; + typedef std::tr1::unordered_map map_type; + + map_type _m_map; + hasher_type _m_hasher; + + public: + typedef T value_type; + + template + inline const value_type * + add (const value_type &candidate, match_type &match) + { + bucket_type &bucket = _m_map[_m_hasher (candidate)]; + + for (typename bucket_type::iterator i = bucket.begin (); + i != bucket.end (); + ++i) + { + const value_type &elt = *i; + if (match (elt, candidate)) + // We have a winner! + return &elt; + } + + // No matches: new element. + bucket.push_back (candidate); + return &(bucket.back ()); + } + + // Unclear why you didn't just use a normal identity_set then! + inline const value_type *add (const value_type &candidate) + { + is equalator; + return add (candidate, equalator); + } + }; + /* This is a dummy you can template/syntactically use in place of std::cout et al for disabled debugging spew. */ struct nostream