Listener.cpp revision 344779
1235537Sgber//===-- Listener.cpp --------------------------------------------*- C++ -*-===//
2235537Sgber//
3235537Sgber//                     The LLVM Compiler Infrastructure
4235537Sgber//
5235537Sgber// This file is distributed under the University of Illinois Open Source
6235537Sgber// License. See LICENSE.TXT for details.
7235537Sgber//
8235537Sgber//===----------------------------------------------------------------------===//
9235537Sgber
10235537Sgber#include "lldb/Utility/Listener.h"
11235537Sgber
12235537Sgber#include "lldb/Utility/Broadcaster.h"
13235537Sgber#include "lldb/Utility/ConstString.h"
14235537Sgber#include "lldb/Utility/Event.h"
15235537Sgber#include "lldb/Utility/Log.h"
16235537Sgber#include "lldb/Utility/Logging.h"
17235537Sgber
18235537Sgber#include "llvm/ADT/Optional.h"
19235537Sgber
20235537Sgber#include <algorithm>
21235537Sgber#include <memory>
22235537Sgber#include <utility>
23235537Sgber
24235537Sgberusing namespace lldb;
25235537Sgberusing namespace lldb_private;
26235537Sgber
27235537Sgbernamespace {
28235537Sgberclass BroadcasterManagerWPMatcher {
29235537Sgberpublic:
30235537Sgber  BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
31235537Sgber      : m_manager_sp(manager_sp) {}
32235537Sgber  bool operator()(const BroadcasterManagerWP input_wp) const {
33235537Sgber    BroadcasterManagerSP input_sp = input_wp.lock();
34235537Sgber    return (input_sp && input_sp == m_manager_sp);
35235537Sgber  }
36235537Sgber
37235537Sgber  BroadcasterManagerSP m_manager_sp;
38235537Sgber};
39235537Sgber} // anonymous namespace
40235537Sgber
41235537SgberListener::Listener(const char *name)
42235537Sgber    : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
43235537Sgber      m_events_mutex() {
44235537Sgber  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
45235537Sgber  if (log != nullptr)
46235537Sgber    log->Printf("%p Listener::Listener('%s')", static_cast<void *>(this),
47235537Sgber                m_name.c_str());
48235537Sgber}
49235537Sgber
50235537SgberListener::~Listener() {
51235537Sgber  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
52235537Sgber
53235537Sgber  Clear();
54235537Sgber
55235537Sgber  if (log)
56235537Sgber    log->Printf("%p Listener::%s('%s')", static_cast<void *>(this),
57235537Sgber                __FUNCTION__, m_name.c_str());
58235537Sgber}
59235537Sgber
60235537Sgbervoid Listener::Clear() {
61235537Sgber  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
62235537Sgber  std::lock_guard<std::recursive_mutex> broadcasters_guard(
63235537Sgber      m_broadcasters_mutex);
64235537Sgber  broadcaster_collection::iterator pos, end = m_broadcasters.end();
65235537Sgber  for (pos = m_broadcasters.begin(); pos != end; ++pos) {
66235537Sgber    Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
67235537Sgber    if (broadcaster_sp)
68235537Sgber      broadcaster_sp->RemoveListener(this, pos->second.event_mask);
69235537Sgber  }
70235537Sgber  m_broadcasters.clear();
71235537Sgber
72235537Sgber  std::lock_guard<std::mutex> events_guard(m_events_mutex);
73235537Sgber  m_events.clear();
74235537Sgber  size_t num_managers = m_broadcaster_managers.size();
75235537Sgber
76235537Sgber  for (size_t i = 0; i < num_managers; i++) {
77235537Sgber    BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
78235537Sgber    if (manager_sp)
79235537Sgber      manager_sp->RemoveListener(this);
80235537Sgber  }
81235537Sgber
82235537Sgber  if (log)
83235537Sgber    log->Printf("%p Listener::%s('%s')", static_cast<void *>(this),
84235537Sgber                __FUNCTION__, m_name.c_str());
85235537Sgber}
86235537Sgber
87235537Sgberuint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
88235537Sgber                                           uint32_t event_mask) {
89235537Sgber  if (broadcaster) {
90235537Sgber    // Scope for "locker"
91235537Sgber    // Tell the broadcaster to add this object as a listener
92235537Sgber    {
93235537Sgber      std::lock_guard<std::recursive_mutex> broadcasters_guard(
94235537Sgber          m_broadcasters_mutex);
95235537Sgber      Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
96235537Sgber      m_broadcasters.insert(
97235537Sgber          std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
98235537Sgber    }
99235537Sgber
100235537Sgber    uint32_t acquired_mask =
101235537Sgber        broadcaster->AddListener(this->shared_from_this(), event_mask);
102235537Sgber
103235537Sgber    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
104235537Sgber    if (log != nullptr)
105235537Sgber      log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, "
106235537Sgber                  "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
107235537Sgber                  static_cast<void *>(this), static_cast<void *>(broadcaster),
108235537Sgber                  event_mask, acquired_mask, m_name.c_str());
109235537Sgber
110235537Sgber    return acquired_mask;
111235537Sgber  }
112235537Sgber  return 0;
113235537Sgber}
114235537Sgber
115235537Sgberuint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
116235537Sgber                                           uint32_t event_mask,
117235537Sgber                                           HandleBroadcastCallback callback,
118235537Sgber                                           void *callback_user_data) {
119235537Sgber  if (broadcaster) {
120235537Sgber    // Scope for "locker"
121235537Sgber    // Tell the broadcaster to add this object as a listener
122235537Sgber    {
123235537Sgber      std::lock_guard<std::recursive_mutex> broadcasters_guard(
124235537Sgber          m_broadcasters_mutex);
125235537Sgber      Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
126235537Sgber      m_broadcasters.insert(std::make_pair(
127235537Sgber          impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
128235537Sgber    }
129235537Sgber
130235537Sgber    uint32_t acquired_mask =
131235537Sgber        broadcaster->AddListener(this->shared_from_this(), event_mask);
132235537Sgber
133235537Sgber    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
134235537Sgber    if (log != nullptr) {
135235537Sgber      void **pointer = reinterpret_cast<void **>(&callback);
136235537Sgber      log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, "
137235537Sgber                  "mask = 0x%8.8x, callback = %p, user_data = %p) "
138235537Sgber                  "acquired_mask = 0x%8.8x for %s",
139235537Sgber                  static_cast<void *>(this), static_cast<void *>(broadcaster),
140235537Sgber                  event_mask, *pointer, static_cast<void *>(callback_user_data),
141235537Sgber                  acquired_mask, m_name.c_str());
142235537Sgber    }
143235537Sgber
144235537Sgber    return acquired_mask;
145235537Sgber  }
146235537Sgber  return 0;
147235537Sgber}
148235537Sgber
149235537Sgberbool Listener::StopListeningForEvents(Broadcaster *broadcaster,
150235537Sgber                                      uint32_t event_mask) {
151235537Sgber  if (broadcaster) {
152235537Sgber    // Scope for "locker"
153235537Sgber    {
154235537Sgber      std::lock_guard<std::recursive_mutex> broadcasters_guard(
155235537Sgber          m_broadcasters_mutex);
156235537Sgber      m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
157235537Sgber    }
158235537Sgber    // Remove the broadcaster from our set of broadcasters
159235537Sgber    return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
160235537Sgber  }
161235537Sgber
162235537Sgber  return false;
163235537Sgber}
164235537Sgber
165235537Sgber// 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
167void 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
189void 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
203void 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
215class EventBroadcasterMatches {
216public:
217  EventBroadcasterMatches(Broadcaster *broadcaster)
218      : m_broadcaster(broadcaster) {}
219
220  bool operator()(const EventSP &event_sp) const {
221    return event_sp->BroadcasterIs(m_broadcaster);
222  }
223
224private:
225  Broadcaster *m_broadcaster;
226};
227
228class EventMatcher {
229public:
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
236  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
257private:
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
264bool 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
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        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
387bool 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
394bool 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
400bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
401  return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
402}
403
404size_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
427uint32_t
428Listener::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
456bool 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
466ListenerSP Listener::MakeListener(const char *name) {
467  return ListenerSP(new Listener(name));
468}
469