Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Utility/Broadcaster.cpp
39587 views
1
//===-- Broadcaster.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
9
#include "lldb/Utility/Broadcaster.h"
10
#include "lldb/Utility/Event.h"
11
#include "lldb/Utility/LLDBLog.h"
12
#include "lldb/Utility/Listener.h"
13
#include "lldb/Utility/Stream.h"
14
#include "lldb/Utility/StreamString.h"
15
16
#include <algorithm>
17
#include <memory>
18
#include <utility>
19
20
#include <cassert>
21
#include <cstddef>
22
23
using namespace lldb;
24
using namespace lldb_private;
25
26
Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, std::string name)
27
: m_broadcaster_sp(std::make_shared<BroadcasterImpl>(*this)),
28
m_manager_sp(std::move(manager_sp)), m_broadcaster_name(std::move(name)) {
29
Log *log = GetLog(LLDBLog::Object);
30
LLDB_LOG(log, "{0} Broadcaster::Broadcaster(\"{1}\")",
31
static_cast<void *>(this), GetBroadcasterName());
32
}
33
34
Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster)
35
: m_broadcaster(broadcaster), m_listeners(), m_listeners_mutex(),
36
m_hijacking_listeners(), m_hijacking_masks() {}
37
38
Broadcaster::~Broadcaster() {
39
Log *log = GetLog(LLDBLog::Object);
40
LLDB_LOG(log, "{0} Broadcaster::~Broadcaster(\"{1}\")",
41
static_cast<void *>(this), GetBroadcasterName());
42
43
Clear();
44
}
45
46
void Broadcaster::CheckInWithManager() {
47
if (m_manager_sp) {
48
m_manager_sp->SignUpListenersForBroadcaster(*this);
49
}
50
}
51
52
llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4>
53
Broadcaster::BroadcasterImpl::GetListeners(uint32_t event_mask,
54
bool include_primary) {
55
llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4> listeners;
56
size_t max_count = m_listeners.size();
57
if (include_primary)
58
max_count++;
59
listeners.reserve(max_count);
60
61
for (auto it = m_listeners.begin(); it != m_listeners.end();) {
62
lldb::ListenerSP curr_listener_sp(it->first.lock());
63
if (curr_listener_sp) {
64
if (it->second & event_mask)
65
listeners.emplace_back(std::move(curr_listener_sp), it->second);
66
++it;
67
} else
68
// If our listener_wp didn't resolve, then we should remove this entry.
69
it = m_listeners.erase(it);
70
}
71
if (include_primary && m_primary_listener_sp)
72
listeners.emplace_back(m_primary_listener_sp, m_primary_listener_mask);
73
74
return listeners;
75
}
76
77
bool Broadcaster::BroadcasterImpl::HasListeners(uint32_t event_mask) {
78
if (m_primary_listener_sp)
79
return true;
80
for (auto it = m_listeners.begin(); it != m_listeners.end(); it++) {
81
// Don't return a listener if the other end of the WP is gone:
82
lldb::ListenerSP curr_listener_sp(it->first.lock());
83
if (curr_listener_sp && (it->second & event_mask))
84
return true;
85
}
86
return false;
87
}
88
89
void Broadcaster::BroadcasterImpl::Clear() {
90
std::lock_guard<std::mutex> guard(m_listeners_mutex);
91
92
// Make sure the listener forgets about this broadcaster. We do this in the
93
// broadcaster in case the broadcaster object initiates the removal.
94
for (auto &pair : GetListeners())
95
pair.first->BroadcasterWillDestruct(&m_broadcaster);
96
97
m_listeners.clear();
98
m_primary_listener_sp.reset();
99
}
100
101
Broadcaster *Broadcaster::BroadcasterImpl::GetBroadcaster() {
102
return &m_broadcaster;
103
}
104
105
bool Broadcaster::BroadcasterImpl::GetEventNames(
106
Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const {
107
uint32_t num_names_added = 0;
108
if (event_mask && !m_event_names.empty()) {
109
event_names_map::const_iterator end = m_event_names.end();
110
for (uint32_t bit = 1u, mask = event_mask; mask != 0 && bit != 0;
111
bit <<= 1, mask >>= 1) {
112
if (mask & 1) {
113
event_names_map::const_iterator pos = m_event_names.find(bit);
114
if (pos != end) {
115
if (num_names_added > 0)
116
s.PutCString(", ");
117
118
if (prefix_with_broadcaster_name) {
119
s.PutCString(GetBroadcasterName());
120
s.PutChar('.');
121
}
122
s.PutCString(pos->second);
123
++num_names_added;
124
}
125
}
126
}
127
}
128
return num_names_added > 0;
129
}
130
131
void Broadcaster::AddInitialEventsToListener(
132
const lldb::ListenerSP &listener_sp, uint32_t requested_events) {}
133
134
uint32_t
135
Broadcaster::BroadcasterImpl::AddListener(const lldb::ListenerSP &listener_sp,
136
uint32_t event_mask) {
137
if (!listener_sp)
138
return 0;
139
140
std::lock_guard<std::mutex> guard(m_listeners_mutex);
141
142
// See if we already have this listener, and if so, update its mask
143
144
bool handled = false;
145
146
if (listener_sp == m_primary_listener_sp)
147
// This already handles all bits so just return the mask:
148
return event_mask;
149
150
for (auto &pair : GetListeners(UINT32_MAX, false)) {
151
if (pair.first == listener_sp) {
152
handled = true;
153
pair.second |= event_mask;
154
m_broadcaster.AddInitialEventsToListener(listener_sp, event_mask);
155
break;
156
}
157
}
158
159
if (!handled) {
160
// Grant a new listener the available event bits
161
m_listeners.push_back(
162
std::make_pair(lldb::ListenerWP(listener_sp), event_mask));
163
164
// Individual broadcasters decide whether they have outstanding data when a
165
// listener attaches, and insert it into the listener with this method.
166
m_broadcaster.AddInitialEventsToListener(listener_sp, event_mask);
167
}
168
169
// Return the event bits that were granted to the listener
170
return event_mask;
171
}
172
173
bool Broadcaster::BroadcasterImpl::EventTypeHasListeners(uint32_t event_type) {
174
std::lock_guard<std::mutex> guard(m_listeners_mutex);
175
176
if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back())
177
return true;
178
179
// The primary listener listens for all event bits:
180
if (m_primary_listener_sp)
181
return true;
182
183
return HasListeners(event_type);
184
}
185
186
bool Broadcaster::BroadcasterImpl::RemoveListener(
187
lldb_private::Listener *listener, uint32_t event_mask) {
188
if (!listener)
189
return false;
190
191
if (listener == m_primary_listener_sp.get()) {
192
// Primary listeners listen for all the event bits for their broadcaster,
193
// so remove this altogether if asked:
194
m_primary_listener_sp.reset();
195
return true;
196
}
197
198
std::lock_guard<std::mutex> guard(m_listeners_mutex);
199
for (auto it = m_listeners.begin(); it != m_listeners.end();) {
200
lldb::ListenerSP curr_listener_sp(it->first.lock());
201
202
if (!curr_listener_sp) {
203
// The weak pointer for this listener didn't resolve, lets' prune it
204
// as we go.
205
it = m_listeners.erase(it);
206
continue;
207
}
208
209
if (curr_listener_sp.get() == listener) {
210
it->second &= ~event_mask;
211
// If we removed all the event bits from a listener, remove it from
212
// the list as well.
213
if (!it->second)
214
m_listeners.erase(it);
215
return true;
216
}
217
it++;
218
}
219
return false;
220
}
221
222
bool Broadcaster::BroadcasterImpl::RemoveListener(
223
const lldb::ListenerSP &listener_sp, uint32_t event_mask) {
224
return RemoveListener(listener_sp.get(), event_mask);
225
}
226
227
void Broadcaster::BroadcasterImpl::BroadcastEvent(EventSP &event_sp) {
228
return PrivateBroadcastEvent(event_sp, false);
229
}
230
231
void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique(EventSP &event_sp) {
232
return PrivateBroadcastEvent(event_sp, true);
233
}
234
235
void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp,
236
bool unique) {
237
// Can't add a nullptr event...
238
if (!event_sp)
239
return;
240
241
// Update the broadcaster on this event
242
event_sp->SetBroadcaster(&m_broadcaster);
243
244
const uint32_t event_type = event_sp->GetType();
245
246
std::lock_guard<std::mutex> guard(m_listeners_mutex);
247
248
ListenerSP hijacking_listener_sp;
249
250
if (!m_hijacking_listeners.empty()) {
251
assert(!m_hijacking_masks.empty());
252
hijacking_listener_sp = m_hijacking_listeners.back();
253
if ((event_type & m_hijacking_masks.back()) == 0)
254
hijacking_listener_sp.reset();
255
}
256
257
Log *log = GetLog(LLDBLog::Events);
258
if (!log && event_sp->GetData())
259
log = event_sp->GetData()->GetLogChannel();
260
261
if (log) {
262
StreamString event_description;
263
event_sp->Dump(&event_description);
264
LLDB_LOG(log,
265
"{0:x} Broadcaster(\"{1}\")::BroadcastEvent (event_sp = {2}, "
266
"unique={3}) hijack = {4:x}",
267
static_cast<void *>(this), GetBroadcasterName(),
268
event_description.GetData(), unique,
269
static_cast<void *>(hijacking_listener_sp.get()));
270
}
271
ListenerSP primary_listener_sp
272
= hijacking_listener_sp ? hijacking_listener_sp : m_primary_listener_sp;
273
274
if (primary_listener_sp) {
275
if (unique && primary_listener_sp->PeekAtNextEventForBroadcasterWithType(
276
&m_broadcaster, event_type))
277
return;
278
// Add the pending listeners but not if the event is hijacked, since that
279
// is given sole access to the event stream it is hijacking.
280
// Make sure to do this before adding the event to the primary or it might
281
// start handling the event before we're done adding all the pending
282
// listeners.
283
// Also, don't redo the check for unique here, since otherwise that could
284
// be racy, and if we send the event to the primary listener then we SHOULD
285
// send it to the secondary listeners or they will get out of sync with the
286
// primary listener.
287
if (!hijacking_listener_sp) {
288
for (auto &pair : GetListeners(event_type, false))
289
event_sp->AddPendingListener(pair.first);
290
}
291
primary_listener_sp->AddEvent(event_sp);
292
} else {
293
for (auto &pair : GetListeners(event_type)) {
294
if (unique && pair.first->PeekAtNextEventForBroadcasterWithType(
295
&m_broadcaster, event_type))
296
continue;
297
298
pair.first->AddEvent(event_sp);
299
}
300
}
301
}
302
303
void Broadcaster::BroadcasterImpl::BroadcastEvent(uint32_t event_type) {
304
auto event_sp = std::make_shared<Event>(event_type, /*data = */ nullptr);
305
PrivateBroadcastEvent(event_sp, false);
306
}
307
308
void Broadcaster::BroadcasterImpl::BroadcastEvent(
309
uint32_t event_type, const lldb::EventDataSP &event_data_sp) {
310
auto event_sp = std::make_shared<Event>(event_type, event_data_sp);
311
PrivateBroadcastEvent(event_sp, false);
312
}
313
314
void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique(uint32_t event_type) {
315
auto event_sp = std::make_shared<Event>(event_type, /*data = */ nullptr);
316
PrivateBroadcastEvent(event_sp, true);
317
}
318
319
void Broadcaster::BroadcasterImpl::SetPrimaryListener(lldb::ListenerSP
320
listener_sp) {
321
// This might have already been added as a normal listener, make sure we
322
// don't hold two copies.
323
RemoveListener(listener_sp.get(), UINT32_MAX);
324
m_primary_listener_sp = listener_sp;
325
326
}
327
328
bool Broadcaster::BroadcasterImpl::HijackBroadcaster(
329
const lldb::ListenerSP &listener_sp, uint32_t event_mask) {
330
std::lock_guard<std::mutex> guard(m_listeners_mutex);
331
332
Log *log = GetLog(LLDBLog::Events);
333
LLDB_LOG(
334
log,
335
"{0} Broadcaster(\"{1}\")::HijackBroadcaster (listener(\"{2}\")={3})",
336
static_cast<void *>(this), GetBroadcasterName(),
337
listener_sp->m_name.c_str(), static_cast<void *>(listener_sp.get()));
338
m_hijacking_listeners.push_back(listener_sp);
339
m_hijacking_masks.push_back(event_mask);
340
return true;
341
}
342
343
bool Broadcaster::BroadcasterImpl::IsHijackedForEvent(uint32_t event_mask) {
344
std::lock_guard<std::mutex> guard(m_listeners_mutex);
345
346
if (!m_hijacking_listeners.empty())
347
return (event_mask & m_hijacking_masks.back()) != 0;
348
return false;
349
}
350
351
const char *Broadcaster::BroadcasterImpl::GetHijackingListenerName() {
352
if (m_hijacking_listeners.size()) {
353
return m_hijacking_listeners.back()->GetName();
354
}
355
return nullptr;
356
}
357
358
void Broadcaster::BroadcasterImpl::RestoreBroadcaster() {
359
std::lock_guard<std::mutex> guard(m_listeners_mutex);
360
361
if (!m_hijacking_listeners.empty()) {
362
ListenerSP listener_sp = m_hijacking_listeners.back();
363
Log *log = GetLog(LLDBLog::Events);
364
LLDB_LOG(log,
365
"{0} Broadcaster(\"{1}\")::RestoreBroadcaster (about to pop "
366
"listener(\"{2}\")={3})",
367
static_cast<void *>(this), GetBroadcasterName(),
368
listener_sp->m_name.c_str(),
369
static_cast<void *>(listener_sp.get()));
370
m_hijacking_listeners.pop_back();
371
}
372
if (!m_hijacking_masks.empty())
373
m_hijacking_masks.pop_back();
374
}
375
376
llvm::StringRef Broadcaster::GetBroadcasterClass() const {
377
static constexpr llvm::StringLiteral class_name("lldb.anonymous");
378
return class_name;
379
}
380
381
bool BroadcastEventSpec::operator<(const BroadcastEventSpec &rhs) const {
382
if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) {
383
return GetEventBits() < rhs.GetEventBits();
384
}
385
return GetBroadcasterClass() < rhs.GetBroadcasterClass();
386
}
387
388
BroadcasterManager::BroadcasterManager() : m_manager_mutex() {}
389
390
lldb::BroadcasterManagerSP BroadcasterManager::MakeBroadcasterManager() {
391
return lldb::BroadcasterManagerSP(new BroadcasterManager());
392
}
393
394
uint32_t BroadcasterManager::RegisterListenerForEventsNoLock(
395
const lldb::ListenerSP &listener_sp, const BroadcastEventSpec &event_spec) {
396
collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
397
uint32_t available_bits = event_spec.GetEventBits();
398
399
auto class_matches = [&event_spec](const event_listener_key &input) -> bool {
400
return input.first.GetBroadcasterClass() ==
401
event_spec.GetBroadcasterClass();
402
};
403
404
while (iter != end_iter &&
405
(iter = find_if(iter, end_iter, class_matches)) != end_iter) {
406
available_bits &= ~((*iter).first.GetEventBits());
407
iter++;
408
}
409
410
if (available_bits != 0) {
411
m_event_map.insert(event_listener_key(
412
BroadcastEventSpec(event_spec.GetBroadcasterClass(), available_bits),
413
listener_sp));
414
m_listeners.insert(listener_sp);
415
}
416
417
return available_bits;
418
}
419
420
bool BroadcasterManager::UnregisterListenerForEventsNoLock(
421
const lldb::ListenerSP &listener_sp, const BroadcastEventSpec &event_spec) {
422
bool removed_some = false;
423
424
if (m_listeners.erase(listener_sp) == 0)
425
return false;
426
427
auto listener_matches_and_shared_bits =
428
[&listener_sp, &event_spec](const event_listener_key &input) -> bool {
429
return input.first.GetBroadcasterClass() ==
430
event_spec.GetBroadcasterClass() &&
431
(input.first.GetEventBits() & event_spec.GetEventBits()) != 0 &&
432
input.second == listener_sp;
433
};
434
std::vector<BroadcastEventSpec> to_be_readded;
435
uint32_t event_bits_to_remove = event_spec.GetEventBits();
436
437
// Go through the map and delete the exact matches, and build a list of
438
// matches that weren't exact to re-add:
439
for (auto iter = m_event_map.begin(), end = m_event_map.end();;) {
440
iter = find_if(iter, end, listener_matches_and_shared_bits);
441
if (iter == end)
442
break;
443
uint32_t iter_event_bits = (*iter).first.GetEventBits();
444
removed_some = true;
445
446
if (event_bits_to_remove != iter_event_bits) {
447
uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
448
to_be_readded.emplace_back(event_spec.GetBroadcasterClass(),
449
new_event_bits);
450
}
451
iter = m_event_map.erase(iter);
452
}
453
454
// Okay now add back the bits that weren't completely removed:
455
for (const auto &event : to_be_readded) {
456
m_event_map.insert(event_listener_key(event, listener_sp));
457
}
458
459
return removed_some;
460
}
461
462
ListenerSP BroadcasterManager::GetListenerForEventSpec(
463
const BroadcastEventSpec &event_spec) const {
464
std::lock_guard<std::mutex> guard(m_manager_mutex);
465
466
auto event_spec_matches =
467
[&event_spec](const event_listener_key &input) -> bool {
468
return input.first.IsContainedIn(event_spec);
469
};
470
471
auto iter = llvm::find_if(m_event_map, event_spec_matches);
472
if (iter != m_event_map.end())
473
return (*iter).second;
474
475
return nullptr;
476
}
477
478
void BroadcasterManager::RemoveListener(Listener *listener) {
479
std::lock_guard<std::mutex> guard(m_manager_mutex);
480
auto listeners_predicate =
481
[&listener](const lldb::ListenerSP &input) -> bool {
482
return input.get() == listener;
483
};
484
485
if (auto iter = llvm::find_if(m_listeners, listeners_predicate);
486
iter != m_listeners.end())
487
m_listeners.erase(iter);
488
489
auto events_predicate = [listener](const event_listener_key &input) -> bool {
490
return input.second.get() == listener;
491
};
492
493
// TODO: use 'std::map::erase_if' when moving to c++20.
494
for (auto iter = m_event_map.begin(), end = m_event_map.end();;) {
495
iter = find_if(iter, end, events_predicate);
496
if (iter == end)
497
break;
498
499
iter = m_event_map.erase(iter);
500
}
501
}
502
503
void BroadcasterManager::RemoveListener(const lldb::ListenerSP &listener_sp) {
504
std::lock_guard<std::mutex> guard(m_manager_mutex);
505
506
auto listener_matches =
507
[&listener_sp](const event_listener_key &input) -> bool {
508
return input.second == listener_sp;
509
};
510
511
if (m_listeners.erase(listener_sp) == 0)
512
return;
513
514
// TODO: use 'std::map::erase_if' when moving to c++20.
515
for (auto iter = m_event_map.begin(), end_iter = m_event_map.end();;) {
516
iter = find_if(iter, end_iter, listener_matches);
517
if (iter == end_iter)
518
break;
519
520
iter = m_event_map.erase(iter);
521
}
522
}
523
524
void BroadcasterManager::SignUpListenersForBroadcaster(
525
Broadcaster &broadcaster) {
526
std::lock_guard<std::mutex> guard(m_manager_mutex);
527
528
collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
529
530
auto class_matches = [&broadcaster](const event_listener_key &input) -> bool {
531
return input.first.GetBroadcasterClass() ==
532
broadcaster.GetBroadcasterClass();
533
};
534
535
while (iter != end_iter &&
536
(iter = find_if(iter, end_iter, class_matches)) != end_iter) {
537
(*iter).second->StartListeningForEvents(&broadcaster,
538
(*iter).first.GetEventBits());
539
iter++;
540
}
541
}
542
543
void BroadcasterManager::Clear() {
544
std::lock_guard<std::mutex> guard(m_manager_mutex);
545
546
for (auto &listener : m_listeners)
547
listener->BroadcasterManagerWillDestruct(this->shared_from_this());
548
m_listeners.clear();
549
m_event_map.clear();
550
}
551
552