1 //===-- Listener.cpp ------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "lldb/Utility/Listener.h"
10 #include "lldb/Utility/Broadcaster.h"
11 #include "lldb/Utility/ConstString.h"
12 #include "lldb/Utility/Event.h"
13 #include "lldb/Utility/LLDBLog.h"
14 #include "llvm/ADT/Optional.h"
15
16 #include <algorithm>
17 #include <memory>
18 #include <utility>
19
20 using namespace lldb;
21 using namespace lldb_private;
22
23 namespace {
24 class BroadcasterManagerWPMatcher {
25 public:
BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)26 BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
27 : m_manager_sp(std::move(manager_sp)) {}
operator ()(const BroadcasterManagerWP & input_wp) const28 bool operator()(const BroadcasterManagerWP &input_wp) const {
29 BroadcasterManagerSP input_sp = input_wp.lock();
30 return (input_sp && input_sp == m_manager_sp);
31 }
32
33 BroadcasterManagerSP m_manager_sp;
34 };
35 } // anonymous namespace
36
Listener(const char * name)37 Listener::Listener(const char *name)
38 : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
39 m_events_mutex() {
40 Log *log = GetLog(LLDBLog::Object);
41 if (log != nullptr)
42 LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this),
43 m_name.c_str());
44 }
45
~Listener()46 Listener::~Listener() {
47 Log *log = GetLog(LLDBLog::Object);
48
49 Clear();
50
51 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
52 __FUNCTION__, m_name.c_str());
53 }
54
Clear()55 void Listener::Clear() {
56 Log *log = GetLog(LLDBLog::Object);
57 std::lock_guard<std::recursive_mutex> broadcasters_guard(
58 m_broadcasters_mutex);
59 broadcaster_collection::iterator pos, end = m_broadcasters.end();
60 for (pos = m_broadcasters.begin(); pos != end; ++pos) {
61 Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
62 if (broadcaster_sp)
63 broadcaster_sp->RemoveListener(this, pos->second.event_mask);
64 }
65 m_broadcasters.clear();
66
67 std::lock_guard<std::mutex> events_guard(m_events_mutex);
68 m_events.clear();
69 size_t num_managers = m_broadcaster_managers.size();
70
71 for (size_t i = 0; i < num_managers; i++) {
72 BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
73 if (manager_sp)
74 manager_sp->RemoveListener(this);
75 }
76
77 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
78 __FUNCTION__, m_name.c_str());
79 }
80
StartListeningForEvents(Broadcaster * broadcaster,uint32_t event_mask)81 uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
82 uint32_t event_mask) {
83 if (broadcaster) {
84 // Scope for "locker"
85 // Tell the broadcaster to add this object as a listener
86 {
87 std::lock_guard<std::recursive_mutex> broadcasters_guard(
88 m_broadcasters_mutex);
89 Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
90 m_broadcasters.insert(
91 std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
92 }
93
94 uint32_t acquired_mask =
95 broadcaster->AddListener(this->shared_from_this(), event_mask);
96
97 Log *log = GetLog(LLDBLog::Events);
98 if (log != nullptr)
99 LLDB_LOGF(log,
100 "%p Listener::StartListeningForEvents (broadcaster = %p, "
101 "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
102 static_cast<void *>(this), static_cast<void *>(broadcaster),
103 event_mask, acquired_mask, m_name.c_str());
104
105 return acquired_mask;
106 }
107 return 0;
108 }
109
StartListeningForEvents(Broadcaster * broadcaster,uint32_t event_mask,HandleBroadcastCallback callback,void * callback_user_data)110 uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
111 uint32_t event_mask,
112 HandleBroadcastCallback callback,
113 void *callback_user_data) {
114 if (broadcaster) {
115 // Scope for "locker"
116 // Tell the broadcaster to add this object as a listener
117 {
118 std::lock_guard<std::recursive_mutex> broadcasters_guard(
119 m_broadcasters_mutex);
120 Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
121 m_broadcasters.insert(std::make_pair(
122 impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
123 }
124
125 uint32_t acquired_mask =
126 broadcaster->AddListener(this->shared_from_this(), event_mask);
127
128 Log *log = GetLog(LLDBLog::Events);
129 if (log != nullptr) {
130 void **pointer = reinterpret_cast<void **>(&callback);
131 LLDB_LOGF(log,
132 "%p Listener::StartListeningForEvents (broadcaster = %p, "
133 "mask = 0x%8.8x, callback = %p, user_data = %p) "
134 "acquired_mask = 0x%8.8x for %s",
135 static_cast<void *>(this), static_cast<void *>(broadcaster),
136 event_mask, *pointer, static_cast<void *>(callback_user_data),
137 acquired_mask, m_name.c_str());
138 }
139
140 return acquired_mask;
141 }
142 return 0;
143 }
144
StopListeningForEvents(Broadcaster * broadcaster,uint32_t event_mask)145 bool Listener::StopListeningForEvents(Broadcaster *broadcaster,
146 uint32_t event_mask) {
147 if (broadcaster) {
148 // Scope for "locker"
149 {
150 std::lock_guard<std::recursive_mutex> broadcasters_guard(
151 m_broadcasters_mutex);
152 m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
153 }
154 // Remove the broadcaster from our set of broadcasters
155 return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
156 }
157
158 return false;
159 }
160
161 // Called when a Broadcaster is in its destructor. We need to remove all
162 // knowledge of this broadcaster and any events that it may have queued up
BroadcasterWillDestruct(Broadcaster * broadcaster)163 void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) {
164 // Scope for "broadcasters_locker"
165 {
166 std::lock_guard<std::recursive_mutex> broadcasters_guard(
167 m_broadcasters_mutex);
168 m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
169 }
170
171 // Scope for "event_locker"
172 {
173 std::lock_guard<std::mutex> events_guard(m_events_mutex);
174 // Remove all events for this broadcaster object.
175 event_collection::iterator pos = m_events.begin();
176 while (pos != m_events.end()) {
177 if ((*pos)->GetBroadcaster() == broadcaster)
178 pos = m_events.erase(pos);
179 else
180 ++pos;
181 }
182 }
183 }
184
BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp)185 void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) {
186 // Just need to remove this broadcast manager from the list of managers:
187 broadcaster_manager_collection::iterator iter,
188 end_iter = m_broadcaster_managers.end();
189 BroadcasterManagerWP manager_wp;
190
191 BroadcasterManagerWPMatcher matcher(std::move(manager_sp));
192 iter = std::find_if<broadcaster_manager_collection::iterator,
193 BroadcasterManagerWPMatcher>(
194 m_broadcaster_managers.begin(), end_iter, matcher);
195 if (iter != end_iter)
196 m_broadcaster_managers.erase(iter);
197 }
198
AddEvent(EventSP & event_sp)199 void Listener::AddEvent(EventSP &event_sp) {
200 Log *log = GetLog(LLDBLog::Events);
201 if (log != nullptr)
202 LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})",
203 static_cast<void *>(this), m_name.c_str(),
204 static_cast<void *>(event_sp.get()));
205
206 std::lock_guard<std::mutex> guard(m_events_mutex);
207 m_events.push_back(event_sp);
208 m_events_condition.notify_all();
209 }
210
211 class EventBroadcasterMatches {
212 public:
EventBroadcasterMatches(Broadcaster * broadcaster)213 EventBroadcasterMatches(Broadcaster *broadcaster)
214 : m_broadcaster(broadcaster) {}
215
operator ()(const EventSP & event_sp) const216 bool operator()(const EventSP &event_sp) const {
217 return event_sp->BroadcasterIs(m_broadcaster);
218 }
219
220 private:
221 Broadcaster *m_broadcaster;
222 };
223
224 class EventMatcher {
225 public:
EventMatcher(Broadcaster * broadcaster,const ConstString * broadcaster_names,uint32_t num_broadcaster_names,uint32_t event_type_mask)226 EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names,
227 uint32_t num_broadcaster_names, uint32_t event_type_mask)
228 : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names),
229 m_num_broadcaster_names(num_broadcaster_names),
230 m_event_type_mask(event_type_mask) {}
231
operator ()(const EventSP & event_sp) const232 bool operator()(const EventSP &event_sp) const {
233 if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
234 return false;
235
236 if (m_broadcaster_names) {
237 bool found_source = false;
238 ConstString event_broadcaster_name =
239 event_sp->GetBroadcaster()->GetBroadcasterName();
240 for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) {
241 if (m_broadcaster_names[i] == event_broadcaster_name) {
242 found_source = true;
243 break;
244 }
245 }
246 if (!found_source)
247 return false;
248 }
249
250 return m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType();
251 }
252
253 private:
254 Broadcaster *m_broadcaster;
255 const ConstString *m_broadcaster_names;
256 const uint32_t m_num_broadcaster_names;
257 const uint32_t m_event_type_mask;
258 };
259
FindNextEventInternal(std::unique_lock<std::mutex> & lock,Broadcaster * broadcaster,const ConstString * broadcaster_names,uint32_t num_broadcaster_names,uint32_t event_type_mask,EventSP & event_sp,bool remove)260 bool Listener::FindNextEventInternal(
261 std::unique_lock<std::mutex> &lock,
262 Broadcaster *broadcaster, // nullptr for any broadcaster
263 const ConstString *broadcaster_names, // nullptr for any event
264 uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp,
265 bool remove) {
266 // NOTE: callers of this function must lock m_events_mutex using a
267 // Mutex::Locker
268 // and pass the locker as the first argument. m_events_mutex is no longer
269 // recursive.
270 Log *log = GetLog(LLDBLog::Events);
271
272 if (m_events.empty())
273 return false;
274
275 Listener::event_collection::iterator pos = m_events.end();
276
277 if (broadcaster == nullptr && broadcaster_names == nullptr &&
278 event_type_mask == 0) {
279 pos = m_events.begin();
280 } else {
281 pos = std::find_if(m_events.begin(), m_events.end(),
282 EventMatcher(broadcaster, broadcaster_names,
283 num_broadcaster_names, event_type_mask));
284 }
285
286 if (pos != m_events.end()) {
287 event_sp = *pos;
288
289 if (log != nullptr)
290 LLDB_LOGF(log,
291 "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, "
292 "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, "
293 "remove=%i) event %p",
294 static_cast<void *>(this), GetName(),
295 static_cast<void *>(broadcaster),
296 static_cast<const void *>(broadcaster_names),
297 num_broadcaster_names, event_type_mask, remove,
298 static_cast<void *>(event_sp.get()));
299
300 if (remove) {
301 m_events.erase(pos);
302 // Unlock the event queue here. We've removed this event and are about
303 // to return it so it should be okay to get the next event off the queue
304 // here - and it might be useful to do that in the "DoOnRemoval".
305 lock.unlock();
306 event_sp->DoOnRemoval();
307 }
308 return true;
309 }
310
311 event_sp.reset();
312 return false;
313 }
314
PeekAtNextEvent()315 Event *Listener::PeekAtNextEvent() {
316 std::unique_lock<std::mutex> guard(m_events_mutex);
317 EventSP event_sp;
318 if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false))
319 return event_sp.get();
320 return nullptr;
321 }
322
PeekAtNextEventForBroadcaster(Broadcaster * broadcaster)323 Event *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) {
324 std::unique_lock<std::mutex> guard(m_events_mutex);
325 EventSP event_sp;
326 if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false))
327 return event_sp.get();
328 return nullptr;
329 }
330
331 Event *
PeekAtNextEventForBroadcasterWithType(Broadcaster * broadcaster,uint32_t event_type_mask)332 Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster,
333 uint32_t event_type_mask) {
334 std::unique_lock<std::mutex> guard(m_events_mutex);
335 EventSP event_sp;
336 if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask,
337 event_sp, false))
338 return event_sp.get();
339 return nullptr;
340 }
341
GetEventInternal(const Timeout<std::micro> & timeout,Broadcaster * broadcaster,const ConstString * broadcaster_names,uint32_t num_broadcaster_names,uint32_t event_type_mask,EventSP & event_sp)342 bool Listener::GetEventInternal(
343 const Timeout<std::micro> &timeout,
344 Broadcaster *broadcaster, // nullptr for any broadcaster
345 const ConstString *broadcaster_names, // nullptr for any event
346 uint32_t num_broadcaster_names, uint32_t event_type_mask,
347 EventSP &event_sp) {
348 Log *log = GetLog(LLDBLog::Events);
349 LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name);
350
351 std::unique_lock<std::mutex> lock(m_events_mutex);
352
353 while (true) {
354 if (FindNextEventInternal(lock, broadcaster, broadcaster_names,
355 num_broadcaster_names, event_type_mask, event_sp,
356 true)) {
357 return true;
358 } else {
359 std::cv_status result = std::cv_status::no_timeout;
360 if (!timeout)
361 m_events_condition.wait(lock);
362 else
363 result = m_events_condition.wait_for(lock, *timeout);
364
365 if (result == std::cv_status::timeout) {
366 log = GetLog(LLDBLog::Events);
367 LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s",
368 static_cast<void *>(this), m_name.c_str());
369 return false;
370 } else if (result != std::cv_status::no_timeout) {
371 log = GetLog(LLDBLog::Events);
372 LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s",
373 static_cast<void *>(this), m_name.c_str());
374 return false;
375 }
376 }
377 }
378
379 return false;
380 }
381
GetEventForBroadcasterWithType(Broadcaster * broadcaster,uint32_t event_type_mask,EventSP & event_sp,const Timeout<std::micro> & timeout)382 bool Listener::GetEventForBroadcasterWithType(
383 Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp,
384 const Timeout<std::micro> &timeout) {
385 return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask,
386 event_sp);
387 }
388
GetEventForBroadcaster(Broadcaster * broadcaster,EventSP & event_sp,const Timeout<std::micro> & timeout)389 bool Listener::GetEventForBroadcaster(Broadcaster *broadcaster,
390 EventSP &event_sp,
391 const Timeout<std::micro> &timeout) {
392 return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp);
393 }
394
GetEvent(EventSP & event_sp,const Timeout<std::micro> & timeout)395 bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
396 return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
397 }
398
HandleBroadcastEvent(EventSP & event_sp)399 size_t Listener::HandleBroadcastEvent(EventSP &event_sp) {
400 size_t num_handled = 0;
401 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
402 Broadcaster *broadcaster = event_sp->GetBroadcaster();
403 if (!broadcaster)
404 return 0;
405 broadcaster_collection::iterator pos;
406 broadcaster_collection::iterator end = m_broadcasters.end();
407 Broadcaster::BroadcasterImplSP broadcaster_impl_sp(
408 broadcaster->GetBroadcasterImpl());
409 for (pos = m_broadcasters.find(broadcaster_impl_sp);
410 pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) {
411 BroadcasterInfo info = pos->second;
412 if (event_sp->GetType() & info.event_mask) {
413 if (info.callback != nullptr) {
414 info.callback(event_sp, info.callback_user_data);
415 ++num_handled;
416 }
417 }
418 }
419 return num_handled;
420 }
421
422 uint32_t
StartListeningForEventSpec(const BroadcasterManagerSP & manager_sp,const BroadcastEventSpec & event_spec)423 Listener::StartListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
424 const BroadcastEventSpec &event_spec) {
425 if (!manager_sp)
426 return 0;
427
428 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
429 // avoid violating the lock hierarchy (manager before broadcasters).
430 std::lock_guard<std::recursive_mutex> manager_guard(
431 manager_sp->m_manager_mutex);
432 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
433
434 uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(
435 this->shared_from_this(), event_spec);
436 if (bits_acquired) {
437 broadcaster_manager_collection::iterator iter,
438 end_iter = m_broadcaster_managers.end();
439 BroadcasterManagerWP manager_wp(manager_sp);
440 BroadcasterManagerWPMatcher matcher(manager_sp);
441 iter = std::find_if<broadcaster_manager_collection::iterator,
442 BroadcasterManagerWPMatcher>(
443 m_broadcaster_managers.begin(), end_iter, matcher);
444 if (iter == end_iter)
445 m_broadcaster_managers.push_back(manager_wp);
446 }
447
448 return bits_acquired;
449 }
450
StopListeningForEventSpec(const BroadcasterManagerSP & manager_sp,const BroadcastEventSpec & event_spec)451 bool Listener::StopListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
452 const BroadcastEventSpec &event_spec) {
453 if (!manager_sp)
454 return false;
455
456 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
457 return manager_sp->UnregisterListenerForEvents(this->shared_from_this(),
458 event_spec);
459 }
460
MakeListener(const char * name)461 ListenerSP Listener::MakeListener(const char *name) {
462 return ListenerSP(new Listener(name));
463 }
464