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