LLDB mainline
Listener.cpp
Go to the documentation of this file.
1//===-- Listener.cpp ------------------------------------------------------===//
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
12#include "lldb/Utility/Event.h"
14
15#include <algorithm>
16#include <memory>
17#include <utility>
18
19using namespace lldb;
20using namespace lldb_private;
21
22namespace {
23class BroadcasterManagerWPMatcher {
24public:
25 BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp)
26 : m_manager_sp(std::move(manager_sp)) {}
27 bool operator()(const BroadcasterManagerWP &input_wp) const {
28 BroadcasterManagerSP input_sp = input_wp.lock();
29 return (input_sp && input_sp == m_manager_sp);
30 }
31
32 BroadcasterManagerSP m_manager_sp;
33};
34} // anonymous namespace
35
36Listener::Listener(const char *name)
37 : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
38 m_events_mutex(), m_is_shadow() {
40 if (log != nullptr)
41 LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this),
42 m_name.c_str());
43}
44
47
48 Clear();
49
50 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
51 __FUNCTION__, m_name.c_str());
52}
53
56 std::lock_guard<std::recursive_mutex> broadcasters_guard(
58 broadcaster_collection::iterator pos, end = m_broadcasters.end();
59 for (pos = m_broadcasters.begin(); pos != end; ++pos) {
60 Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
61 if (broadcaster_sp)
62 broadcaster_sp->RemoveListener(this, pos->second.event_mask);
63 }
64 m_broadcasters.clear();
65
66 std::lock_guard<std::mutex> events_guard(m_events_mutex);
67 m_events.clear();
68 size_t num_managers = m_broadcaster_managers.size();
69
70 for (size_t i = 0; i < num_managers; i++) {
71 BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
72 if (manager_sp)
73 manager_sp->RemoveListener(this);
74 }
75
76 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
77 __FUNCTION__, m_name.c_str());
78}
79
81 uint32_t event_mask) {
82 if (broadcaster) {
83 // Scope for "locker"
84 // Tell the broadcaster to add this object as a listener
85 {
86 std::lock_guard<std::recursive_mutex> broadcasters_guard(
89 m_broadcasters.insert(
90 std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
91 }
92
93 uint32_t acquired_mask =
94 broadcaster->AddListener(this->shared_from_this(), event_mask);
95
97 if (log != nullptr)
98 LLDB_LOGF(log,
99 "%p Listener::StartListeningForEvents (broadcaster = %p, "
100 "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
101 static_cast<void *>(this), static_cast<void *>(broadcaster),
102 event_mask, acquired_mask, m_name.c_str());
103
104 return acquired_mask;
105 }
106 return 0;
107}
108
110 uint32_t event_mask,
111 HandleBroadcastCallback callback,
112 void *callback_user_data) {
113 if (broadcaster) {
114 // Scope for "locker"
115 // Tell the broadcaster to add this object as a listener
116 {
117 std::lock_guard<std::recursive_mutex> broadcasters_guard(
120 m_broadcasters.insert(std::make_pair(
121 impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
122 }
123
124 uint32_t acquired_mask =
125 broadcaster->AddListener(this->shared_from_this(), event_mask);
126
127 Log *log = GetLog(LLDBLog::Events);
128 if (log != nullptr) {
129 void **pointer = reinterpret_cast<void **>(&callback);
130 LLDB_LOGF(log,
131 "%p Listener::StartListeningForEvents (broadcaster = %p, "
132 "mask = 0x%8.8x, callback = %p, user_data = %p) "
133 "acquired_mask = 0x%8.8x for %s",
134 static_cast<void *>(this), static_cast<void *>(broadcaster),
135 event_mask, *pointer, static_cast<void *>(callback_user_data),
136 acquired_mask, m_name.c_str());
137 }
138
139 return acquired_mask;
140 }
141 return 0;
142}
143
145 uint32_t event_mask) {
146 if (broadcaster) {
147 // Scope for "locker"
148 {
149 std::lock_guard<std::recursive_mutex> broadcasters_guard(
151 m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
152 }
153 // Remove the broadcaster from our set of broadcasters
154 return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
155 }
156
157 return false;
158}
159
160// Called when a Broadcaster is in its destructor. We need to remove all
161// knowledge of this broadcaster and any events that it may have queued up
163 // Scope for "broadcasters_locker"
164 {
165 std::lock_guard<std::recursive_mutex> broadcasters_guard(
167 m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
168 }
169
170 // Scope for "event_locker"
171 {
172 std::lock_guard<std::mutex> events_guard(m_events_mutex);
173 // Remove all events for this broadcaster object.
174 event_collection::iterator pos = m_events.begin();
175 while (pos != m_events.end()) {
176 if ((*pos)->GetBroadcaster() == broadcaster)
177 pos = m_events.erase(pos);
178 else
179 ++pos;
180 }
181 }
182}
183
184void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) {
185 // Just need to remove this broadcast manager from the list of managers:
186 broadcaster_manager_collection::iterator iter,
187 end_iter = m_broadcaster_managers.end();
188 BroadcasterManagerWP manager_wp;
189
190 BroadcasterManagerWPMatcher matcher(std::move(manager_sp));
191 iter = std::find_if<broadcaster_manager_collection::iterator,
192 BroadcasterManagerWPMatcher>(
193 m_broadcaster_managers.begin(), end_iter, matcher);
194 if (iter != end_iter)
195 m_broadcaster_managers.erase(iter);
196}
197
198void Listener::AddEvent(EventSP &event_sp) {
199 Log *log = GetLog(LLDBLog::Events);
200 if (log != nullptr)
201 LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})",
202 static_cast<void *>(this), m_name.c_str(),
203 static_cast<void *>(event_sp.get()));
204
205 std::lock_guard<std::mutex> guard(m_events_mutex);
206 m_events.push_back(event_sp);
207 m_events_condition.notify_all();
208}
209
211public:
213 : m_broadcaster(broadcaster) {}
214
215 bool operator()(const EventSP &event_sp) const {
216 return event_sp->BroadcasterIs(m_broadcaster);
217 }
218
219private:
221};
222
224public:
225 EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names,
226 uint32_t num_broadcaster_names, uint32_t event_type_mask)
227 : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names),
228 m_num_broadcaster_names(num_broadcaster_names),
229 m_event_type_mask(event_type_mask) {}
230
231 bool operator()(const EventSP &event_sp) const {
232 if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster))
233 return false;
234
235 if (m_broadcaster_names) {
236 bool found_source = false;
237 ConstString event_broadcaster_name =
238 event_sp->GetBroadcaster()->GetBroadcasterName();
239 for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) {
240 if (m_broadcaster_names[i] == event_broadcaster_name) {
241 found_source = true;
242 break;
243 }
244 }
245 if (!found_source)
246 return false;
247 }
248
249 return m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType();
250 }
251
252private:
257};
258
260 std::unique_lock<std::mutex> &lock,
261 Broadcaster *broadcaster, // nullptr for any broadcaster
262 const ConstString *broadcaster_names, // nullptr for any event
263 uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp,
264 bool remove) {
265 // NOTE: callers of this function must lock m_events_mutex using a
266 // Mutex::Locker
267 // and pass the locker as the first argument. m_events_mutex is no longer
268 // recursive.
269 Log *log = GetLog(LLDBLog::Events);
270
271 if (m_events.empty())
272 return false;
273
274 Listener::event_collection::iterator pos = m_events.end();
275
276 if (broadcaster == nullptr && broadcaster_names == nullptr &&
277 event_type_mask == 0) {
278 pos = m_events.begin();
279 } else {
280 pos = std::find_if(m_events.begin(), m_events.end(),
281 EventMatcher(broadcaster, broadcaster_names,
282 num_broadcaster_names, event_type_mask));
283 }
284
285 if (pos != m_events.end()) {
286 event_sp = *pos;
287
288 if (log != nullptr)
289 LLDB_LOGF(log,
290 "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, "
291 "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, "
292 "remove=%i) event %p",
293 static_cast<void *>(this), GetName(),
294 static_cast<void *>(broadcaster),
295 static_cast<const void *>(broadcaster_names),
296 num_broadcaster_names, event_type_mask, remove,
297 static_cast<void *>(event_sp.get()));
298
299 if (remove) {
300 m_events.erase(pos);
301 // Unlock the event queue here. We've removed this event and are about
302 // to return it so it should be okay to get the next event off the queue
303 // here - and it might be useful to do that in the "DoOnRemoval".
304 lock.unlock();
305 if (!m_is_shadow)
306 event_sp->DoOnRemoval();
307 }
308 return true;
309 }
310
311 event_sp.reset();
312 return false;
313}
314
316 std::unique_lock<std::mutex> guard(m_events_mutex);
317 EventSP event_sp;
318 if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false))
319 return event_sp.get();
320 return nullptr;
321}
322
324 std::unique_lock<std::mutex> guard(m_events_mutex);
325 EventSP event_sp;
326 if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false))
327 return event_sp.get();
328 return nullptr;
329}
330
331Event *
333 uint32_t event_type_mask) {
334 std::unique_lock<std::mutex> guard(m_events_mutex);
335 EventSP event_sp;
336 if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask,
337 event_sp, false))
338 return event_sp.get();
339 return nullptr;
340}
341
343 const Timeout<std::micro> &timeout,
344 Broadcaster *broadcaster, // nullptr for any broadcaster
345 const ConstString *broadcaster_names, // nullptr for any event
346 uint32_t num_broadcaster_names, uint32_t event_type_mask,
347 EventSP &event_sp) {
348 Log *log = GetLog(LLDBLog::Events);
349 LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name);
350
351 std::unique_lock<std::mutex> lock(m_events_mutex);
352
353 while (true) {
354 if (FindNextEventInternal(lock, broadcaster, broadcaster_names,
355 num_broadcaster_names, event_type_mask, event_sp,
356 true)) {
357 return true;
358 } else {
359 std::cv_status result = std::cv_status::no_timeout;
360 if (!timeout)
361 m_events_condition.wait(lock);
362 else
363 result = m_events_condition.wait_for(lock, *timeout);
364
365 if (result == std::cv_status::timeout) {
366 log = GetLog(LLDBLog::Events);
367 LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s",
368 static_cast<void *>(this), m_name.c_str());
369 return false;
370 } else if (result != std::cv_status::no_timeout) {
371 log = GetLog(LLDBLog::Events);
372 LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s",
373 static_cast<void *>(this), m_name.c_str());
374 return false;
375 }
376 }
377 }
378
379 return false;
380}
381
383 Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp,
384 const Timeout<std::micro> &timeout) {
385 return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask,
386 event_sp);
387}
388
390 EventSP &event_sp,
391 const Timeout<std::micro> &timeout) {
392 return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp);
393}
394
395bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
396 return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp);
397}
398
399size_t Listener::HandleBroadcastEvent(EventSP &event_sp) {
400 size_t num_handled = 0;
401 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
402 Broadcaster *broadcaster = event_sp->GetBroadcaster();
403 if (!broadcaster)
404 return 0;
405 broadcaster_collection::iterator pos;
406 broadcaster_collection::iterator end = m_broadcasters.end();
407 Broadcaster::BroadcasterImplSP broadcaster_impl_sp(
408 broadcaster->GetBroadcasterImpl());
409 for (pos = m_broadcasters.find(broadcaster_impl_sp);
410 pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) {
411 BroadcasterInfo info = pos->second;
412 if (event_sp->GetType() & info.event_mask) {
413 if (info.callback != nullptr) {
414 info.callback(event_sp, info.callback_user_data);
415 ++num_handled;
416 }
417 }
418 }
419 return num_handled;
420}
421
423Listener::StartListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
424 const BroadcastEventSpec &event_spec) {
425 if (!manager_sp)
426 return 0;
427
428 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
429 // avoid violating the lock hierarchy (manager before broadcasters).
430 std::lock_guard<std::recursive_mutex> manager_guard(
431 manager_sp->m_manager_mutex);
432 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
433
434 uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(
435 this->shared_from_this(), event_spec);
436 if (bits_acquired) {
437 broadcaster_manager_collection::iterator iter,
438 end_iter = m_broadcaster_managers.end();
439 BroadcasterManagerWP manager_wp(manager_sp);
440 BroadcasterManagerWPMatcher matcher(manager_sp);
441 iter = std::find_if<broadcaster_manager_collection::iterator,
442 BroadcasterManagerWPMatcher>(
443 m_broadcaster_managers.begin(), end_iter, matcher);
444 if (iter == end_iter)
445 m_broadcaster_managers.push_back(manager_wp);
446 }
447
448 return bits_acquired;
449}
450
451bool Listener::StopListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
452 const BroadcastEventSpec &event_spec) {
453 if (!manager_sp)
454 return false;
455
456 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
457 return manager_sp->UnregisterListenerForEvents(this->shared_from_this(),
458 event_spec);
459}
460
461ListenerSP Listener::MakeListener(const char *name) {
462 return ListenerSP(new Listener(name));
463}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:337
#define LLDB_LOGF(log,...)
Definition: Log.h:344
EventBroadcasterMatches(Broadcaster *broadcaster)
Definition: Listener.cpp:212
bool operator()(const EventSP &event_sp) const
Definition: Listener.cpp:215
Broadcaster * m_broadcaster
Definition: Listener.cpp:220
const ConstString * m_broadcaster_names
Definition: Listener.cpp:254
const uint32_t m_num_broadcaster_names
Definition: Listener.cpp:255
EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names, uint32_t num_broadcaster_names, uint32_t event_type_mask)
Definition: Listener.cpp:225
const uint32_t m_event_type_mask
Definition: Listener.cpp:256
bool operator()(const EventSP &event_sp) const
Definition: Listener.cpp:231
Broadcaster * m_broadcaster
Definition: Listener.cpp:253
lldb::BroadcastEventSpec
Definition: Broadcaster.h:40
An event broadcasting class.
Definition: Broadcaster.h:145
uint32_t AddListener(const lldb::ListenerSP &listener_sp, uint32_t event_mask)
Listen for any events specified by event_mask.
Definition: Broadcaster.h:211
bool RemoveListener(const lldb::ListenerSP &listener_sp, uint32_t event_mask=UINT32_MAX)
Removes a Listener from this broadcasters list and frees the event bits specified by event_mask that ...
Definition: Broadcaster.h:268
std::weak_ptr< BroadcasterImpl > BroadcasterImplWP
Definition: Broadcaster.h:433
BroadcasterImplSP GetBroadcasterImpl()
Definition: Broadcaster.h:435
std::shared_ptr< BroadcasterImpl > BroadcasterImplSP
Definition: Broadcaster.h:432
A uniqued constant string class.
Definition: ConstString.h:39
size_t HandleBroadcastEvent(lldb::EventSP &event_sp)
Definition: Listener.cpp:399
static lldb::ListenerSP MakeListener(const char *name)
Definition: Listener.cpp:461
event_collection m_events
Definition: Listener.h:135
bool GetEventInternal(const Timeout< std::micro > &timeout, Broadcaster *broadcaster, const ConstString *sources, uint32_t num_sources, uint32_t event_type_mask, lldb::EventSP &event_sp)
Definition: Listener.cpp:342
Event * PeekAtNextEventForBroadcaster(Broadcaster *broadcaster)
Definition: Listener.cpp:323
Event * PeekAtNextEvent()
Definition: Listener.cpp:315
uint32_t StartListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask)
Definition: Listener.cpp:80
std::condition_variable m_events_condition
Definition: Listener.h:137
uint32_t StartListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec)
Definition: Listener.cpp:423
std::recursive_mutex m_broadcasters_mutex
Definition: Listener.h:134
bool FindNextEventInternal(std::unique_lock< std::mutex > &lock, Broadcaster *broadcaster, const ConstString *sources, uint32_t num_sources, uint32_t event_type_mask, lldb::EventSP &event_sp, bool remove)
Definition: Listener.cpp:259
bool StopListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec)
Definition: Listener.cpp:451
std::string m_name
Definition: Listener.h:132
broadcaster_manager_collection m_broadcaster_managers
Definition: Listener.h:138
bool GetEventForBroadcaster(Broadcaster *broadcaster, lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition: Listener.cpp:389
const char * GetName()
Definition: Listener.h:59
Event * PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, uint32_t event_type_mask)
Definition: Listener.cpp:332
bool StopListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask)
Definition: Listener.cpp:144
bool GetEventForBroadcasterWithType(Broadcaster *broadcaster, uint32_t event_type_mask, lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition: Listener.cpp:382
Listener(const char *name)
Definition: Listener.cpp:36
void BroadcasterWillDestruct(Broadcaster *)
Definition: Listener.cpp:162
void BroadcasterManagerWillDestruct(lldb::BroadcasterManagerSP manager_sp)
Definition: Listener.cpp:184
broadcaster_collection m_broadcasters
Definition: Listener.h:133
std::mutex m_events_mutex
Definition: Listener.h:136
void AddEvent(lldb::EventSP &event)
Definition: Listener.cpp:198
bool GetEvent(lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition: Listener.cpp:395
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:309
Definition: SBAddress.h:15
HandleBroadcastCallback callback
Definition: Listener.h:108