Index: lldb/include/lldb/Core/ThreadSafeSTLMap.h =================================================================== --- lldb/include/lldb/Core/ThreadSafeSTLMap.h +++ /dev/null @@ -1,128 +0,0 @@ -//===-- ThreadSafeSTLMap.h --------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ThreadSafeSTLMap_h_ -#define liblldb_ThreadSafeSTLMap_h_ - -#include -#include - -#include "lldb/lldb-defines.h" - -namespace lldb_private { - -template class ThreadSafeSTLMap { -public: - typedef std::map<_Key, _Tp> collection; - typedef typename collection::iterator iterator; - typedef typename collection::const_iterator const_iterator; - // Constructors and Destructors - ThreadSafeSTLMap() : m_collection(), m_mutex() {} - - ~ThreadSafeSTLMap() {} - - bool IsEmpty() const { - std::lock_guard guard(m_mutex); - return m_collection.empty(); - } - - void Clear() { - std::lock_guard guard(m_mutex); - return m_collection.clear(); - } - - size_t Erase(const _Key &key) { - std::lock_guard guard(m_mutex); - return EraseNoLock(key); - } - - size_t EraseNoLock(const _Key &key) { return m_collection.erase(key); } - - bool GetValueForKey(const _Key &key, _Tp &value) const { - std::lock_guard guard(m_mutex); - return GetValueForKeyNoLock(key, value); - } - - // Call this if you have already manually locked the mutex using the - // GetMutex() accessor - bool GetValueForKeyNoLock(const _Key &key, _Tp &value) const { - const_iterator pos = m_collection.find(key); - if (pos != m_collection.end()) { - value = pos->second; - return true; - } - return false; - } - - bool GetFirstKeyForValue(const _Tp &value, _Key &key) const { - std::lock_guard guard(m_mutex); - return GetFirstKeyForValueNoLock(value, key); - } - - bool GetFirstKeyForValueNoLock(const _Tp &value, _Key &key) const { - const_iterator pos, end = m_collection.end(); - for (pos = m_collection.begin(); pos != end; ++pos) { - if (pos->second == value) { - key = pos->first; - return true; - } - } - return false; - } - - bool LowerBound(const _Key &key, _Key &match_key, _Tp &match_value, - bool decrement_if_not_equal) const { - std::lock_guard guard(m_mutex); - return LowerBoundNoLock(key, match_key, match_value, - decrement_if_not_equal); - } - - bool LowerBoundNoLock(const _Key &key, _Key &match_key, _Tp &match_value, - bool decrement_if_not_equal) const { - const_iterator pos = m_collection.lower_bound(key); - if (pos != m_collection.end()) { - match_key = pos->first; - if (decrement_if_not_equal && key != match_key && - pos != m_collection.begin()) { - --pos; - match_key = pos->first; - } - match_value = pos->second; - return true; - } - return false; - } - - iterator lower_bound_unsafe(const _Key &key) { - return m_collection.lower_bound(key); - } - - void SetValueForKey(const _Key &key, const _Tp &value) { - std::lock_guard guard(m_mutex); - SetValueForKeyNoLock(key, value); - } - - // Call this if you have already manually locked the mutex using the - // GetMutex() accessor - void SetValueForKeyNoLock(const _Key &key, const _Tp &value) { - m_collection[key] = value; - } - - std::recursive_mutex &GetMutex() { return m_mutex; } - -private: - collection m_collection; - mutable std::recursive_mutex m_mutex; - - // For ThreadSafeSTLMap only - DISALLOW_COPY_AND_ASSIGN(ThreadSafeSTLMap); -}; - -} // namespace lldb_private - -#endif // liblldb_ThreadSafeSTLMap_h_ Index: lldb/include/lldb/Core/ThreadSafeSTLVector.h =================================================================== --- lldb/include/lldb/Core/ThreadSafeSTLVector.h +++ /dev/null @@ -1,72 +0,0 @@ -//===-- ThreadSafeSTLVector.h ------------------------------------*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ThreadSafeSTLVector_h_ -#define liblldb_ThreadSafeSTLVector_h_ - -#include -#include - -#include "lldb/lldb-defines.h" - -namespace lldb_private { - -template class ThreadSafeSTLVector { -public: - typedef std::vector<_Object> collection; - typedef typename collection::iterator iterator; - typedef typename collection::const_iterator const_iterator; - // Constructors and Destructors - ThreadSafeSTLVector() : m_collection(), m_mutex() {} - - ~ThreadSafeSTLVector() = default; - - bool IsEmpty() const { - std::lock_guard guard(m_mutex); - return m_collection.empty(); - } - - void Clear() { - std::lock_guard guard(m_mutex); - return m_collection.clear(); - } - - size_t GetCount() { - std::lock_guard guard(m_mutex); - return m_collection.size(); - } - - void AppendObject(_Object &object) { - std::lock_guard guard(m_mutex); - m_collection.push_back(object); - } - - _Object GetObject(size_t index) { - std::lock_guard guard(m_mutex); - return m_collection.at(index); - } - - void SetObject(size_t index, const _Object &object) { - std::lock_guard guard(m_mutex); - m_collection.at(index) = object; - } - - std::recursive_mutex &GetMutex() { return m_mutex; } - -private: - collection m_collection; - mutable std::recursive_mutex m_mutex; - - // For ThreadSafeSTLVector only - DISALLOW_COPY_AND_ASSIGN(ThreadSafeSTLVector); -}; - -} // namespace lldb_private - -#endif // liblldb_ThreadSafeSTLVector_h_ Index: lldb/include/lldb/Core/ValueObjectSyntheticFilter.h =================================================================== --- lldb/include/lldb/Core/ValueObjectSyntheticFilter.h +++ lldb/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -9,8 +9,6 @@ #ifndef liblldb_ValueObjectSyntheticFilter_h_ #define liblldb_ValueObjectSyntheticFilter_h_ -#include "lldb/Core/ThreadSafeSTLMap.h" -#include "lldb/Core/ThreadSafeSTLVector.h" #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Utility/ConstString.h" @@ -135,19 +133,24 @@ lldb::SyntheticChildrenSP m_synth_sp; std::unique_ptr m_synth_filter_up; - typedef ThreadSafeSTLMap ByIndexMap; - typedef ThreadSafeSTLMap NameToIndexMap; - typedef ThreadSafeSTLVector SyntheticChildrenCache; + typedef std::map ByIndexMap; + typedef std::map NameToIndexMap; + typedef std::vector SyntheticChildrenCache; typedef ByIndexMap::iterator ByIndexIterator; typedef NameToIndexMap::iterator NameToIndexIterator; + std::mutex m_child_mutex; + /// Guarded by m_child_mutex; ByIndexMap m_children_byindex; + /// Guarded by m_child_mutex; NameToIndexMap m_name_toindex; + /// Guarded by m_child_mutex; + SyntheticChildrenCache m_synthetic_children_cache; + uint32_t m_synthetic_children_count; // FIXME use the ValueObject's // ChildrenManager instead of a special // purpose solution - SyntheticChildrenCache m_synthetic_children_cache; ConstString m_parent_type_name; Index: lldb/source/Core/ValueObjectSyntheticFilter.cpp =================================================================== --- lldb/source/Core/ValueObjectSyntheticFilter.cpp +++ lldb/source/Core/ValueObjectSyntheticFilter.cpp @@ -48,8 +48,9 @@ ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent, lldb::SyntheticChildrenSP filter) : ValueObject(parent), m_synth_sp(filter), m_children_byindex(), - m_name_toindex(), m_synthetic_children_count(UINT32_MAX), - m_synthetic_children_cache(), m_parent_type_name(parent.GetTypeName()), + m_name_toindex(), m_synthetic_children_cache(), + m_synthetic_children_count(UINT32_MAX), + m_parent_type_name(parent.GetTypeName()), m_might_have_children(eLazyBoolCalculate), m_provides_value(eLazyBoolCalculate) { SetName(parent.GetName()); @@ -177,14 +178,20 @@ "filter said caches are stale - clearing", GetName().AsCString()); // filter said that cached values are stale - m_children_byindex.Clear(); - m_name_toindex.Clear(); + { + std::lock_guard guard(m_child_mutex); + m_children_byindex.clear(); + m_name_toindex.clear(); + } // usually, an object's value can change but this does not alter its // children count for a synthetic VO that might indeed happen, so we need // to tell the upper echelons that they need to come back to us asking for // children m_children_count_valid = false; - m_synthetic_children_cache.Clear(); + { + std::lock_guard guard(m_child_mutex); + m_synthetic_children_cache.clear(); + } m_synthetic_children_count = UINT32_MAX; m_might_have_children = eLazyBoolCalculate; } else { @@ -232,7 +239,16 @@ UpdateValueIfNeeded(); ValueObject *valobj; - if (!m_children_byindex.GetValueForKey(idx, valobj)) { + bool child_is_cached; + { + std::lock_guard guard(m_child_mutex); + auto cached_child_it = m_children_byindex.find(idx); + child_is_cached = cached_child_it != m_children_byindex.end(); + if (child_is_cached) + valobj = cached_child_it->second; + } + + if (!child_is_cached) { if (can_create && m_synth_filter_up != nullptr) { LLDB_LOGF(log, "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " @@ -254,9 +270,12 @@ if (!synth_guy) return synth_guy; - if (synth_guy->IsSyntheticChildrenGenerated()) - m_synthetic_children_cache.AppendObject(synth_guy); - m_children_byindex.SetValueForKey(idx, synth_guy.get()); + { + std::lock_guard guard(m_child_mutex); + if (synth_guy->IsSyntheticChildrenGenerated()) + m_synthetic_children_cache.push_back(synth_guy); + m_children_byindex[idx] = synth_guy.get(); + } synth_guy->SetPreferredDisplayLanguageIfNeeded( GetPreferredDisplayLanguage()); return synth_guy; @@ -297,13 +316,21 @@ UpdateValueIfNeeded(); uint32_t found_index = UINT32_MAX; - bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index); + bool did_find; + { + std::lock_guard guard(m_child_mutex); + auto name_to_index = m_name_toindex.find(name.GetCString()); + did_find = name_to_index != m_name_toindex.end(); + if (did_find) + found_index = name_to_index->second; + } if (!did_find && m_synth_filter_up != nullptr) { uint32_t index = m_synth_filter_up->GetIndexOfChildWithName(name); if (index == UINT32_MAX) return index; - m_name_toindex.SetValueForKey(name.GetCString(), index); + std::lock_guard guard(m_child_mutex); + m_name_toindex[name.GetCString()] = index; return index; } else if (!did_find && m_synth_filter_up == nullptr) return UINT32_MAX;