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