Skip to content

Commit 59e3b1d

Browse files
committed
[lldb][progress] Hook up new broadcast bit and progress manager
This commit adds the functionality to broadcast events using the `Debugger::eBroadcastProgressCategory` bit (llvm#81169) by keeping track of these reports with the `ProgressManager` class (llvm#81319). The new bit is used in such a way that it will only broadcast the initial and final progress reports for specific progress categories that are managed by the progress manager. This commit also adds a new test to the progress report unit test that checks that only the initial/final reports are broadcasted when using the new bit.
1 parent f01ed3b commit 59e3b1d

File tree

5 files changed

+195
-51
lines changed

5 files changed

+195
-51
lines changed

lldb/include/lldb/Core/Debugger.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
593593
friend class CommandInterpreter;
594594
friend class REPL;
595595
friend class Progress;
596+
friend class ProgressManager;
596597

597598
/// Report progress events.
598599
///
@@ -623,10 +624,11 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
623624
/// debugger identifier that this progress should be delivered to. If this
624625
/// optional parameter does not have a value, the progress will be
625626
/// delivered to all debuggers.
626-
static void ReportProgress(uint64_t progress_id, std::string title,
627-
std::string details, uint64_t completed,
628-
uint64_t total,
629-
std::optional<lldb::user_id_t> debugger_id);
627+
static void
628+
ReportProgress(uint64_t progress_id, std::string title, std::string details,
629+
uint64_t completed, uint64_t total,
630+
std::optional<lldb::user_id_t> debugger_id,
631+
uint32_t progress_category_bit = eBroadcastBitProgress);
630632

631633
static void ReportDiagnosticImpl(DiagnosticEventData::Type type,
632634
std::string message,

lldb/include/lldb/Core/Progress.h

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
#ifndef LLDB_CORE_PROGRESS_H
1010
#define LLDB_CORE_PROGRESS_H
1111

12-
#include "lldb/Utility/ConstString.h"
12+
#include "lldb/lldb-forward.h"
1313
#include "lldb/lldb-types.h"
1414
#include "llvm/ADT/StringMap.h"
1515
#include <atomic>
16+
#include <cstdint>
1617
#include <mutex>
1718
#include <optional>
1819

@@ -97,27 +98,36 @@ class Progress {
9798
/// Used to indicate a non-deterministic progress report
9899
static constexpr uint64_t kNonDeterministicTotal = UINT64_MAX;
99100

101+
/// Data belonging to this Progress event. This data is used by the Debugger
102+
/// to broadcast the event and by the ProgressManager for bookkeeping.
103+
struct ProgressData {
104+
/// The title of the progress activity, also used as a category.
105+
std::string title;
106+
/// More specific information about the current file being displayed in the
107+
/// report.
108+
std::string details;
109+
/// A unique integer identifier for progress reporting.
110+
uint64_t progress_id;
111+
/// How much work ([0...m_total]) that has been completed.
112+
uint64_t completed;
113+
/// Total amount of work, use a std::nullopt in the constructor for non
114+
/// deterministic progress.
115+
uint64_t total;
116+
/// The optional debugger ID to report progress to. If this has no value
117+
/// then all debuggers will receive this event.
118+
std::optional<lldb::user_id_t> debugger_id;
119+
};
120+
100121
private:
101122
void ReportProgress();
102123
static std::atomic<uint64_t> g_id;
103-
/// The title of the progress activity.
104-
std::string m_title;
105-
std::string m_details;
106124
std::mutex m_mutex;
107-
/// A unique integer identifier for progress reporting.
108-
const uint64_t m_id;
109-
/// How much work ([0...m_total]) that has been completed.
110-
uint64_t m_completed;
111-
/// Total amount of work, use a std::nullopt in the constructor for non
112-
/// deterministic progress.
113-
uint64_t m_total;
114-
/// The optional debugger ID to report progress to. If this has no value then
115-
/// all debuggers will receive this event.
116-
std::optional<lldb::user_id_t> m_debugger_id;
117125
/// Set to true when progress has been reported where m_completed == m_total
118126
/// to ensure that we don't send progress updates after progress has
119127
/// completed.
120128
bool m_complete = false;
129+
/// Data needed by the debugger to broadcast a progress event.
130+
ProgressData m_progress_data;
121131
};
122132

123133
/// A class used to group progress reports by category. This is done by using a
@@ -130,13 +140,16 @@ class ProgressManager {
130140
~ProgressManager();
131141

132142
/// Control the refcount of the progress report category as needed.
133-
void Increment(std::string category);
134-
void Decrement(std::string category);
143+
void Increment(const Progress::ProgressData &);
144+
void Decrement(const Progress::ProgressData &);
135145

136146
static ProgressManager &Instance();
137147

148+
void ReportProgress(Progress::ProgressData);
149+
138150
private:
139-
llvm::StringMap<uint64_t> m_progress_category_map;
151+
llvm::StringMap<std::pair<uint64_t, Progress::ProgressData>>
152+
m_progress_category_map;
140153
std::mutex m_progress_map_mutex;
141154
};
142155

lldb/source/Core/Debugger.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "lldb/Core/ModuleList.h"
1616
#include "lldb/Core/ModuleSpec.h"
1717
#include "lldb/Core/PluginManager.h"
18+
#include "lldb/Core/Progress.h"
1819
#include "lldb/Core/StreamAsynchronousIO.h"
1920
#include "lldb/DataFormatters/DataVisualization.h"
2021
#include "lldb/Expression/REPL.h"
@@ -1433,13 +1434,14 @@ void Debugger::SetDestroyCallback(
14331434
static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
14341435
std::string title, std::string details,
14351436
uint64_t completed, uint64_t total,
1436-
bool is_debugger_specific) {
1437+
bool is_debugger_specific,
1438+
uint32_t progress_broadcast_bit) {
14371439
// Only deliver progress events if we have any progress listeners.
1438-
const uint32_t event_type = Debugger::eBroadcastBitProgress;
1439-
if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type))
1440+
if (!debugger.GetBroadcaster().EventTypeHasListeners(progress_broadcast_bit))
14401441
return;
1442+
14411443
EventSP event_sp(new Event(
1442-
event_type,
1444+
progress_broadcast_bit,
14431445
new ProgressEventData(progress_id, std::move(title), std::move(details),
14441446
completed, total, is_debugger_specific)));
14451447
debugger.GetBroadcaster().BroadcastEvent(event_sp);
@@ -1448,7 +1450,8 @@ static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
14481450
void Debugger::ReportProgress(uint64_t progress_id, std::string title,
14491451
std::string details, uint64_t completed,
14501452
uint64_t total,
1451-
std::optional<lldb::user_id_t> debugger_id) {
1453+
std::optional<lldb::user_id_t> debugger_id,
1454+
uint32_t progress_category_bit) {
14521455
// Check if this progress is for a specific debugger.
14531456
if (debugger_id) {
14541457
// It is debugger specific, grab it and deliver the event if the debugger
@@ -1457,7 +1460,8 @@ void Debugger::ReportProgress(uint64_t progress_id, std::string title,
14571460
if (debugger_sp)
14581461
PrivateReportProgress(*debugger_sp, progress_id, std::move(title),
14591462
std::move(details), completed, total,
1460-
/*is_debugger_specific*/ true);
1463+
/*is_debugger_specific*/ true,
1464+
progress_category_bit);
14611465
return;
14621466
}
14631467
// The progress event is not debugger specific, iterate over all debuggers
@@ -1467,7 +1471,8 @@ void Debugger::ReportProgress(uint64_t progress_id, std::string title,
14671471
DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
14681472
for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos)
14691473
PrivateReportProgress(*(*pos), progress_id, title, details, completed,
1470-
total, /*is_debugger_specific*/ false);
1474+
total, /*is_debugger_specific*/ false,
1475+
progress_category_bit);
14711476
}
14721477
}
14731478

