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) : m_name(name) {
22 LLDB_LOGF(GetLog(LLDBLog::Object), "%p Listener::Listener('%s')",
23 static_cast<void *>(this), m_name.c_str());
24}
25
27 // Don't call Clear() from here as that can cause races. See #96750.
28
29 LLDB_LOGF(GetLog(LLDBLog::Object), "%p Listener::%s('%s')",
30 static_cast<void *>(this), __FUNCTION__, m_name.c_str());
31}
32
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());
39 if (broadcaster_sp)
40 broadcaster_sp->RemoveListener(this, pos->second.event_mask);
41 }
42 m_broadcasters.clear();
43
44 std::lock_guard<std::mutex> events_guard(m_events_mutex);
45 m_events.clear();
46 size_t num_managers = m_broadcaster_managers.size();
47
48 for (size_t i = 0; i < num_managers; i++) {
49 BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock());
50 if (manager_sp)
51 manager_sp->RemoveListener(this);
52 }
53
54 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this),
55 __FUNCTION__, m_name.c_str());
56}
57
59 uint32_t event_mask) {
60 if (broadcaster) {
61 // Scope for "locker"
62 // Tell the broadcaster to add this object as a listener
63 {
64 std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
66 m_broadcasters.insert(
67 std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
68 }
69
70 uint32_t acquired_mask =
71 broadcaster->AddListener(this->shared_from_this(), event_mask);
72
74 LLDB_LOGF(log,
75 "%p Listener::StartListeningForEvents (broadcaster = %p, "
76 "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s",
77 static_cast<void *>(this), static_cast<void *>(broadcaster),
78 event_mask, acquired_mask, m_name.c_str());
79
80 return acquired_mask;
81 }
82 return 0;
83}
84
86 uint32_t event_mask,
88 void *callback_user_data) {
89 if (broadcaster) {
90 // Scope for "locker"
91 // Tell the broadcaster to add this object as a listener
92 {
93 std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
95 m_broadcasters.insert(std::make_pair(
96 impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
97 }
98
99 uint32_t acquired_mask =
100 broadcaster->AddListener(this->shared_from_this(), event_mask);
101
102 Log *log = GetLog(LLDBLog::Events);
103 if (log != nullptr) {
104 void **pointer = reinterpret_cast<void **>(&callback);
105 LLDB_LOGF(log,
106 "%p Listener::StartListeningForEvents (broadcaster = %p, "
107 "mask = 0x%8.8x, callback = %p, user_data = %p) "
108 "acquired_mask = 0x%8.8x for %s",
109 static_cast<void *>(this), static_cast<void *>(broadcaster),
110 event_mask, *pointer, static_cast<void *>(callback_user_data),
111 acquired_mask, m_name.c_str());
112 }
113
114 return acquired_mask;
115 }
116 return 0;
117}
118
120 uint32_t event_mask) {
121 if (broadcaster) {
122 // Scope for "locker"
123 {
124 std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
125 m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
126 }
127 // Remove the broadcaster from our set of broadcasters
128 return broadcaster->RemoveListener(this->shared_from_this(), event_mask);
129 }
130
131 return false;
132}
133
134// Called when a Broadcaster is in its destructor. We need to remove all
135// knowledge of this broadcaster and any events that it may have queued up
137 // Scope for "broadcasters_locker"
138 {
139 std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
140 m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
141 }
142
143 // Scope for "event_locker"
144 {
145 std::lock_guard<std::mutex> events_guard(m_events_mutex);
146 // Remove all events for this broadcaster object.
147 event_collection::iterator pos = m_events.begin();
148 while (pos != m_events.end()) {
149 if ((*pos)->GetBroadcaster() == broadcaster)
150 pos = m_events.erase(pos);
151 else
152 ++pos;
153 }
154 }
155}
156
158 const auto manager_matcher =
159 [&manager_sp](const BroadcasterManagerWP &input_wp) -> bool {
160 BroadcasterManagerSP input_sp = input_wp.lock();
161 return (input_sp && input_sp == manager_sp);
162 };
163 llvm::erase_if(m_broadcaster_managers, manager_matcher);
164}
165
167 Log *log = GetLog(LLDBLog::Events);
168 LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})",
169 static_cast<void *>(this), m_name.c_str(),
170 static_cast<void *>(event_sp.get()));
171
172 std::lock_guard<std::mutex> guard(m_events_mutex);
173 m_events.push_back(event_sp);
174 m_events_condition.notify_all();
175}
176
178 std::unique_lock<std::mutex> &lock,
179 Broadcaster *broadcaster, // nullptr for any broadcaster
180 uint32_t event_type_mask, EventSP &event_sp, bool remove) {
181 // NOTE: callers of this function must lock m_events_mutex using a
182 // Mutex::Locker
183 // and pass the locker as the first argument. m_events_mutex is no longer
184 // recursive.
185 Log *log = GetLog(LLDBLog::Events);
186
187 if (m_events.empty())
188 return false;
189
190 const auto event_matcher =
191 [broadcaster, event_type_mask](const EventSP &event_sp) -> bool {
192 if (broadcaster && !event_sp->BroadcasterIs(broadcaster))
193 return false;
194 return event_type_mask == 0 || event_type_mask & event_sp->GetType();
195 };
196 Listener::event_collection::iterator pos = m_events.end();
197
198 if (broadcaster == nullptr && event_type_mask == 0)
199 pos = m_events.begin();
200 else
201 pos = llvm::find_if(m_events, event_matcher);
202
203 if (pos != m_events.end()) {
204 event_sp = *pos;
205
206 LLDB_LOGF(log,
207 "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, "
208 "event_type_mask=0x%8.8x, "
209 "remove=%i) event %p",
210 static_cast<void *>(this), GetName(),
211 static_cast<void *>(broadcaster), event_type_mask, remove,
212 static_cast<void *>(event_sp.get()));
213
214 if (remove) {
215 m_events.erase(pos);
216 // Unlock the event queue here. We've removed this event and are about
217 // to return it so it should be okay to get the next event off the queue
218 // here - and it might be useful to do that in the "DoOnRemoval".
219 lock.unlock();
220 event_sp->DoOnRemoval();
221 }
222 return true;
223 }
224
225 event_sp.reset();
226 return false;
227}
228
230 std::unique_lock<std::mutex> guard(m_events_mutex);
231 EventSP event_sp;
232 if (FindNextEventInternal(guard, nullptr, 0, event_sp, false))
233 return event_sp.get();
234 return nullptr;
235}
236
238 std::unique_lock<std::mutex> guard(m_events_mutex);
239 EventSP event_sp;
240 if (FindNextEventInternal(guard, broadcaster, 0, event_sp, false))
241 return event_sp.get();
242 return nullptr;
243}
244
245Event *
247 uint32_t event_type_mask) {
248 std::unique_lock<std::mutex> guard(m_events_mutex);
249 EventSP event_sp;
250 if (FindNextEventInternal(guard, broadcaster, event_type_mask, event_sp,
251 false))
252 return event_sp.get();
253 return nullptr;
254}
255
257 const Timeout<std::micro> &timeout,
258 Broadcaster *broadcaster, // nullptr for any broadcaster
259 uint32_t event_type_mask, EventSP &event_sp) {
260 Log *log = GetLog(LLDBLog::Events);
261 LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name);
262
263 std::unique_lock<std::mutex> lock(m_events_mutex);
264
265 while (true) {
266 if (FindNextEventInternal(lock, broadcaster, event_type_mask, event_sp,
267 true)) {
268 return true;
269 } else {
270 std::cv_status result = std::cv_status::no_timeout;
271 if (!timeout)
272 m_events_condition.wait(lock);
273 else
274 result = m_events_condition.wait_for(lock, *timeout);
275
276 if (result == std::cv_status::timeout) {
277 log = GetLog(LLDBLog::Events);
278 LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s",
279 static_cast<void *>(this), m_name.c_str());
280 return false;
281 } else if (result != std::cv_status::no_timeout) {
282 log = GetLog(LLDBLog::Events);
283 LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s",
284 static_cast<void *>(this), m_name.c_str());
285 return false;
286 }
287 }
288 }
289
290 return false;
291}
292
294 Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp,
295 const Timeout<std::micro> &timeout) {
296 return GetEventInternal(timeout, broadcaster, event_type_mask, event_sp);
297}
298
300 EventSP &event_sp,
301 const Timeout<std::micro> &timeout) {
302 return GetEventInternal(timeout, broadcaster, 0, event_sp);
303}
304
305bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {
306 return GetEventInternal(timeout, nullptr, 0, event_sp);
307}
308
310 size_t num_handled = 0;
311 std::lock_guard<std::mutex> guard(m_broadcasters_mutex);
312 Broadcaster *broadcaster = event_sp->GetBroadcaster();
313 if (!broadcaster)
314 return 0;
315 broadcaster_collection::iterator pos;
316 broadcaster_collection::iterator end = m_broadcasters.end();
317 Broadcaster::BroadcasterImplSP broadcaster_impl_sp(
318 broadcaster->GetBroadcasterImpl());
319 for (pos = m_broadcasters.find(broadcaster_impl_sp);
320 pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) {
321 BroadcasterInfo info = pos->second;
322 if (event_sp->GetType() & info.event_mask) {
323 if (info.callback != nullptr) {
324 info.callback(event_sp, info.callback_user_data);
325 ++num_handled;
326 }
327 }
328 }
329 return num_handled;
330}
331
332uint32_t
334 const BroadcastEventSpec &event_spec) {
335 if (!manager_sp)
336 return 0;
337
338 const auto manager_matcher =
339 [&manager_sp](const BroadcasterManagerWP &input_wp) -> bool {
340 BroadcasterManagerSP input_sp = input_wp.lock();
341 return (input_sp && input_sp == manager_sp);
342 };
343 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
344 // avoid violating the lock hierarchy (manager before broadcasters).
345 std::lock_guard<std::mutex> manager_guard(manager_sp->m_manager_mutex);
346 std::lock_guard<std::mutex> guard(m_broadcasters_mutex);
347
348 uint32_t bits_acquired = manager_sp->RegisterListenerForEventsNoLock(
349 this->shared_from_this(), event_spec);
350 if (bits_acquired) {
351 BroadcasterManagerWP manager_wp(manager_sp);
352 if (llvm::none_of(m_broadcaster_managers, manager_matcher))
353 m_broadcaster_managers.push_back(manager_wp);
354 }
355
356 return bits_acquired;
357}
358
360 const BroadcastEventSpec &event_spec) {
361 if (!manager_sp)
362 return false;
363
364 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
365 // avoid violating the lock hierarchy (manager before broadcasters).
366 std::lock_guard<std::mutex> manager_guard(manager_sp->m_manager_mutex);
367 std::lock_guard<std::mutex> guard(m_broadcasters_mutex);
368 return manager_sp->UnregisterListenerForEventsNoLock(this->shared_from_this(),
369 event_spec);
370}
371
373 return ListenerSP(new Listener(name));
374}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:369
#define LLDB_LOGF(log,...)
Definition Log.h:383
lldb::BroadcastEventSpec
Definition Broadcaster.h:40
uint32_t AddListener(const lldb::ListenerSP &listener_sp, uint32_t event_mask)
Listen for any events specified by event_mask.
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 ...
std::weak_ptr< BroadcasterImpl > BroadcasterImplWP
BroadcasterImplSP GetBroadcasterImpl()
std::shared_ptr< BroadcasterImpl > BroadcasterImplSP
size_t HandleBroadcastEvent(lldb::EventSP &event_sp)
Definition Listener.cpp:309
static lldb::ListenerSP MakeListener(const char *name)
Definition Listener.cpp:372
event_collection m_events
Definition Listener.h:129
Event * PeekAtNextEventForBroadcaster(Broadcaster *broadcaster)
Definition Listener.cpp:237
uint32_t StartListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask)
Definition Listener.cpp:58
std::condition_variable m_events_condition
Definition Listener.h:131
uint32_t StartListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec)
Definition Listener.cpp:333
friend class Broadcaster
Definition Listener.h:39
bool StopListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec)
Definition Listener.cpp:359
bool(* HandleBroadcastCallback)(lldb::EventSP &event_sp, void *baton)
Definition Listener.h:37
std::mutex m_broadcasters_mutex
Definition Listener.h:128
broadcaster_manager_collection m_broadcaster_managers
Definition Listener.h:132
bool GetEventForBroadcaster(Broadcaster *broadcaster, lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition Listener.cpp:299
bool FindNextEventInternal(std::unique_lock< std::mutex > &lock, Broadcaster *broadcaster, uint32_t event_type_mask, lldb::EventSP &event_sp, bool remove)
Definition Listener.cpp:177
const char * GetName()
Definition Listener.h:58
Event * PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, uint32_t event_type_mask)
Definition Listener.cpp:246
bool StopListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask)
Definition Listener.cpp:119
bool GetEventForBroadcasterWithType(Broadcaster *broadcaster, uint32_t event_type_mask, lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition Listener.cpp:293
Listener(const char *name)
Definition Listener.cpp:21
void BroadcasterWillDestruct(Broadcaster *)
Definition Listener.cpp:136
void BroadcasterManagerWillDestruct(lldb::BroadcasterManagerSP manager_sp)
Definition Listener.cpp:157
broadcaster_collection m_broadcasters
Definition Listener.h:127
bool GetEventInternal(const Timeout< std::micro > &timeout, Broadcaster *broadcaster, uint32_t event_type_mask, lldb::EventSP &event_sp)
Definition Listener.cpp:256
std::mutex m_events_mutex
Definition Listener.h:130
void AddEvent(lldb::EventSP &event)
Definition Listener.cpp:166
bool GetEvent(lldb::EventSP &event_sp, const Timeout< std::micro > &timeout)
Definition Listener.cpp:305
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
std::shared_ptr< lldb_private::BroadcasterManager > BroadcasterManagerSP
std::shared_ptr< lldb_private::Event > EventSP
std::shared_ptr< lldb_private::Listener > ListenerSP
std::weak_ptr< lldb_private::BroadcasterManager > BroadcasterManagerWP
HandleBroadcastCallback callback
Definition Listener.h:105