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 23using namespace lldb; 24using namespace lldb_private; 25 26Broadcaster::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 34Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster) 35 : m_broadcaster(broadcaster), m_listeners(), m_listeners_mutex(), 36 m_hijacking_listeners(), m_hijacking_masks() {} 37 38Broadcaster::~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 46void Broadcaster::CheckInWithManager() { 47 if (m_manager_sp) { 48 m_manager_sp->SignUpListenersForBroadcaster(*this); 49 } 50} 51 52llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4> 53Broadcaster::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 77bool 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 89void Broadcaster::BroadcasterImpl::Clear() { 90 std::lock_guard<std::recursive_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 101Broadcaster *Broadcaster::BroadcasterImpl::GetBroadcaster() { 102 return &m_broadcaster; 103} 104 105bool 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 131void Broadcaster::AddInitialEventsToListener( 132 const lldb::ListenerSP &listener_sp, uint32_t requested_events) {} 133 134uint32_t 135Broadcaster::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::recursive_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 173bool Broadcaster::BroadcasterImpl::EventTypeHasListeners(uint32_t event_type) { 174 std::lock_guard<std::recursive_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 186bool 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::recursive_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 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 } else 217 it++; 218 } 219 return false; 220} 221 222bool Broadcaster::BroadcasterImpl::RemoveListener( 223 const lldb::ListenerSP &listener_sp, uint32_t event_mask) { 224 return RemoveListener(listener_sp.get(), event_mask); 225} 226 227void Broadcaster::BroadcasterImpl::BroadcastEvent(EventSP &event_sp) { 228 return PrivateBroadcastEvent(event_sp, false); 229} 230 231void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique(EventSP &event_sp) { 232 return PrivateBroadcastEvent(event_sp, true); 233} 234 235void 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::recursive_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 303void 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 308void 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 314void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique( 315 uint32_t event_type, EventData *event_data) { 316 auto event_sp = std::make_shared<Event>(event_type, event_data); 317 PrivateBroadcastEvent(event_sp, true); 318} 319 320void Broadcaster::BroadcasterImpl::SetPrimaryListener(lldb::ListenerSP 321 listener_sp) { 322 // This might have already been added as a normal listener, make sure we 323 // don't hold two copies. 324 RemoveListener(listener_sp.get(), UINT32_MAX); 325 m_primary_listener_sp = listener_sp; 326 327} 328 329bool Broadcaster::BroadcasterImpl::HijackBroadcaster( 330 const lldb::ListenerSP &listener_sp, uint32_t event_mask) { 331 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); 332 333 Log *log = GetLog(LLDBLog::Events); 334 LLDB_LOG( 335 log, 336 "{0} Broadcaster(\"{1}\")::HijackBroadcaster (listener(\"{2}\")={3})", 337 static_cast<void *>(this), GetBroadcasterName(), 338 listener_sp->m_name.c_str(), static_cast<void *>(listener_sp.get())); 339 m_hijacking_listeners.push_back(listener_sp); 340 m_hijacking_masks.push_back(event_mask); 341 return true; 342} 343 344bool Broadcaster::BroadcasterImpl::IsHijackedForEvent(uint32_t event_mask) { 345 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); 346 347 if (!m_hijacking_listeners.empty()) 348 return (event_mask & m_hijacking_masks.back()) != 0; 349 return false; 350} 351 352const char *Broadcaster::BroadcasterImpl::GetHijackingListenerName() { 353 if (m_hijacking_listeners.size()) { 354 return m_hijacking_listeners.back()->GetName(); 355 } 356 return nullptr; 357} 358 359void Broadcaster::BroadcasterImpl::RestoreBroadcaster() { 360 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); 361 362 if (!m_hijacking_listeners.empty()) { 363 ListenerSP listener_sp = m_hijacking_listeners.back(); 364 Log *log = GetLog(LLDBLog::Events); 365 LLDB_LOG(log, 366 "{0} Broadcaster(\"{1}\")::RestoreBroadcaster (about to pop " 367 "listener(\"{2}\")={3})", 368 static_cast<void *>(this), GetBroadcasterName(), 369 listener_sp->m_name.c_str(), 370 static_cast<void *>(listener_sp.get())); 371 m_hijacking_listeners.pop_back(); 372 } 373 if (!m_hijacking_masks.empty()) 374 m_hijacking_masks.pop_back(); 375} 376 377ConstString &Broadcaster::GetBroadcasterClass() const { 378 static ConstString class_name("lldb.anonymous"); 379 return class_name; 380} 381 382bool BroadcastEventSpec::operator<(const BroadcastEventSpec &rhs) const { 383 if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) { 384 return GetEventBits() < rhs.GetEventBits(); 385 } 386 return GetBroadcasterClass() < rhs.GetBroadcasterClass(); 387} 388 389BroadcasterManager::BroadcasterManager() : m_manager_mutex() {} 390 391lldb::BroadcasterManagerSP BroadcasterManager::MakeBroadcasterManager() { 392 return lldb::BroadcasterManagerSP(new BroadcasterManager()); 393} 394 395uint32_t BroadcasterManager::RegisterListenerForEvents( 396 const lldb::ListenerSP &listener_sp, const BroadcastEventSpec &event_spec) { 397 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); 398 399 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); 400 uint32_t available_bits = event_spec.GetEventBits(); 401 402 auto class_matches = [&event_spec](const event_listener_key &input) -> bool { 403 return input.first.GetBroadcasterClass() == 404 event_spec.GetBroadcasterClass(); 405 }; 406 407 while (iter != end_iter && 408 (iter = find_if(iter, end_iter, class_matches)) != end_iter) { 409 available_bits &= ~((*iter).first.GetEventBits()); 410 iter++; 411 } 412 413 if (available_bits != 0) { 414 m_event_map.insert(event_listener_key( 415 BroadcastEventSpec(event_spec.GetBroadcasterClass(), available_bits), 416 listener_sp)); 417 m_listeners.insert(listener_sp); 418 } 419 420 return available_bits; 421} 422 423bool BroadcasterManager::UnregisterListenerForEvents( 424 const lldb::ListenerSP &listener_sp, const BroadcastEventSpec &event_spec) { 425 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); 426 bool removed_some = false; 427 428 if (m_listeners.erase(listener_sp) == 0) 429 return false; 430 431 auto listener_matches_and_shared_bits = 432 [&listener_sp, &event_spec](const event_listener_key &input) -> bool { 433 return input.first.GetBroadcasterClass() == 434 event_spec.GetBroadcasterClass() && 435 (input.first.GetEventBits() & event_spec.GetEventBits()) != 0 && 436 input.second == listener_sp; 437 }; 438 std::vector<BroadcastEventSpec> to_be_readded; 439 uint32_t event_bits_to_remove = event_spec.GetEventBits(); 440 441 // Go through the map and delete the exact matches, and build a list of 442 // matches that weren't exact to re-add: 443 for (auto iter = m_event_map.begin(), end = m_event_map.end();;) { 444 iter = find_if(iter, end, listener_matches_and_shared_bits); 445 if (iter == end) 446 break; 447 uint32_t iter_event_bits = (*iter).first.GetEventBits(); 448 removed_some = true; 449 450 if (event_bits_to_remove != iter_event_bits) { 451 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove; 452 to_be_readded.emplace_back(event_spec.GetBroadcasterClass(), 453 new_event_bits); 454 } 455 iter = m_event_map.erase(iter); 456 } 457 458 // Okay now add back the bits that weren't completely removed: 459 for (const auto &event : to_be_readded) { 460 m_event_map.insert(event_listener_key(event, listener_sp)); 461 } 462 463 return removed_some; 464} 465 466ListenerSP BroadcasterManager::GetListenerForEventSpec( 467 const BroadcastEventSpec &event_spec) const { 468 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); 469 470 auto event_spec_matches = 471 [&event_spec](const event_listener_key &input) -> bool { 472 return input.first.IsContainedIn(event_spec); 473 }; 474 475 auto iter = llvm::find_if(m_event_map, event_spec_matches); 476 if (iter != m_event_map.end()) 477 return (*iter).second; 478 479 return nullptr; 480} 481 482void BroadcasterManager::RemoveListener(Listener *listener) { 483 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); 484 auto listeners_predicate = 485 [&listener](const lldb::ListenerSP &input) -> bool { 486 return input.get() == listener; 487 }; 488 489 if (auto iter = llvm::find_if(m_listeners, listeners_predicate); 490 iter != m_listeners.end()) 491 m_listeners.erase(iter); 492 493 auto events_predicate = [listener](const event_listener_key &input) -> bool { 494 return input.second.get() == listener; 495 }; 496 497 // TODO: use 'std::map::erase_if' when moving to c++20. 498 for (auto iter = m_event_map.begin(), end = m_event_map.end();;) { 499 iter = find_if(iter, end, events_predicate); 500 if (iter == end) 501 break; 502 503 iter = m_event_map.erase(iter); 504 } 505} 506 507void BroadcasterManager::RemoveListener(const lldb::ListenerSP &listener_sp) { 508 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); 509 510 auto listener_matches = 511 [&listener_sp](const event_listener_key &input) -> bool { 512 return input.second == listener_sp; 513 }; 514 515 if (m_listeners.erase(listener_sp) == 0) 516 return; 517 518 // TODO: use 'std::map::erase_if' when moving to c++20. 519 for (auto iter = m_event_map.begin(), end_iter = m_event_map.end();;) { 520 iter = find_if(iter, end_iter, listener_matches); 521 if (iter == end_iter) 522 break; 523 524 iter = m_event_map.erase(iter); 525 } 526} 527 528void BroadcasterManager::SignUpListenersForBroadcaster( 529 Broadcaster &broadcaster) { 530 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); 531 532 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); 533 534 auto class_matches = [&broadcaster](const event_listener_key &input) -> bool { 535 return input.first.GetBroadcasterClass() == 536 broadcaster.GetBroadcasterClass(); 537 }; 538 539 while (iter != end_iter && 540 (iter = find_if(iter, end_iter, class_matches)) != end_iter) { 541 (*iter).second->StartListeningForEvents(&broadcaster, 542 (*iter).first.GetEventBits()); 543 iter++; 544 } 545} 546 547void BroadcasterManager::Clear() { 548 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); 549 550 for (auto &listener : m_listeners) 551 listener->BroadcasterManagerWillDestruct(this->shared_from_this()); 552 m_listeners.clear(); 553 m_event_map.clear(); 554} 555