lldb/source/Core/Progress.cpp

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "lldb/Core/Debugger.h"
1212
#include "lldb/Utility/StreamString.h"
1313

14+
#include <cstdint>
1415
#include <mutex>
1516
#include <optional>
1617

@@ -22,38 +23,46 @@ std::atomic<uint64_t> Progress::g_id(0);
2223
Progress::Progress(std::string title, std::string details,
2324
std::optional<uint64_t> total,
2425
lldb_private::Debugger *debugger)
25-
: m_title(title), m_details(details), m_id(++g_id), m_completed(0),
26-
m_total(Progress::kNonDeterministicTotal) {
26+
: m_progress_data{title,
27+
details,
28+
++g_id,
29+
/*m_progress_data.completed=*/0,
30+
Progress::kNonDeterministicTotal,
31+
/*m_progress_data.debugger_id=*/std::nullopt} {
2732
if (total)
28-
m_total = *total;
33+
m_progress_data.total = *total;
2934

3035
if (debugger)
31-
m_debugger_id = debugger->GetID();
36+
m_progress_data.debugger_id = debugger->GetID();
37+
3238
std::lock_guard<std::mutex> guard(m_mutex);
3339
ReportProgress();
40+
ProgressManager::Instance().Increment(m_progress_data);
3441
}
3542

3643
Progress::~Progress() {
3744
// Make sure to always report progress completed when this object is
3845
// destructed so it indicates the progress dialog/activity should go away.
3946
std::lock_guard<std::mutex> guard(m_mutex);
40-
if (!m_completed)
41-
m_completed = m_total;
47+
if (!m_progress_data.completed)
48+
m_progress_data.completed = m_progress_data.total;
4249
ReportProgress();
50+
ProgressManager::Instance().Decrement(m_progress_data);
4351
}
4452

4553
void Progress::Increment(uint64_t amount,
4654
std::optional<std::string> updated_detail) {
4755
if (amount > 0) {
4856
std::lock_guard<std::mutex> guard(m_mutex);
4957
if (updated_detail)
50-
m_details = std::move(updated_detail.value());
58+
m_progress_data.details = std::move(updated_detail.value());
5159
// Watch out for unsigned overflow and make sure we don't increment too
52-
// much and exceed m_total.
53-
if (m_total && (amount > (m_total - m_completed)))
54-
m_completed = m_total;
60+
// much and exceed the total.
61+
if (m_progress_data.total &&
62+
(amount > (m_progress_data.total - m_progress_data.completed)))
63+
m_progress_data.completed = m_progress_data.total;
5564
else
56-
m_completed += amount;
65+
m_progress_data.completed += amount;
5766
ReportProgress();
5867
}
5968
}
@@ -62,9 +71,11 @@ void Progress::ReportProgress() {
6271
if (!m_complete) {
6372
// Make sure we only send one notification that indicates the progress is
6473
// complete
65-
m_complete = m_completed == m_total;
66-
Debugger::ReportProgress(m_id, m_title, m_details, m_completed, m_total,
67-
m_debugger_id);
74+
m_complete = m_progress_data.completed == m_progress_data.total;
75+
Debugger::ReportProgress(m_progress_data.progress_id, m_progress_data.title,
76+
m_progress_data.details, m_progress_data.completed,
77+
m_progress_data.total,
78+
m_progress_data.debugger_id);
6879
}
6980
}
7081

@@ -82,20 +93,42 @@ ProgressManager &ProgressManager::Instance() {
8293
return *g_progress_manager;
8394
}
8495

85-
void ProgressManager::Increment(std::string title) {
96+
void ProgressManager::Increment(const Progress::ProgressData &progress_data) {
8697
std::lock_guard<std::mutex> lock(m_progress_map_mutex);
87-
m_progress_category_map[title]++;
98+
// If the current category exists in the map then it is not an initial report,
99+
// therefore don't broadcast to the category bit. Also, store the current
100+
// progress data in the map so that we have a note of the ID used for the
101+
// initial progress report.
102+
if (!m_progress_category_map.contains(progress_data.title)) {
103+
m_progress_category_map[progress_data.title].second = progress_data;
104+
ReportProgress(progress_data);
105+
}
106+
m_progress_category_map[progress_data.title].first++;
88107
}
89108

90-
void ProgressManager::Decrement(std::string title) {
109+
void ProgressManager::Decrement(const Progress::ProgressData &progress_data) {
91110
std::lock_guard<std::mutex> lock(m_progress_map_mutex);
92-
auto pos = m_progress_category_map.find(title);
111+
auto pos = m_progress_category_map.find(progress_data.title);
93112

94113
if (pos == m_progress_category_map.end())
95114
return;
96115

97-
if (pos->second <= 1)
98-
m_progress_category_map.erase(title);
99-
else
100-
--pos->second;
116+
if (pos->second.first <= 1) {
117+
ReportProgress(progress_data);
118+
m_progress_category_map.erase(progress_data.title);
119+
} else {
120+
--pos->second.first;
121+
}
122+
}
123+
124+
void ProgressManager::ReportProgress(Progress::ProgressData progress_data) {
125+
// The category bit only keeps track of when progress report categories have
126+
// started and ended, so clear the details and other fields when broadcasting
127+
// to it since that bit doesn't need that information.
128+
129+
Debugger::ReportProgress(
130+
m_progress_category_map[progress_data.title].second.progress_id,
131+
progress_data.title, "", Progress::kNonDeterministicTotal,
132+
Progress::kNonDeterministicTotal, progress_data.debugger_id,
133+
Debugger::eBroadcastBitProgressCategory);
101134
}

0 commit comments

Comments
 (0)