Listener.cpp revision 360784
1//===-- Listener.cpp --------------------------------------------*- C++ -*-===//
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
23using namespace lldb;
24using namespace lldb_private;
25
26namespace {
27class BroadcasterManagerWPMatcher {
28public:
29  BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
30      : m_manager_sp(std::move(manager_sp)) {}
31  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
40Listener::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
49Listener::~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
58void 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
84uint32_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
113uint32_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
148bool 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
166void 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
188void 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
202void 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
214class EventBroadcasterMatches {
215public:
216  EventBroadcasterMatches(Broadcaster *broadcaster)
217      : m_broadcaster(broadcaster) {}
218
219  bool operator()(const EventSP &event_sp) const {
220    return event_sp->BroadcasterIs(m_broadcaster);
221  }
222
223private:
224  Broadcaster *m_broadcaster;
225};
226
227class EventMatcher {
228public:
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
235  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
256private:
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
263bool 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
318Event *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
326Event *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
334Event *
335Listener::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
345bool 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
385bool 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
392bool 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
398bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
399  return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
400}
401
402size_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
425uint32_t
426Listener::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
454bool 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
464ListenerSP Listener::MakeListener(const char *name) {
465  return ListenerSP(new Listener(name));
466}
467