@@ -35,10 +35,7 @@ Progress::Progress(std::string title, std::string details,
35
35
36
36
std::lock_guard<std::mutex> guard (m_mutex);
37
37
ReportProgress ();
38
-
39
- // Report to the ProgressManager if that subsystem is enabled.
40
- if (ProgressManager::Enabled ())
41
- ProgressManager::Instance ().Increment (m_progress_data);
38
+ ProgressManager::Instance ().Increment (m_progress_data);
42
39
}
43
40
44
41
Progress::~Progress () {
@@ -48,10 +45,7 @@ Progress::~Progress() {
48
45
if (!m_completed)
49
46
m_completed = m_total;
50
47
ReportProgress ();
51
-
52
- // Report to the ProgressManager if that subsystem is enabled.
53
- if (ProgressManager::Enabled ())
54
- ProgressManager::Instance ().Decrement (m_progress_data);
48
+ ProgressManager::Instance ().Decrement (m_progress_data);
55
49
}
56
50
57
51
void Progress::Increment (uint64_t amount,
@@ -81,84 +75,45 @@ void Progress::ReportProgress() {
81
75
}
82
76
}
83
77
84
- ProgressManager::ProgressManager ()
85
- : m_entries(), m_alarm(std::chrono::milliseconds(100 )) {}
78
+ ProgressManager::ProgressManager () : m_progress_category_map() {}
86
79
87
80
ProgressManager::~ProgressManager () {}
88
81
89
- void ProgressManager::Initialize () {
90
- assert (!InstanceImpl () && " Already initialized." );
91
- InstanceImpl ().emplace ();
92
- }
93
-
94
- void ProgressManager::Terminate () {
95
- assert (InstanceImpl () && " Already terminated." );
96
- InstanceImpl ().reset ();
97
- }
98
-
99
- bool ProgressManager::Enabled () { return InstanceImpl ().operator bool (); }
100
-
101
82
ProgressManager &ProgressManager::Instance () {
102
- assert ( InstanceImpl () && " ProgressManager must be initialized " ) ;
103
- return * InstanceImpl () ;
104
- }
105
-
106
- std::optional<ProgressManager> & ProgressManager::InstanceImpl () {
107
- static std::optional<ProgressManager> g_progress_manager ;
108
- return g_progress_manager;
83
+ static std::once_flag g_once_flag ;
84
+ static ProgressManager *g_progress_manager = nullptr ;
85
+ std::call_once (g_once_flag, []() {
86
+ // NOTE: known leak to avoid global destructor chain issues.
87
+ g_progress_manager = new ProgressManager ();
88
+ }) ;
89
+ return * g_progress_manager;
109
90
}
110
91
111
92
void ProgressManager::Increment (const Progress::ProgressData &progress_data) {
112
- std::lock_guard<std::mutex> lock (m_entries_mutex);
113
-
114
- llvm::StringRef key = progress_data.title ;
115
- bool new_entry = !m_entries.contains (key);
116
- Entry &entry = m_entries[progress_data.title ];
117
-
118
- if (new_entry) {
119
- // This is a new progress event. Report progress and store the progress
120
- // data.
93
+ std::lock_guard<std::mutex> lock (m_progress_map_mutex);
94
+ // If the current category exists in the map then it is not an initial report,
95
+ // therefore don't broadcast to the category bit. Also, store the current
96
+ // progress data in the map so that we have a note of the ID used for the
97
+ // initial progress report.
98
+ if (!m_progress_category_map.contains (progress_data.title )) {
99
+ m_progress_category_map[progress_data.title ].second = progress_data;
121
100
ReportProgress (progress_data, EventType::Begin);
122
- entry.data = progress_data;
123
- } else if (entry.refcount == 0 ) {
124
- // This is an existing entry that was scheduled to be deleted but a new one
125
- // came in before the timer expired.
126
- assert (entry.handle != Alarm::INVALID_HANDLE);
127
-
128
- if (!m_alarm.Cancel (entry.handle )) {
129
- // The timer expired before we had a chance to cancel it. We have to treat
130
- // this as an entirely new progress event.
131
- ReportProgress (progress_data, EventType::Begin);
132
- }
133
- // Clear the alarm handle.
134
- entry.handle = Alarm::INVALID_HANDLE;
135
101
}
136
-
137
- // Regardless of how we got here, we need to bump the reference count.
138
- entry.refcount ++;
102
+ m_progress_category_map[progress_data.title ].first ++;
139
103
}
140
104
141
105
void ProgressManager::Decrement (const Progress::ProgressData &progress_data) {
142
- std::lock_guard<std::mutex> lock (m_entries_mutex );
143
- llvm::StringRef key = progress_data.title ;
106
+ std::lock_guard<std::mutex> lock (m_progress_map_mutex );
107
+ auto pos = m_progress_category_map. find ( progress_data.title ) ;
144
108
145
- if (!m_entries. contains (key ))
109
+ if (pos == m_progress_category_map. end ( ))
146
110
return ;
147
111
148
- Entry &entry = m_entries[key];
149
- entry.refcount --;
150
-
151
- if (entry.refcount == 0 ) {
152
- assert (entry.handle == Alarm::INVALID_HANDLE);
153
-
154
- // Copy the key to a std::string so we can pass it by value to the lambda.
155
- // The underlying StringRef will not exist by the time the callback is
156
- // called.
157
- std::string key_str = std::string (key);
158
-
159
- // Start a timer. If it expires before we see another progress event, it
160
- // will be reported.
161
- entry.handle = m_alarm.Create ([=]() { Expire (key_str); });
112
+ if (pos->second .first <= 1 ) {
113
+ ReportProgress (pos->second .second , EventType::End);
114
+ m_progress_category_map.erase (progress_data.title );
115
+ } else {
116
+ --pos->second .first ;
162
117
}
163
118
}
164
119
@@ -174,20 +129,3 @@ void ProgressManager::ReportProgress(
174
129
progress_data.debugger_id ,
175
130
Debugger::eBroadcastBitProgressCategory);
176
131
}
177
-
178
- void ProgressManager::Expire (llvm::StringRef key) {
179
- std::lock_guard<std::mutex> lock (m_entries_mutex);
180
-
181
- // This shouldn't happen but be resilient anyway.
182
- if (!m_entries.contains (key))
183
- return ;
184
-
185
- // A new event came in and the alarm fired before we had a chance to restart
186
- // it.
187
- if (m_entries[key].refcount != 0 )
188
- return ;
189
-
190
- // We're done with this entry.
191
- ReportProgress (m_entries[key].data , EventType::End);
192
- m_entries.erase (key);
193
- }
0 commit comments