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:
26   BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
27       : m_manager_sp(std::move(manager_sp)) {}
28   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 
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 
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 
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 
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 
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 
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
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 
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 
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:
213   EventBroadcasterMatches(Broadcaster *broadcaster)
214       : m_broadcaster(broadcaster) {}
215 
216   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:
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 
232   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 
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 
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 
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 *
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 
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 
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 
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 
395 bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
396   return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
397 }
398 
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
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 
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 
461 ListenerSP Listener::MakeListener(const char *name) {
462   return ListenerSP(new Listener(name));
463 }
464