1 //===-- Listener.cpp ------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/Listener.h"
10 #include "lldb/Utility/Broadcaster.h"
11 #include "lldb/Utility/Event.h"
12 #include "lldb/Utility/LLDBLog.h"
19 using namespace lldb_private
;
21 Listener::Listener(const char *name
) : m_name(name
) {
22 LLDB_LOGF(GetLog(LLDBLog::Object
), "%p Listener::Listener('%s')",
23 static_cast<void *>(this), m_name
.c_str());
26 Listener::~Listener() {
27 // Don't call Clear() from here as that can cause races. See #96750.
29 LLDB_LOGF(GetLog(LLDBLog::Object
), "%p Listener::%s('%s')",
30 static_cast<void *>(this), __FUNCTION__
, m_name
.c_str());
33 void Listener::Clear() {
34 Log
*log
= GetLog(LLDBLog::Object
);
35 std::lock_guard
<std::mutex
> broadcasters_guard(m_broadcasters_mutex
);
36 broadcaster_collection::iterator pos
, end
= m_broadcasters
.end();
37 for (pos
= m_broadcasters
.begin(); pos
!= end
; ++pos
) {
38 Broadcaster::BroadcasterImplSP
broadcaster_sp(pos
->first
.lock());
40 broadcaster_sp
->RemoveListener(this, pos
->second
.event_mask
);
42 m_broadcasters
.clear();
44 std::lock_guard
<std::mutex
> events_guard(m_events_mutex
);
46 size_t num_managers
= m_broadcaster_managers
.size();
48 for (size_t i
= 0; i
< num_managers
; i
++) {
49 BroadcasterManagerSP
manager_sp(m_broadcaster_managers
[i
].lock());
51 manager_sp
->RemoveListener(this);
54 LLDB_LOGF(log
, "%p Listener::%s('%s')", static_cast<void *>(this),
55 __FUNCTION__
, m_name
.c_str());
58 uint32_t Listener::StartListeningForEvents(Broadcaster
*broadcaster
,
59 uint32_t event_mask
) {
62 // Tell the broadcaster to add this object as a listener
64 std::lock_guard
<std::mutex
> broadcasters_guard(m_broadcasters_mutex
);
65 Broadcaster::BroadcasterImplWP
impl_wp(broadcaster
->GetBroadcasterImpl());
66 m_broadcasters
.insert(
67 std::make_pair(impl_wp
, BroadcasterInfo(event_mask
)));
70 uint32_t acquired_mask
=
71 broadcaster
->AddListener(this->shared_from_this(), event_mask
);
73 Log
*log
= GetLog(LLDBLog::Events
);
76 "%p Listener::StartListeningForEvents (broadcaster = %p, "
77 "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
78 static_cast<void *>(this), static_cast<void *>(broadcaster
),
79 event_mask
, acquired_mask
, m_name
.c_str());
86 uint32_t Listener::StartListeningForEvents(Broadcaster
*broadcaster
,
88 HandleBroadcastCallback callback
,
89 void *callback_user_data
) {
92 // Tell the broadcaster to add this object as a listener
94 std::lock_guard
<std::mutex
> broadcasters_guard(m_broadcasters_mutex
);
95 Broadcaster::BroadcasterImplWP
impl_wp(broadcaster
->GetBroadcasterImpl());
96 m_broadcasters
.insert(std::make_pair(
97 impl_wp
, BroadcasterInfo(event_mask
, callback
, callback_user_data
)));
100 uint32_t acquired_mask
=
101 broadcaster
->AddListener(this->shared_from_this(), event_mask
);
103 Log
*log
= GetLog(LLDBLog::Events
);
104 if (log
!= nullptr) {
105 void **pointer
= reinterpret_cast<void **>(&callback
);
107 "%p Listener::StartListeningForEvents (broadcaster = %p, "
108 "mask = 0x%8.8x, callback = %p, user_data = %p) "
109 "acquired_mask = 0x%8.8x for %s",
110 static_cast<void *>(this), static_cast<void *>(broadcaster
),
111 event_mask
, *pointer
, static_cast<void *>(callback_user_data
),
112 acquired_mask
, m_name
.c_str());
115 return acquired_mask
;
120 bool Listener::StopListeningForEvents(Broadcaster
*broadcaster
,
121 uint32_t event_mask
) {
123 // Scope for "locker"
125 std::lock_guard
<std::mutex
> broadcasters_guard(m_broadcasters_mutex
);
126 m_broadcasters
.erase(broadcaster
->GetBroadcasterImpl());
128 // Remove the broadcaster from our set of broadcasters
129 return broadcaster
->RemoveListener(this->shared_from_this(), event_mask
);
135 // Called when a Broadcaster is in its destructor. We need to remove all
136 // knowledge of this broadcaster and any events that it may have queued up
137 void Listener::BroadcasterWillDestruct(Broadcaster
*broadcaster
) {
138 // Scope for "broadcasters_locker"
140 std::lock_guard
<std::mutex
> broadcasters_guard(m_broadcasters_mutex
);
141 m_broadcasters
.erase(broadcaster
->GetBroadcasterImpl());
144 // Scope for "event_locker"
146 std::lock_guard
<std::mutex
> events_guard(m_events_mutex
);
147 // Remove all events for this broadcaster object.
148 event_collection::iterator pos
= m_events
.begin();
149 while (pos
!= m_events
.end()) {
150 if ((*pos
)->GetBroadcaster() == broadcaster
)
151 pos
= m_events
.erase(pos
);
158 void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp
) {
159 const auto manager_matcher
=
160 [&manager_sp
](const BroadcasterManagerWP
&input_wp
) -> bool {
161 BroadcasterManagerSP input_sp
= input_wp
.lock();
162 return (input_sp
&& input_sp
== manager_sp
);
164 llvm::erase_if(m_broadcaster_managers
, manager_matcher
);
167 void Listener::AddEvent(EventSP
&event_sp
) {
168 Log
*log
= GetLog(LLDBLog::Events
);
170 LLDB_LOGF(log
, "%p Listener('%s')::AddEvent (event_sp = {%p})",
171 static_cast<void *>(this), m_name
.c_str(),
172 static_cast<void *>(event_sp
.get()));
174 std::lock_guard
<std::mutex
> guard(m_events_mutex
);
175 m_events
.push_back(event_sp
);
176 m_events_condition
.notify_all();
179 bool Listener::FindNextEventInternal(
180 std::unique_lock
<std::mutex
> &lock
,
181 Broadcaster
*broadcaster
, // nullptr for any broadcaster
182 uint32_t event_type_mask
, EventSP
&event_sp
, bool remove
) {
183 // NOTE: callers of this function must lock m_events_mutex using a
185 // and pass the locker as the first argument. m_events_mutex is no longer
187 Log
*log
= GetLog(LLDBLog::Events
);
189 if (m_events
.empty())
192 const auto event_matcher
=
193 [broadcaster
, event_type_mask
](const EventSP
&event_sp
) -> bool {
194 if (broadcaster
&& !event_sp
->BroadcasterIs(broadcaster
))
196 return event_type_mask
== 0 || event_type_mask
& event_sp
->GetType();
198 Listener::event_collection::iterator pos
= m_events
.end();
200 if (broadcaster
== nullptr && event_type_mask
== 0)
201 pos
= m_events
.begin();
203 pos
= llvm::find_if(m_events
, event_matcher
);
205 if (pos
!= m_events
.end()) {
210 "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, "
211 "event_type_mask=0x%8.8x, "
212 "remove=%i) event %p",
213 static_cast<void *>(this), GetName(),
214 static_cast<void *>(broadcaster
), event_type_mask
, remove
,
215 static_cast<void *>(event_sp
.get()));
219 // Unlock the event queue here. We've removed this event and are about
220 // to return it so it should be okay to get the next event off the queue
221 // here - and it might be useful to do that in the "DoOnRemoval".
223 event_sp
->DoOnRemoval();
232 Event
*Listener::PeekAtNextEvent() {
233 std::unique_lock
<std::mutex
> guard(m_events_mutex
);
235 if (FindNextEventInternal(guard
, nullptr, 0, event_sp
, false))
236 return event_sp
.get();
240 Event
*Listener::PeekAtNextEventForBroadcaster(Broadcaster
*broadcaster
) {
241 std::unique_lock
<std::mutex
> guard(m_events_mutex
);
243 if (FindNextEventInternal(guard
, broadcaster
, 0, event_sp
, false))
244 return event_sp
.get();
249 Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster
*broadcaster
,
250 uint32_t event_type_mask
) {
251 std::unique_lock
<std::mutex
> guard(m_events_mutex
);
253 if (FindNextEventInternal(guard
, broadcaster
, event_type_mask
, event_sp
,
255 return event_sp
.get();
259 bool Listener::GetEventInternal(
260 const Timeout
<std::micro
> &timeout
,
261 Broadcaster
*broadcaster
, // nullptr for any broadcaster
262 uint32_t event_type_mask
, EventSP
&event_sp
) {
263 Log
*log
= GetLog(LLDBLog::Events
);
264 LLDB_LOG(log
, "this = {0}, timeout = {1} for {2}", this, timeout
, m_name
);
266 std::unique_lock
<std::mutex
> lock(m_events_mutex
);
269 if (FindNextEventInternal(lock
, broadcaster
, event_type_mask
, event_sp
,
273 std::cv_status result
= std::cv_status::no_timeout
;
275 m_events_condition
.wait(lock
);
277 result
= m_events_condition
.wait_for(lock
, *timeout
);
279 if (result
== std::cv_status::timeout
) {
280 log
= GetLog(LLDBLog::Events
);
281 LLDB_LOGF(log
, "%p Listener::GetEventInternal() timed out for %s",
282 static_cast<void *>(this), m_name
.c_str());
284 } else if (result
!= std::cv_status::no_timeout
) {
285 log
= GetLog(LLDBLog::Events
);
286 LLDB_LOGF(log
, "%p Listener::GetEventInternal() unknown error for %s",
287 static_cast<void *>(this), m_name
.c_str());
296 bool Listener::GetEventForBroadcasterWithType(
297 Broadcaster
*broadcaster
, uint32_t event_type_mask
, EventSP
&event_sp
,
298 const Timeout
<std::micro
> &timeout
) {
299 return GetEventInternal(timeout
, broadcaster
, event_type_mask
, event_sp
);
302 bool Listener::GetEventForBroadcaster(Broadcaster
*broadcaster
,
304 const Timeout
<std::micro
> &timeout
) {
305 return GetEventInternal(timeout
, broadcaster
, 0, event_sp
);
308 bool Listener::GetEvent(EventSP
&event_sp
, const Timeout
<std::micro
> &timeout
) {
309 return GetEventInternal(timeout
, nullptr, 0, event_sp
);
312 size_t Listener::HandleBroadcastEvent(EventSP
&event_sp
) {
313 size_t num_handled
= 0;
314 std::lock_guard
<std::mutex
> guard(m_broadcasters_mutex
);
315 Broadcaster
*broadcaster
= event_sp
->GetBroadcaster();
318 broadcaster_collection::iterator pos
;
319 broadcaster_collection::iterator end
= m_broadcasters
.end();
320 Broadcaster::BroadcasterImplSP
broadcaster_impl_sp(
321 broadcaster
->GetBroadcasterImpl());
322 for (pos
= m_broadcasters
.find(broadcaster_impl_sp
);
323 pos
!= end
&& pos
->first
.lock() == broadcaster_impl_sp
; ++pos
) {
324 BroadcasterInfo info
= pos
->second
;
325 if (event_sp
->GetType() & info
.event_mask
) {
326 if (info
.callback
!= nullptr) {
327 info
.callback(event_sp
, info
.callback_user_data
);
336 Listener::StartListeningForEventSpec(const BroadcasterManagerSP
&manager_sp
,
337 const BroadcastEventSpec
&event_spec
) {
341 const auto manager_matcher
=
342 [&manager_sp
](const BroadcasterManagerWP
&input_wp
) -> bool {
343 BroadcasterManagerSP input_sp
= input_wp
.lock();
344 return (input_sp
&& input_sp
== manager_sp
);
346 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
347 // avoid violating the lock hierarchy (manager before broadcasters).
348 std::lock_guard
<std::mutex
> manager_guard(manager_sp
->m_manager_mutex
);
349 std::lock_guard
<std::mutex
> guard(m_broadcasters_mutex
);
351 uint32_t bits_acquired
= manager_sp
->RegisterListenerForEventsNoLock(
352 this->shared_from_this(), event_spec
);
354 BroadcasterManagerWP
manager_wp(manager_sp
);
355 auto iter
= llvm::find_if(m_broadcaster_managers
, manager_matcher
);
356 if (iter
== m_broadcaster_managers
.end())
357 m_broadcaster_managers
.push_back(manager_wp
);
360 return bits_acquired
;
363 bool Listener::StopListeningForEventSpec(const BroadcasterManagerSP
&manager_sp
,
364 const BroadcastEventSpec
&event_spec
) {
368 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
369 // avoid violating the lock hierarchy (manager before broadcasters).
370 std::lock_guard
<std::mutex
> manager_guard(manager_sp
->m_manager_mutex
);
371 std::lock_guard
<std::mutex
> guard(m_broadcasters_mutex
);
372 return manager_sp
->UnregisterListenerForEventsNoLock(this->shared_from_this(),
376 ListenerSP
Listener::MakeListener(const char *name
) {
377 return ListenerSP(new Listener(name
));