[Lldb-commits] [lldb] [lldb][progress][NFC] Add groundwork to keep track of progress reports (PR #81026)
Greg Clayton via lldb-commits
lldb-commits at lists.llvm.org
Wed Feb 7 13:39:23 PST 2024
================
@@ -9,26 +9,34 @@
#include "lldb/Core/Progress.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Utility/StreamString.h"
#include <optional>
using namespace lldb;
using namespace lldb_private;
std::atomic<uint64_t> Progress::g_id(0);
+std::atomic<uint64_t> Progress::g_refcount(1);
+std::unordered_map<std::string, uint64_t> Progress::g_map = {};
----------------
clayborg wrote:
When something isn't just an integer, like the map here, we can run into issues with this in a multi-threaded environment. Why? These variables are part of the global C++ constructor / destructor chain. If any thread uses these after the main thread shuts down it can cause a crash. So for global objects we typically will create a pointer to one and leak it with a note. See `lldb/source/Core/Debugger.cpp` and look for `g_debugger_list_mutex_ptr` and other variables right next to them and then see `Debugger::Initialize()`.
This map also need to be threadsafe, so it needs a mutex. Might be a good idea to create a class to contain these and use an accessor to provide access to it. The solution below will make something that is thread safe _and_ also something that will survive the global destructor chain being called and letting other threads still be able to use Progress objects without crashing the process:
```
namespace {
class ProgressCategoryMap {
std::mutex m_mutex;
std::unordered_map<std::string, uint64_t> m_map;
void Increment(std::string title) {
std::lock_guard<std::mutex> lock(m_mutex);
auto pair = g_map.emplace(title, 1); // No need to use g_refcount as it is just a constant 1
// pair.first will be true if insertion happened.
if (pair.first == false)
++pair.second; // Key already in map, increment the ref count.
}
void Decrement(std::string title) {
std::lock_guard<std::mutex> lock(m_mutex);
auto pos = g_map.find(title);
if (pos == g_map.end())
return;
if (--pos->second == 0)
g_map.erase(pos->second); // Decremented to zero
}
};
// Now make a global accessor to get a threadsafe copy of ProgressCategoryMap
ProgressCategoryMap *GetProgressCategoryMap() {
static std::once_flag g_once;
static ProgressCategoryMap *g_category_map_ptr = nullptr;
std::call_once(g_once, []{
// NOTE: intentional leak to avoid issues with C++ destructor chain
g_category_map_ptr = new ProgressCategoryMap();
});
return g_category_map_ptr;
}
} // anonymous namespace
```
https://github.com/llvm/llvm-project/pull/81026
More information about the lldb-commits
mailing list