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