Only do one map lookup instead of two in QuicheLinkedHashMap::insert(). Instead of find() then insert(), use try_emplace(). This change is inspired by cl/163240273. Also factor out two insert() calls into InsertInternal(). PiperOrigin-RevId: 372947805
diff --git a/common/quiche_linked_hash_map.h b/common/quiche_linked_hash_map.h index 311e369..a52863e 100644 --- a/common/quiche_linked_hash_map.h +++ b/common/quiche_linked_hash_map.h
@@ -127,7 +127,8 @@ iterator erase(iterator position) { typename MapType::iterator found = map_.find(position->first); QUICHE_CHECK(found->second == position) - << "Inconsisent iterator for map and list, or the iterator is invalid."; + << "Inconsistent iterator for map and list, or the iterator is " + "invalid."; map_.erase(found); return list_.erase(position); @@ -172,49 +173,12 @@ // Inserts an element into the map std::pair<iterator, bool> insert(const std::pair<Key, Value>& pair) { - // First make sure the map doesn't have a key with this value. If it does, - // return a pair with an iterator to it, and false indicating that we - // didn't insert anything. - typename MapType::iterator found = map_.find(pair.first); - if (found != map_.end()) { - return std::make_pair(found->second, false); - } - - // Otherwise, insert into the list first. - list_.push_back(pair); - - // Obtain an iterator to the newly added element. We do -- instead of - - // since list::iterator doesn't implement operator-(). - typename ListType::iterator last = list_.end(); - --last; - - QUICHE_CHECK(map_.insert(std::make_pair(pair.first, last)).second) - << "Map and list are inconsistent"; - - return std::make_pair(last, true); + return InsertInternal(pair); } // Inserts an element into the map std::pair<iterator, bool> insert(std::pair<Key, Value>&& pair) { - // First make sure the map doesn't have a key with this value. If it does, - // return a pair with an iterator to it, and false indicating that we - // didn't insert anything. - typename MapType::iterator found = map_.find(pair.first); - if (found != map_.end()) { - return std::make_pair(found->second, false); - } - - // Otherwise, insert into the list first. - list_.push_back(std::move(pair)); - - // Obtain an iterator to the newly added element. We do -- instead of - - // since list::iterator doesn't implement operator-(). - typename ListType::iterator last = list_.end(); - --last; - - QUICHE_CHECK(map_.insert(std::make_pair(last->first, last)).second) - << "Map and list are inconsistent"; - return std::make_pair(last, true); + return InsertInternal(std::move(pair)); } // Derive size_ from map_, as list::size might be O(N). @@ -240,6 +204,24 @@ } private: + template <typename U> + std::pair<iterator, bool> InsertInternal(U&& pair) { + auto insert_result = map_.try_emplace(pair.first); + auto map_iter = insert_result.first; + + // If the map already contains this key, return a pair with an iterator to + // it, and false indicating that we didn't insert anything. + if (!insert_result.second) { + return {map_iter->second, false}; + } + + // Otherwise, insert into the list, and set value in map. + auto list_iter = list_.insert(list_.end(), std::forward<U>(pair)); + map_iter->second = list_iter; + + return {list_iter, true}; + } + // The map component, used for speedy lookups MapType map_;