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
11#include "lldb/Utility/Event.h"
13
14#include <algorithm>
15#include <memory>
16#include <utility>
17
18using namespace lldb;
19using namespace lldb_private;
20
21Listener::Listener(const char *name)
22 : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
23 m_events_mutex(), m_is_shadow() {
25 if (log != nullptr)
26 LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this),
27 m_name.c_str());
28}
29
32
33 Clear();
34
35 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
36 __FUNCTION__, m_name.c_str());
37}
38
41 std::lock_guard<std::recursive_mutex> broadcasters_guard(
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());
46 if (broadcaster_sp)
47 broadcaster_sp->RemoveListener(this, pos->second.event_mask);
48 }
49 m_broadcasters.clear();
50
51 std::lock_guard<std::mutex> events_guard(m_events_mutex);
52 m_events.clear();
53 size_t num_managers = m_broadcaster_managers.size();
54
55 for (size_t i = 0; i < num_managers; i++) {
56 BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
57 if (manager_sp)
58 manager_sp->RemoveListener(this);
59 }
60
61 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
62 __FUNCTION__, m_name.c_str());
63}
64
66 uint32_t event_mask) {
67 if (broadcaster) {
68 // Scope for "locker"
69 // Tell the broadcaster to add this object as a listener
70 {
71 std::lock_guard<std::recursive_mutex> broadcasters_guard(
74 m_broadcasters.insert(
75 std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
76 }
77
78 uint32_t acquired_mask =
79 broadcaster->AddListener(this->shared_from_this(), event_mask);
80
82 if (log != nullptr)
83 LLDB_LOGF(log,
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());
88
89 return acquired_mask;
90 }
91 return 0;
92}
93
95 uint32_t event_mask,
96 HandleBroadcastCallback callback,
97 void *callback_user_data) {
98 if (broadcaster) {
99 // Scope for "locker"
100 // Tell the broadcaster to add this object as a listener
101 {
102 std::lock_guard<std::recursive_mutex> broadcasters_guard(
105 m_broadcasters.insert(std::make_pair(
106 impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
107 }
108
109 uint32_t acquired_mask =
110 broadcaster->AddListener(this->shared_from_this(), event_mask);
111
112 Log *log = GetLog(LLDBLog::Events);
113 if (log != nullptr) {
114 void **pointer = reinterpret_cast<void **>(&callback);
115 LLDB_LOGF(log,
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());
122 }
123
124 return acquired_mask;
125 }
126 return 0;
127}
128
130 uint32_t event_mask) {
131 if (broadcaster) {
132 // Scope for "locker"
133 {
134 std::lock_guard<std::recursive_mutex> broadcasters_guard(
136 m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
137 }
138 // Remove the broadcaster from our set of broadcasters
139 return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
140 }
141
142 return false;
143}
144
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
148 // Scope for "broadcasters_locker"
149 {
150 std::lock_guard<std::recursive_mutex> broadcasters_guard(
152 m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
153 }
154
155 // Scope for "event_locker"
156 {
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);
163 else
164 ++pos;
165 }
166 }
167}
168
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);
174 };
175 llvm::erase_if(m_broadcaster_managers, manager_matcher);
176}
177
179 Log *log = GetLog(LLDBLog::Events);
180 if (log != nullptr)
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()));
184
185 std::lock_guard<std::mutex> guard(m_events_mutex);
186 m_events.push_back(event_sp);
187 m_events_condition.notify_all();
188}
189
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
195 // Mutex::Locker
196 // and pass the locker as the first argument. m_events_mutex is no longer
197 // recursive.
198 Log *log = GetLog(LLDBLog::Events);
199
200 if (m_events.empty())
201 return false;
202
203 const auto event_matcher =
204 [broadcaster, event_type_mask](const EventSP &event_sp) -> bool {
205 if (broadcaster && !event_sp->BroadcasterIs(broadcaster))
206 return false;
207 return event_type_mask == 0 || event_type_mask & event_sp->GetType();
208 };
209 Listener::event_collection::iterator pos = m_events.end();
210
211 if (broadcaster == nullptr && event_type_mask == 0)
212 pos = m_events.begin();
213 else
214 pos = llvm::find_if(m_events, event_matcher);
215
216 if (pos != m_events.end()) {
217 event_sp = *pos;
218
219 if (log != nullptr)
220 LLDB_LOGF(log,
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()));
227
228 if (remove) {
229 m_events.erase(pos);
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".
233 lock.unlock();
234 event_sp->DoOnRemoval();
235 }
236 return true;
237 }
238
239 event_sp.reset();
240 return false;
241}
242
244 std::unique_lock<std::mutex> guard(m_events_mutex);
245 EventSP event_sp;
246 if (FindNextEventInternal(guard, nullptr, 0, event_sp, false))
247 return event_sp.get();
248 return nullptr;
249}
250
252 std::unique_lock<std::mutex> guard(m_events_mutex);
253 EventSP event_sp;
254 if (FindNextEventInternal(guard, broadcaster, 0, event_sp, false))
255 return event_sp.get();
256 return nullptr;
257}
258
259Event *
261 uint32_t event_type_mask) {
262 std::unique_lock<std::mutex> guard(m_events_mutex);
263 EventSP event_sp;
264 if (FindNextEventInternal(guard, broadcaster, event_type_mask, event_sp,
265 false))
266 return event_sp.get();
267 return nullptr;
268}
269
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);
276
277 std::unique_lock<std::mutex> lock(m_events_mutex);
278
279 while (true) {
280 if (FindNextEventInternal(lock, broadcaster, event_type_mask, event_sp,
281 true)) {
282 return true;
283 } else {
284 std::cv_status result = std::cv_status::no_timeout;
285 if (!timeout)
286 m_events_condition.wait(lock);
287 else
288 result = m_events_condition.wait_for(lock, *timeout);
289
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());
294 return false;
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());
299 return false;
300 }
301 }
302 }
303
304 return false;
305}
306
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);
311}
312
314 EventSP &event_sp,
315 const Timeout<std::micro> &timeout) {
316 return GetEventInternal(timeout, broadcaster, 0, event_sp);
317}
318
319bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
320 return GetEventInternal(timeout, nullptr, 0, event_sp);
321}
322
324 size_t num_handled = 0;
325 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
326 Broadcaster *broadcaster = event_sp->GetBroadcaster();
327 if (!broadcaster)
328 return 0;
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);
339 ++num_handled;
340 }
341 }
342 }
343 return num_handled;
344}
345
346uint32_t
348 const BroadcastEventSpec &event_spec) {
349 if (!manager_sp)
350 return 0;
351
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);
356 };
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);
362
363 uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(
364 this->shared_from_this(), event_spec);
365 if (bits_acquired) {
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);
370 }
371
372 return bits_acquired;
373}
374
376 const BroadcastEventSpec &event_spec) {
377 if (!manager_sp)
378 return false;
379
380 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
381 return manager_sp->UnregisterListenerForEvents(this->shared_from_this(),
382 event_spec);
383}
384
386 return ListenerSP(new Listener(name));
387}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:342
#define LLDB_LOGF(log,...)
Definition: Log.h:349
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:212
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:270
std::weak_ptr< BroadcasterImpl > BroadcasterImplWP
Definition: Broadcaster.h:464
BroadcasterImplSP GetBroadcasterImpl()
Definition: Broadcaster.h:466
std::shared_ptr< BroadcasterImpl > BroadcasterImplSP
Definition: Broadcaster.h:463
size_t HandleBroadcastEvent(lldb::EventSP &event_sp)
Definition: Listener.cpp:323
static lldb::ListenerSP MakeListener(const char *name)
Definition: Listener.cpp:385
event_collection m_events
Definition: Listener.h:131
Event * PeekAtNextEventForBroadcaster(Broadcaster *broadcaster)
Definition: Listener.cpp:251
Event * PeekAtNextEvent()
Definition: Listener.cpp:243
uint32_t StartListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask)
Definition: Listener.cpp:65
std::condition_variable m_events_condition
Definition: Listener.h:133
uint32_t StartListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec)
Definition: Listener.cpp:347
std::recursive_mutex m_broadcasters_mutex
Definition: Listener.h:130
bool StopListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec)
Definition: Listener.cpp:375
std::string m_name
Definition: Listener.h:128
broadcaster_manager_collection m_broadcaster_managers
Definition: Listener.h:134
bool GetEventForBroadcaster(Broadcaster *broadcaster, lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition: Listener.cpp:313
bool FindNextEventInternal(std::unique_lock< std::mutex > &lock, Broadcaster *broadcaster, uint32_t event_type_mask, lldb::EventSP &event_sp, bool remove)
Definition: Listener.cpp:190
const char * GetName()
Definition: Listener.h:58
Event * PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, uint32_t event_type_mask)
Definition: Listener.cpp:260
bool StopListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask)
Definition: Listener.cpp:129
bool GetEventForBroadcasterWithType(Broadcaster *broadcaster, uint32_t event_type_mask, lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition: Listener.cpp:307
Listener(const char *name)
Definition: Listener.cpp:21
void BroadcasterWillDestruct(Broadcaster *)
Definition: Listener.cpp:147
void BroadcasterManagerWillDestruct(lldb::BroadcasterManagerSP manager_sp)
Definition: Listener.cpp:169
broadcaster_collection m_broadcasters
Definition: Listener.h:129
bool GetEventInternal(const Timeout< std::micro > &timeout, Broadcaster *broadcaster, uint32_t event_type_mask, lldb::EventSP &event_sp)
Definition: Listener.cpp:270
std::mutex m_events_mutex
Definition: Listener.h:132
void AddEvent(lldb::EventSP &event)
Definition: Listener.cpp:178
bool GetEvent(lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition: Listener.cpp:319
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:314
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::BroadcasterManager > BroadcasterManagerSP
Definition: lldb-forward.h:322
std::shared_ptr< lldb_private::Event > EventSP
Definition: lldb-forward.h:337
std::shared_ptr< lldb_private::Listener > ListenerSP
Definition: lldb-forward.h:360
std::weak_ptr< lldb_private::BroadcasterManager > BroadcasterManagerWP
Definition: lldb-forward.h:323
HandleBroadcastCallback callback
Definition: Listener.h:107