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