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
)
22 : m_name(name
), m_broadcasters(), m_broadcasters_mutex(), m_events(),
23 m_events_mutex(), m_is_shadow() {
24 Log
*log
= GetLog(LLDBLog::Object
);
26 LLDB_LOGF(log
, "%p Listener::Listener('%s')", static_cast<void *>(this),
30 Listener::~Listener() {
31 Log
*log
= GetLog(LLDBLog::Object
);
35 LLDB_LOGF(log
, "%p Listener::%s('%s')", static_cast<void *>(this),
36 __FUNCTION__
, m_name
.c_str());
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());
47 broadcaster_sp
->RemoveListener(this, pos
->second
.event_mask
);
49 m_broadcasters
.clear();
51 std::lock_guard
<std::mutex
> events_guard(m_events_mutex
);
53 size_t num_managers
= m_broadcaster_managers
.size();
55 for (size_t i
= 0; i
< num_managers
; i
++) {
56 BroadcasterManagerSP
manager_sp(m_broadcaster_managers
[i
].lock());
58 manager_sp
->RemoveListener(this);
61 LLDB_LOGF(log
, "%p Listener::%s('%s')", static_cast<void *>(this),
62 __FUNCTION__
, m_name
.c_str());
65 uint32_t Listener::StartListeningForEvents(Broadcaster
*broadcaster
,
66 uint32_t event_mask
) {
69 // Tell the broadcaster to add this object as a listener
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
)));
78 uint32_t acquired_mask
=
79 broadcaster
->AddListener(this->shared_from_this(), event_mask
);
81 Log
*log
= GetLog(LLDBLog::Events
);
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());
94 uint32_t Listener::StartListeningForEvents(Broadcaster
*broadcaster
,
96 HandleBroadcastCallback callback
,
97 void *callback_user_data
) {
100 // Tell the broadcaster to add this object as a listener
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
)));
109 uint32_t acquired_mask
=
110 broadcaster
->AddListener(this->shared_from_this(), event_mask
);
112 Log
*log
= GetLog(LLDBLog::Events
);
113 if (log
!= nullptr) {
114 void **pointer
= reinterpret_cast<void **>(&callback
);
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());
124 return acquired_mask
;
129 bool Listener::StopListeningForEvents(Broadcaster
*broadcaster
,
130 uint32_t event_mask
) {
132 // Scope for "locker"
134 std::lock_guard
<std::recursive_mutex
> broadcasters_guard(
135 m_broadcasters_mutex
);
136 m_broadcasters
.erase(broadcaster
->GetBroadcasterImpl());
138 // Remove the broadcaster from our set of broadcasters
139 return broadcaster
->RemoveListener(this->shared_from_this(), event_mask
);
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"
150 std::lock_guard
<std::recursive_mutex
> broadcasters_guard(
151 m_broadcasters_mutex
);
152 m_broadcasters
.erase(broadcaster
->GetBroadcasterImpl());
155 // Scope for "event_locker"
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
);
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
);
175 llvm::erase_if(m_broadcaster_managers
, manager_matcher
);
178 void Listener::AddEvent(EventSP
&event_sp
) {
179 Log
*log
= GetLog(LLDBLog::Events
);
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()));
185 std::lock_guard
<std::mutex
> guard(m_events_mutex
);
186 m_events
.push_back(event_sp
);
187 m_events_condition
.notify_all();
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
196 // and pass the locker as the first argument. m_events_mutex is no longer
198 Log
*log
= GetLog(LLDBLog::Events
);
200 if (m_events
.empty())
203 const auto event_matcher
=
204 [broadcaster
, event_type_mask
](const EventSP
&event_sp
) -> bool {
205 if (broadcaster
&& !event_sp
->BroadcasterIs(broadcaster
))
207 return event_type_mask
== 0 || event_type_mask
& event_sp
->GetType();
209 Listener::event_collection::iterator pos
= m_events
.end();
211 if (broadcaster
== nullptr && event_type_mask
== 0)
212 pos
= m_events
.begin();
214 pos
= llvm::find_if(m_events
, event_matcher
);
216 if (pos
!= m_events
.end()) {
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()));
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".
234 event_sp
->DoOnRemoval();
243 Event
*Listener::PeekAtNextEvent() {
244 std::unique_lock
<std::mutex
> guard(m_events_mutex
);
246 if (FindNextEventInternal(guard
, nullptr, 0, event_sp
, false))
247 return event_sp
.get();
251 Event
*Listener::PeekAtNextEventForBroadcaster(Broadcaster
*broadcaster
) {
252 std::unique_lock
<std::mutex
> guard(m_events_mutex
);
254 if (FindNextEventInternal(guard
, broadcaster
, 0, event_sp
, false))
255 return event_sp
.get();
260 Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster
*broadcaster
,
261 uint32_t event_type_mask
) {
262 std::unique_lock
<std::mutex
> guard(m_events_mutex
);
264 if (FindNextEventInternal(guard
, broadcaster
, event_type_mask
, event_sp
,
266 return event_sp
.get();
270 bool Listener::GetEventInternal(
271 const Timeout
<std::micro
> &timeout
,
272 Broadcaster
*broadcaster
, // nullptr for any broadcaster
273 uint32_t event_type_mask
, EventSP
&event_sp
) {
274 Log
*log
= GetLog(LLDBLog::Events
);
275 LLDB_LOG(log
, "this = {0}, timeout = {1} for {2}", this, timeout
, m_name
);
277 std::unique_lock
<std::mutex
> lock(m_events_mutex
);
280 if (FindNextEventInternal(lock
, broadcaster
, event_type_mask
, event_sp
,
284 std::cv_status result
= std::cv_status::no_timeout
;
286 m_events_condition
.wait(lock
);
288 result
= m_events_condition
.wait_for(lock
, *timeout
);
290 if (result
== std::cv_status::timeout
) {
291 log
= GetLog(LLDBLog::Events
);
292 LLDB_LOGF(log
, "%p Listener::GetEventInternal() timed out for %s",
293 static_cast<void *>(this), m_name
.c_str());
295 } else if (result
!= std::cv_status::no_timeout
) {
296 log
= GetLog(LLDBLog::Events
);
297 LLDB_LOGF(log
, "%p Listener::GetEventInternal() unknown error for %s",
298 static_cast<void *>(this), m_name
.c_str());
307 bool Listener::GetEventForBroadcasterWithType(
308 Broadcaster
*broadcaster
, uint32_t event_type_mask
, EventSP
&event_sp
,
309 const Timeout
<std::micro
> &timeout
) {
310 return GetEventInternal(timeout
, broadcaster
, event_type_mask
, event_sp
);
313 bool Listener::GetEventForBroadcaster(Broadcaster
*broadcaster
,
315 const Timeout
<std::micro
> &timeout
) {
316 return GetEventInternal(timeout
, broadcaster
, 0, event_sp
);
319 bool Listener::GetEvent(EventSP
&event_sp
, const Timeout
<std::micro
> &timeout
) {
320 return GetEventInternal(timeout
, nullptr, 0, event_sp
);
323 size_t Listener::HandleBroadcastEvent(EventSP
&event_sp
) {
324 size_t num_handled
= 0;
325 std::lock_guard
<std::recursive_mutex
> guard(m_broadcasters_mutex
);
326 Broadcaster
*broadcaster
= event_sp
->GetBroadcaster();
329 broadcaster_collection::iterator pos
;
330 broadcaster_collection::iterator end
= m_broadcasters
.end();
331 Broadcaster::BroadcasterImplSP
broadcaster_impl_sp(
332 broadcaster
->GetBroadcasterImpl());
333 for (pos
= m_broadcasters
.find(broadcaster_impl_sp
);
334 pos
!= end
&& pos
->first
.lock() == broadcaster_impl_sp
; ++pos
) {
335 BroadcasterInfo info
= pos
->second
;
336 if (event_sp
->GetType() & info
.event_mask
) {
337 if (info
.callback
!= nullptr) {
338 info
.callback(event_sp
, info
.callback_user_data
);
347 Listener::StartListeningForEventSpec(const BroadcasterManagerSP
&manager_sp
,
348 const BroadcastEventSpec
&event_spec
) {
352 const auto manager_matcher
=
353 [&manager_sp
](const BroadcasterManagerWP
&input_wp
) -> bool {
354 BroadcasterManagerSP input_sp
= input_wp
.lock();
355 return (input_sp
&& input_sp
== manager_sp
);
357 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
358 // avoid violating the lock hierarchy (manager before broadcasters).
359 std::lock_guard
<std::recursive_mutex
> manager_guard(
360 manager_sp
->m_manager_mutex
);
361 std::lock_guard
<std::recursive_mutex
> guard(m_broadcasters_mutex
);
363 uint32_t bits_acquired
= manager_sp
->RegisterListenerForEvents(
364 this->shared_from_this(), event_spec
);
366 BroadcasterManagerWP
manager_wp(manager_sp
);
367 auto iter
= llvm::find_if(m_broadcaster_managers
, manager_matcher
);
368 if (iter
== m_broadcaster_managers
.end())
369 m_broadcaster_managers
.push_back(manager_wp
);
372 return bits_acquired
;
375 bool Listener::StopListeningForEventSpec(const BroadcasterManagerSP
&manager_sp
,
376 const BroadcastEventSpec
&event_spec
) {
380 std::lock_guard
<std::recursive_mutex
> guard(m_broadcasters_mutex
);
381 return manager_sp
->UnregisterListenerForEvents(this->shared_from_this(),
385 ListenerSP
Listener::MakeListener(const char *name
) {
386 return ListenerSP(new Listener(name
));