1343181Sdim//===-- Listener.cpp --------------------------------------------*- C++ -*-===//
2343181Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343181Sdim//
7343181Sdim//===----------------------------------------------------------------------===//
8343181Sdim
9343181Sdim#include "lldb/Utility/Listener.h"
10343181Sdim
11343181Sdim#include "lldb/Utility/Broadcaster.h"
12343181Sdim#include "lldb/Utility/ConstString.h"
13343181Sdim#include "lldb/Utility/Event.h"
14343181Sdim#include "lldb/Utility/Log.h"
15343181Sdim#include "lldb/Utility/Logging.h"
16343181Sdim
17343181Sdim#include "llvm/ADT/Optional.h"
18343181Sdim
19343181Sdim#include <algorithm>
20343181Sdim#include <memory>
21343181Sdim#include <utility>
22343181Sdim
23343181Sdimusing namespace lldb;
24343181Sdimusing namespace lldb_private;
25343181Sdim
26343181Sdimnamespace {
27343181Sdimclass BroadcasterManagerWPMatcher {
28343181Sdimpublic:
29343181Sdim  BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
30353358Sdim      : m_manager_sp(std::move(manager_sp)) {}
31353358Sdim  bool operator()(const BroadcasterManagerWP &input_wp) const {
32343181Sdim    BroadcasterManagerSP input_sp = input_wp.lock();
33343181Sdim    return (input_sp && input_sp == m_manager_sp);
34343181Sdim  }
35343181Sdim
36343181Sdim  BroadcasterManagerSP m_manager_sp;
37343181Sdim};
38343181Sdim} // anonymous namespace
39343181Sdim
40343181SdimListener::Listener(const char *name)
41343181Sdim    : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
42343181Sdim      m_events_mutex() {
43343181Sdim  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
44343181Sdim  if (log != nullptr)
45360784Sdim    LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this),
46360784Sdim              m_name.c_str());
47343181Sdim}
48343181Sdim
49343181SdimListener::~Listener() {
50343181Sdim  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
51343181Sdim
52343181Sdim  Clear();
53343181Sdim
54360784Sdim  LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
55360784Sdim            __FUNCTION__, m_name.c_str());
56343181Sdim}
57343181Sdim
58343181Sdimvoid Listener::Clear() {
59343181Sdim  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
60343181Sdim  std::lock_guard<std::recursive_mutex> broadcasters_guard(
61343181Sdim      m_broadcasters_mutex);
62343181Sdim  broadcaster_collection::iterator pos, end = m_broadcasters.end();
63343181Sdim  for (pos = m_broadcasters.begin(); pos != end; ++pos) {
64343181Sdim    Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
65343181Sdim    if (broadcaster_sp)
66343181Sdim      broadcaster_sp->RemoveListener(this, pos->second.event_mask);
67343181Sdim  }
68343181Sdim  m_broadcasters.clear();
69343181Sdim
70343181Sdim  std::lock_guard<std::mutex> events_guard(m_events_mutex);
71343181Sdim  m_events.clear();
72343181Sdim  size_t num_managers = m_broadcaster_managers.size();
73343181Sdim
74343181Sdim  for (size_t i = 0; i < num_managers; i++) {
75343181Sdim    BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
76343181Sdim    if (manager_sp)
77343181Sdim      manager_sp->RemoveListener(this);
78343181Sdim  }
79343181Sdim
80360784Sdim  LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
81360784Sdim            __FUNCTION__, m_name.c_str());
82343181Sdim}
83343181Sdim
84343181Sdimuint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
85343181Sdim                                           uint32_t event_mask) {
86343181Sdim  if (broadcaster) {
87343181Sdim    // Scope for "locker"
88343181Sdim    // Tell the broadcaster to add this object as a listener
89343181Sdim    {
90343181Sdim      std::lock_guard<std::recursive_mutex> broadcasters_guard(
91343181Sdim          m_broadcasters_mutex);
92343181Sdim      Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
93343181Sdim      m_broadcasters.insert(
94343181Sdim          std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
95343181Sdim    }
96343181Sdim
97343181Sdim    uint32_t acquired_mask =
98343181Sdim        broadcaster->AddListener(this->shared_from_this(), event_mask);
99343181Sdim
100343181Sdim    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
101343181Sdim    if (log != nullptr)
102360784Sdim      LLDB_LOGF(log,
103360784Sdim                "%p Listener::StartListeningForEvents (broadcaster = %p, "
104360784Sdim                "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
105360784Sdim                static_cast<void *>(this), static_cast<void *>(broadcaster),
106360784Sdim                event_mask, acquired_mask, m_name.c_str());
107343181Sdim
108343181Sdim    return acquired_mask;
109343181Sdim  }
110343181Sdim  return 0;
111343181Sdim}
112343181Sdim
113343181Sdimuint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
114343181Sdim                                           uint32_t event_mask,
115343181Sdim                                           HandleBroadcastCallback callback,
116343181Sdim                                           void *callback_user_data) {
117343181Sdim  if (broadcaster) {
118343181Sdim    // Scope for "locker"
119343181Sdim    // Tell the broadcaster to add this object as a listener
120343181Sdim    {
121343181Sdim      std::lock_guard<std::recursive_mutex> broadcasters_guard(
122343181Sdim          m_broadcasters_mutex);
123343181Sdim      Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
124343181Sdim      m_broadcasters.insert(std::make_pair(
125343181Sdim          impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
126343181Sdim    }
127343181Sdim
128343181Sdim    uint32_t acquired_mask =
129343181Sdim        broadcaster->AddListener(this->shared_from_this(), event_mask);
130343181Sdim
131343181Sdim    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
132343181Sdim    if (log != nullptr) {
133343181Sdim      void **pointer = reinterpret_cast<void **>(&callback);
134360784Sdim      LLDB_LOGF(log,
135360784Sdim                "%p Listener::StartListeningForEvents (broadcaster = %p, "
136360784Sdim                "mask = 0x%8.8x, callback = %p, user_data = %p) "
137360784Sdim                "acquired_mask = 0x%8.8x for %s",
138360784Sdim                static_cast<void *>(this), static_cast<void *>(broadcaster),
139360784Sdim                event_mask, *pointer, static_cast<void *>(callback_user_data),
140360784Sdim                acquired_mask, m_name.c_str());
141343181Sdim    }
142343181Sdim
143343181Sdim    return acquired_mask;
144343181Sdim  }
145343181Sdim  return 0;
146343181Sdim}
147343181Sdim
148343181Sdimbool Listener::StopListeningForEvents(Broadcaster *broadcaster,
149343181Sdim                                      uint32_t event_mask) {
150343181Sdim  if (broadcaster) {
151343181Sdim    // Scope for "locker"
152343181Sdim    {
153343181Sdim      std::lock_guard<std::recursive_mutex> broadcasters_guard(
154343181Sdim          m_broadcasters_mutex);
155343181Sdim      m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
156343181Sdim    }
157343181Sdim    // Remove the broadcaster from our set of broadcasters
158343181Sdim    return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
159343181Sdim  }
160343181Sdim
161343181Sdim  return false;
162343181Sdim}
163343181Sdim
164343181Sdim// Called when a Broadcaster is in its destructor. We need to remove all
165343181Sdim// knowledge of this broadcaster and any events that it may have queued up
166343181Sdimvoid Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) {
167343181Sdim  // Scope for "broadcasters_locker"
168343181Sdim  {
169343181Sdim    std::lock_guard<std::recursive_mutex> broadcasters_guard(
170343181Sdim        m_broadcasters_mutex);
171343181Sdim    m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
172343181Sdim  }
173343181Sdim
174343181Sdim  // Scope for "event_locker"
175343181Sdim  {
176343181Sdim    std::lock_guard<std::mutex> events_guard(m_events_mutex);
177343181Sdim    // Remove all events for this broadcaster object.
178343181Sdim    event_collection::iterator pos = m_events.begin();
179343181Sdim    while (pos != m_events.end()) {
180343181Sdim      if ((*pos)->GetBroadcaster() == broadcaster)
181343181Sdim        pos = m_events.erase(pos);
182343181Sdim      else
183343181Sdim        ++pos;
184343181Sdim    }
185343181Sdim  }
186343181Sdim}
187343181Sdim
188343181Sdimvoid Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) {
189343181Sdim  // Just need to remove this broadcast manager from the list of managers:
190343181Sdim  broadcaster_manager_collection::iterator iter,
191343181Sdim      end_iter = m_broadcaster_managers.end();
192343181Sdim  BroadcasterManagerWP manager_wp;
193343181Sdim
194353358Sdim  BroadcasterManagerWPMatcher matcher(std::move(manager_sp));
195343181Sdim  iter = std::find_if<broadcaster_manager_collection::iterator,
196343181Sdim                      BroadcasterManagerWPMatcher>(
197343181Sdim      m_broadcaster_managers.begin(), end_iter, matcher);
198343181Sdim  if (iter != end_iter)
199343181Sdim    m_broadcaster_managers.erase(iter);
200343181Sdim}
201343181Sdim
202343181Sdimvoid Listener::AddEvent(EventSP &event_sp) {
203343181Sdim  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
204343181Sdim  if (log != nullptr)
205360784Sdim    LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})",
206360784Sdim              static_cast<void *>(this), m_name.c_str(),
207360784Sdim              static_cast<void *>(event_sp.get()));
208343181Sdim
209343181Sdim  std::lock_guard<std::mutex> guard(m_events_mutex);
210343181Sdim  m_events.push_back(event_sp);
211343181Sdim  m_events_condition.notify_all();
212343181Sdim}
213343181Sdim
214343181Sdimclass EventBroadcasterMatches {
215343181Sdimpublic:
216343181Sdim  EventBroadcasterMatches(Broadcaster *broadcaster)
217343181Sdim      : m_broadcaster(broadcaster) {}
218343181Sdim
219343181Sdim  bool operator()(const EventSP &event_sp) const {
220343181Sdim    return event_sp->BroadcasterIs(m_broadcaster);
221343181Sdim  }
222343181Sdim
223343181Sdimprivate:
224343181Sdim  Broadcaster *m_broadcaster;
225343181Sdim};
226343181Sdim
227343181Sdimclass EventMatcher {
228343181Sdimpublic:
229343181Sdim  EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names,
230343181Sdim               uint32_t num_broadcaster_names, uint32_t event_type_mask)
231343181Sdim      : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names),
232343181Sdim        m_num_broadcaster_names(num_broadcaster_names),
233343181Sdim        m_event_type_mask(event_type_mask) {}
234343181Sdim
235343181Sdim  bool operator()(const EventSP &event_sp) const {
236343181Sdim    if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
237343181Sdim      return false;
238343181Sdim
239343181Sdim    if (m_broadcaster_names) {
240343181Sdim      bool found_source = false;
241353358Sdim      ConstString event_broadcaster_name =
242343181Sdim          event_sp->GetBroadcaster()->GetBroadcasterName();
243343181Sdim      for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) {
244343181Sdim        if (m_broadcaster_names[i] == event_broadcaster_name) {
245343181Sdim          found_source = true;
246343181Sdim          break;
247343181Sdim        }
248343181Sdim      }
249343181Sdim      if (!found_source)
250343181Sdim        return false;
251343181Sdim    }
252343181Sdim
253343181Sdim    return m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType();
254343181Sdim  }
255343181Sdim
256343181Sdimprivate:
257343181Sdim  Broadcaster *m_broadcaster;
258343181Sdim  const ConstString *m_broadcaster_names;
259343181Sdim  const uint32_t m_num_broadcaster_names;
260343181Sdim  const uint32_t m_event_type_mask;
261343181Sdim};
262343181Sdim
263343181Sdimbool Listener::FindNextEventInternal(
264343181Sdim    std::unique_lock<std::mutex> &lock,
265343181Sdim    Broadcaster *broadcaster,             // nullptr for any broadcaster
266343181Sdim    const ConstString *broadcaster_names, // nullptr for any event
267343181Sdim    uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp,
268343181Sdim    bool remove) {
269343181Sdim  // NOTE: callers of this function must lock m_events_mutex using a
270343181Sdim  // Mutex::Locker
271343181Sdim  // and pass the locker as the first argument. m_events_mutex is no longer
272343181Sdim  // recursive.
273343181Sdim  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
274343181Sdim
275343181Sdim  if (m_events.empty())
276343181Sdim    return false;
277343181Sdim
278343181Sdim  Listener::event_collection::iterator pos = m_events.end();
279343181Sdim
280343181Sdim  if (broadcaster == nullptr && broadcaster_names == nullptr &&
281343181Sdim      event_type_mask == 0) {
282343181Sdim    pos = m_events.begin();
283343181Sdim  } else {
284343181Sdim    pos = std::find_if(m_events.begin(), m_events.end(),
285343181Sdim                       EventMatcher(broadcaster, broadcaster_names,
286343181Sdim                                    num_broadcaster_names, event_type_mask));
287343181Sdim  }
288343181Sdim
289343181Sdim  if (pos != m_events.end()) {
290343181Sdim    event_sp = *pos;
291343181Sdim
292343181Sdim    if (log != nullptr)
293360784Sdim      LLDB_LOGF(log,
294360784Sdim                "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, "
295360784Sdim                "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, "
296360784Sdim                "remove=%i) event %p",
297360784Sdim                static_cast<void *>(this), GetName(),
298360784Sdim                static_cast<void *>(broadcaster),
299360784Sdim                static_cast<const void *>(broadcaster_names),
300360784Sdim                num_broadcaster_names, event_type_mask, remove,
301360784Sdim                static_cast<void *>(event_sp.get()));
302343181Sdim
303343181Sdim    if (remove) {
304343181Sdim      m_events.erase(pos);
305343181Sdim      // Unlock the event queue here.  We've removed this event and are about
306343181Sdim      // to return it so it should be okay to get the next event off the queue
307343181Sdim      // here - and it might be useful to do that in the "DoOnRemoval".
308343181Sdim      lock.unlock();
309343181Sdim      event_sp->DoOnRemoval();
310343181Sdim    }
311343181Sdim    return true;
312343181Sdim  }
313343181Sdim
314343181Sdim  event_sp.reset();
315343181Sdim  return false;
316343181Sdim}
317343181Sdim
318343181SdimEvent *Listener::PeekAtNextEvent() {
319343181Sdim  std::unique_lock<std::mutex> guard(m_events_mutex);
320343181Sdim  EventSP event_sp;
321343181Sdim  if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false))
322343181Sdim    return event_sp.get();
323343181Sdim  return nullptr;
324343181Sdim}
325343181Sdim
326343181SdimEvent *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) {
327343181Sdim  std::unique_lock<std::mutex> guard(m_events_mutex);
328343181Sdim  EventSP event_sp;
329343181Sdim  if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false))
330343181Sdim    return event_sp.get();
331343181Sdim  return nullptr;
332343181Sdim}
333343181Sdim
334343181SdimEvent *
335343181SdimListener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster,
336343181Sdim                                                uint32_t event_type_mask) {
337343181Sdim  std::unique_lock<std::mutex> guard(m_events_mutex);
338343181Sdim  EventSP event_sp;
339343181Sdim  if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask,
340343181Sdim                            event_sp, false))
341343181Sdim    return event_sp.get();
342343181Sdim  return nullptr;
343343181Sdim}
344343181Sdim
345343181Sdimbool Listener::GetEventInternal(
346343181Sdim    const Timeout<std::micro> &timeout,
347343181Sdim    Broadcaster *broadcaster,             // nullptr for any broadcaster
348343181Sdim    const ConstString *broadcaster_names, // nullptr for any event
349343181Sdim    uint32_t num_broadcaster_names, uint32_t event_type_mask,
350343181Sdim    EventSP &event_sp) {
351343181Sdim  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
352343181Sdim  LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name);
353343181Sdim
354343181Sdim  std::unique_lock<std::mutex> lock(m_events_mutex);
355343181Sdim
356343181Sdim  while (true) {
357343181Sdim    if (FindNextEventInternal(lock, broadcaster, broadcaster_names,
358343181Sdim                              num_broadcaster_names, event_type_mask, event_sp,
359343181Sdim                              true)) {
360343181Sdim      return true;
361343181Sdim    } else {
362343181Sdim      std::cv_status result = std::cv_status::no_timeout;
363343181Sdim      if (!timeout)
364343181Sdim        m_events_condition.wait(lock);
365343181Sdim      else
366343181Sdim        result = m_events_condition.wait_for(lock, *timeout);
367343181Sdim
368343181Sdim      if (result == std::cv_status::timeout) {
369343181Sdim        log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
370360784Sdim        LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s",
371360784Sdim                  static_cast<void *>(this), m_name.c_str());
372343181Sdim        return false;
373343181Sdim      } else if (result != std::cv_status::no_timeout) {
374343181Sdim        log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS);
375360784Sdim        LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s",
376360784Sdim                  static_cast<void *>(this), m_name.c_str());
377343181Sdim        return false;
378343181Sdim      }
379343181Sdim    }
380343181Sdim  }
381343181Sdim
382343181Sdim  return false;
383343181Sdim}
384343181Sdim
385343181Sdimbool Listener::GetEventForBroadcasterWithType(
386343181Sdim    Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp,
387343181Sdim    const Timeout<std::micro> &timeout) {
388343181Sdim  return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask,
389343181Sdim                          event_sp);
390343181Sdim}
391343181Sdim
392343181Sdimbool Listener::GetEventForBroadcaster(Broadcaster *broadcaster,
393343181Sdim                                      EventSP &event_sp,
394343181Sdim                                      const Timeout<std::micro> &timeout) {
395343181Sdim  return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp);
396343181Sdim}
397343181Sdim
398343181Sdimbool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
399343181Sdim  return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
400343181Sdim}
401343181Sdim
402343181Sdimsize_t Listener::HandleBroadcastEvent(EventSP &event_sp) {
403343181Sdim  size_t num_handled = 0;
404343181Sdim  std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
405343181Sdim  Broadcaster *broadcaster = event_sp->GetBroadcaster();
406343181Sdim  if (!broadcaster)
407343181Sdim    return 0;
408343181Sdim  broadcaster_collection::iterator pos;
409343181Sdim  broadcaster_collection::iterator end = m_broadcasters.end();
410343181Sdim  Broadcaster::BroadcasterImplSP broadcaster_impl_sp(
411343181Sdim      broadcaster->GetBroadcasterImpl());
412343181Sdim  for (pos = m_broadcasters.find(broadcaster_impl_sp);
413343181Sdim       pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) {
414343181Sdim    BroadcasterInfo info = pos->second;
415343181Sdim    if (event_sp->GetType() & info.event_mask) {
416343181Sdim      if (info.callback != nullptr) {
417343181Sdim        info.callback(event_sp, info.callback_user_data);
418343181Sdim        ++num_handled;
419343181Sdim      }
420343181Sdim    }
421343181Sdim  }
422343181Sdim  return num_handled;
423343181Sdim}
424343181Sdim
425343181Sdimuint32_t
426353358SdimListener::StartListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
427343181Sdim                                     const BroadcastEventSpec &event_spec) {
428343181Sdim  if (!manager_sp)
429343181Sdim    return 0;
430343181Sdim
431343181Sdim  // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
432343181Sdim  // avoid violating the lock hierarchy (manager before broadcasters).
433343181Sdim  std::lock_guard<std::recursive_mutex> manager_guard(
434343181Sdim      manager_sp->m_manager_mutex);
435343181Sdim  std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
436343181Sdim
437343181Sdim  uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(
438343181Sdim      this->shared_from_this(), event_spec);
439343181Sdim  if (bits_acquired) {
440343181Sdim    broadcaster_manager_collection::iterator iter,
441343181Sdim        end_iter = m_broadcaster_managers.end();
442343181Sdim    BroadcasterManagerWP manager_wp(manager_sp);
443343181Sdim    BroadcasterManagerWPMatcher matcher(manager_sp);
444343181Sdim    iter = std::find_if<broadcaster_manager_collection::iterator,
445343181Sdim                        BroadcasterManagerWPMatcher>(
446343181Sdim        m_broadcaster_managers.begin(), end_iter, matcher);
447343181Sdim    if (iter == end_iter)
448343181Sdim      m_broadcaster_managers.push_back(manager_wp);
449343181Sdim  }
450343181Sdim
451343181Sdim  return bits_acquired;
452343181Sdim}
453343181Sdim
454353358Sdimbool Listener::StopListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
455343181Sdim                                         const BroadcastEventSpec &event_spec) {
456343181Sdim  if (!manager_sp)
457343181Sdim    return false;
458343181Sdim
459343181Sdim  std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
460343181Sdim  return manager_sp->UnregisterListenerForEvents(this->shared_from_this(),
461343181Sdim                                                 event_spec);
462343181Sdim}
463343181Sdim
464343181SdimListenerSP Listener::MakeListener(const char *name) {
465343181Sdim  return ListenerSP(new Listener(name));
466343181Sdim}
467