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