jankratochvil updated this revision to Diff 218265. jankratochvil retitled this revision from "Prevent D66398 `TestDataFormatterStdList`-like regressions in the future" to "2/2: Process formatters in reverse-chronological order". jankratochvil edited the summary of this revision. jankratochvil added a reverted change: D66398: 2/2: Fix `TestDataFormatterStdList` regression. jankratochvil added a comment. Herald added a subscriber: abidh.
In D66654#1646544 <https://reviews.llvm.org/D66654#1646544>, @labath wrote: > Personally, I'd go for the registration order, Then you cannot override any existing formatter. Then it would be better to rather assert/error in such case which I tried to do in this patch but nobody likes this patch much. > or possibly the reverse registration order, That is what this new patch implements. Repository: rLLDB LLDB CHANGES SINCE LAST ACTION https://reviews.llvm.org/D66654/new/ https://reviews.llvm.org/D66654 Files: lldb/include/lldb/DataFormatters/FormattersContainer.h
Index: lldb/include/lldb/DataFormatters/FormattersContainer.h =================================================================== --- lldb/include/lldb/DataFormatters/FormattersContainer.h +++ lldb/include/lldb/DataFormatters/FormattersContainer.h @@ -65,8 +65,49 @@ template <typename KeyType, typename ValueType> class FormatMap { public: typedef typename ValueType::SharedPointer ValueSP; - typedef std::map<KeyType, ValueSP> MapType; + // A ValueSP wrapper to track its lifetime and remove it from 'm_age' during + // its destruction. + class ValueTracker { + private: + typedef std::list<std::pair<const KeyType, ValueTracker> *> AgeType; + void Destroy() { + if (m_age_iterator != m_age.end()) + m_age.erase(m_age_iterator); + } + + public: + typedef ValueSP payload_type; + ValueTracker(payload_type payload, AgeType &age) + : m_payload(std::move(payload)), m_age(age), m_age_iterator(age.end()) { + } + void Initialize(typename AgeType::iterator age_iterator) { + Destroy(); + lldbassert(&(*age_iterator)->second == this); + m_age_iterator = age_iterator; + } + ValueTracker(ValueTracker &&other) + : m_payload(std::move(other.m_payload)), m_age(other.m_age), + m_age_iterator(other.m_age_iterator) { + lldbassert(m_age_iterator == m_age.end()); + } + ValueTracker &operator=(ValueTracker &&other) { + std::swap(m_payload, other.m_payload); + return *this; + } + ~ValueTracker() { Destroy(); } + const payload_type &payload() const { return m_payload; } + + private: + payload_type m_payload; + AgeType &m_age; + typename AgeType::iterator m_age_iterator; + + DISALLOW_COPY_AND_ASSIGN(ValueTracker); + }; + typedef std::map<KeyType, ValueTracker> MapType; typedef typename MapType::iterator MapIterator; + typedef std::list<std::pair<const KeyType, ValueTracker> *> AgeType; + typedef typename AgeType::iterator AgeIterator; typedef std::function<bool(const KeyType &, const ValueSP &)> ForEachCallback; FormatMap(IFormatChangeListener *lst) @@ -79,7 +120,17 @@ entry->GetRevision() = 0; std::lock_guard<std::recursive_mutex> guard(m_map_mutex); - m_map[std::move(name)] = entry; + MapIterator iter = m_map.find(name); + if (iter != m_map.end()) + iter->second = ValueTracker(entry, m_age); + else { + auto inserted = + m_map.emplace(std::move(name), ValueTracker(entry, m_age)); + assert(inserted.second); + iter = inserted.first; + } + m_age.push_front(&*iter); + iter->second.Initialize(m_age.begin()); if (listener) listener->Changed(); } @@ -107,7 +158,7 @@ MapIterator iter = m_map.find(name); if (iter == m_map.end()) return false; - entry = iter->second; + entry = iter->second.payload(); return true; } @@ -117,7 +168,7 @@ MapIterator pos, end = m_map.end(); for (pos = m_map.begin(); pos != end; pos++) { const KeyType &type = pos->first; - if (!callback(type, pos->second)) + if (!callback(type, pos->second.payload())) break; } } @@ -135,10 +186,10 @@ if (end == iter) return ValueSP(); } - return iter->second; + return iter->second.payload(); } - // If caller holds the mutex we could return a reference without copy ctor. + // If caller holds the mutex we could return a reference without the copying. KeyType GetKeyAtIndex(size_t index) { std::lock_guard<std::recursive_mutex> guard(m_map_mutex); MapIterator iter = m_map.begin(); @@ -153,10 +204,13 @@ } protected: + AgeType m_age; + // 'm_map' must be destructed first as its element dtor accesses 'm_age'. MapType m_map; std::recursive_mutex m_map_mutex; IFormatChangeListener *listener; + const AgeType &age() const { return m_age; } MapType &map() { return m_map; } std::recursive_mutex &mutex() { return m_map_mutex; } @@ -173,7 +227,9 @@ typedef typename BackEndType::MapType MapType; typedef typename MapType::iterator MapIterator; typedef typename MapType::key_type MapKeyType; - typedef typename MapType::mapped_type MapValueType; + typedef typename MapType::mapped_type::payload_type MapValueType; + typedef typename BackEndType::AgeType AgeType; + typedef typename AgeType::const_iterator AgeConstIterator; typedef typename BackEndType::ForEachCallback ForEachCallback; typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>> SharedPointer; @@ -295,11 +351,11 @@ RegularExpression *dummy) { llvm::StringRef key_str = key.GetStringRef(); std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); - MapIterator pos, end = m_format_map.map().end(); - for (pos = m_format_map.map().begin(); pos != end; pos++) { - const RegularExpression ®ex = pos->first; + AgeConstIterator pos, end = m_format_map.age().cend(); + for (pos = m_format_map.age().cbegin(); pos != end; pos++) { + const RegularExpression ®ex = (*pos)->first; if (regex.Execute(key_str)) { - value = pos->second; + value = (*pos)->second.payload(); return true; } } @@ -313,7 +369,7 @@ for (pos = m_format_map.map().begin(); pos != end; pos++) { const RegularExpression ®ex = pos->first; if (regex.GetText() == key.GetStringRef()) { - value = pos->second; + value = pos->second.payload(); return true; } }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits