@@ -35,10 +35,7 @@ Progress::Progress(std::string title, std::string details,
3535
3636 std::lock_guard<std::mutex> guard (m_mutex);
3737 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);
4239}
4340
4441Progress::~Progress () {
@@ -48,10 +45,7 @@ Progress::~Progress() {
4845 if (!m_completed)
4946 m_completed = m_total;
5047 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);
5549}
5650
5751void Progress::Increment (uint64_t amount,
@@ -81,84 +75,45 @@ void Progress::ReportProgress() {
8175 }
8276}
8377
84- ProgressManager::ProgressManager ()
85- : m_entries(), m_alarm(std::chrono::milliseconds(100 )) {}
78+ ProgressManager::ProgressManager () : m_progress_category_map() {}
8679
8780ProgressManager::~ProgressManager () {}
8881
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-
10182ProgressManager &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;
10990}
11091
11192void 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;
121100 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;
135101 }
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 ++;
139103}
140104
141105void 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 ) ;
144108
145- if (!m_entries. contains (key ))
109+ if (pos == m_progress_category_map. end ( ))
146110 return ;
147111
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 ;
162117 }
163118}
164119
@@ -174,20 +129,3 @@ void ProgressManager::ReportProgress(
174129 progress_data.debugger_id ,
175130 Debugger::eBroadcastBitProgressCategory);
176131}
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