1//===-- Broadcaster.cpp -----------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/Core/Broadcaster.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Core/Log.h" 17#include "lldb/Core/Event.h" 18#include "lldb/Core/StreamString.h" 19#include "lldb/lldb-private-log.h" 20 21using namespace lldb; 22using namespace lldb_private; 23 24Broadcaster::Broadcaster (BroadcasterManager *manager, const char *name) : 25 m_broadcaster_name (name), 26 m_listeners (), 27 m_listeners_mutex (Mutex::eMutexTypeRecursive), 28 m_hijacking_listeners(), 29 m_hijacking_masks(), 30 m_manager (manager) 31{ 32 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 33 if (log) 34 log->Printf ("%p Broadcaster::Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString()); 35 36} 37 38Broadcaster::~Broadcaster() 39{ 40 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 41 if (log) 42 log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString()); 43 44 Clear(); 45} 46 47void 48Broadcaster::CheckInWithManager () 49{ 50 if (m_manager != NULL) 51 { 52 m_manager->SignUpListenersForBroadcaster(*this); 53 } 54} 55 56void 57Broadcaster::Clear() 58{ 59 Mutex::Locker listeners_locker(m_listeners_mutex); 60 61 // Make sure the listener forgets about this broadcaster. We do 62 // this in the broadcaster in case the broadcaster object initiates 63 // the removal. 64 65 collection::iterator pos, end = m_listeners.end(); 66 for (pos = m_listeners.begin(); pos != end; ++pos) 67 pos->first->BroadcasterWillDestruct (this); 68 69 m_listeners.clear(); 70} 71const ConstString & 72Broadcaster::GetBroadcasterName () 73{ 74 return m_broadcaster_name; 75} 76 77bool 78Broadcaster::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const 79{ 80 uint32_t num_names_added = 0; 81 if (event_mask && !m_event_names.empty()) 82 { 83 event_names_map::const_iterator end = m_event_names.end(); 84 for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1) 85 { 86 if (mask & 1) 87 { 88 event_names_map::const_iterator pos = m_event_names.find(bit); 89 if (pos != end) 90 { 91 if (num_names_added > 0) 92 s.PutCString(", "); 93 94 if (prefix_with_broadcaster_name) 95 { 96 s.PutCString (m_broadcaster_name.GetCString()); 97 s.PutChar('.'); 98 } 99 s.PutCString(pos->second.c_str()); 100 ++num_names_added; 101 } 102 } 103 } 104 } 105 return num_names_added > 0; 106} 107 108void 109Broadcaster::AddInitialEventsToListener (Listener *listener, uint32_t requested_events) 110{ 111 112} 113 114uint32_t 115Broadcaster::AddListener (Listener* listener, uint32_t event_mask) 116{ 117 if (listener == NULL) 118 return 0; 119 120 Mutex::Locker locker(m_listeners_mutex); 121 collection::iterator pos, end = m_listeners.end(); 122 123 collection::iterator existing_pos = end; 124 // See if we already have this listener, and if so, update its mask 125 uint32_t taken_event_types = 0; 126 for (pos = m_listeners.begin(); pos != end; ++pos) 127 { 128 if (pos->first == listener) 129 existing_pos = pos; 130 // For now don't descriminate on who gets what 131 // FIXME: Implement "unique listener for this bit" mask 132 // taken_event_types |= pos->second; 133 } 134 135 // Each event bit in a Broadcaster object can only be used 136 // by one listener 137 uint32_t available_event_types = ~taken_event_types & event_mask; 138 139 if (available_event_types) 140 { 141 // If we didn't find our listener, add it 142 if (existing_pos == end) 143 { 144 // Grant a new listener the available event bits 145 m_listeners.push_back(std::make_pair(listener, available_event_types)); 146 } 147 else 148 { 149 // Grant the existing listener the available event bits 150 existing_pos->second |= available_event_types; 151 } 152 153 // Individual broadcasters decide whether they have outstanding data when a 154 // listener attaches, and insert it into the listener with this method. 155 156 AddInitialEventsToListener (listener, available_event_types); 157 } 158 159 // Return the event bits that were granted to the listener 160 return available_event_types; 161} 162 163bool 164Broadcaster::EventTypeHasListeners (uint32_t event_type) 165{ 166 Mutex::Locker locker (m_listeners_mutex); 167 168 if (m_hijacking_listeners.size() > 0 && event_type & m_hijacking_masks.back()) 169 return true; 170 171 if (m_listeners.empty()) 172 return false; 173 174 collection::iterator pos, end = m_listeners.end(); 175 for (pos = m_listeners.begin(); pos != end; ++pos) 176 { 177 if (pos->second & event_type) 178 return true; 179 } 180 return false; 181} 182 183bool 184Broadcaster::RemoveListener (Listener* listener, uint32_t event_mask) 185{ 186 Mutex::Locker locker(m_listeners_mutex); 187 collection::iterator pos, end = m_listeners.end(); 188 // See if we already have this listener, and if so, update its mask 189 for (pos = m_listeners.begin(); pos != end; ++pos) 190 { 191 if (pos->first == listener) 192 { 193 // Relinquish all event bits in "event_mask" 194 pos->second &= ~event_mask; 195 // If all bits have been relinquished then remove this listener 196 if (pos->second == 0) 197 m_listeners.erase (pos); 198 return true; 199 } 200 } 201 return false; 202} 203 204void 205Broadcaster::BroadcastEvent (EventSP &event_sp) 206{ 207 return PrivateBroadcastEvent (event_sp, false); 208} 209 210void 211Broadcaster::BroadcastEventIfUnique (EventSP &event_sp) 212{ 213 return PrivateBroadcastEvent (event_sp, true); 214} 215 216void 217Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique) 218{ 219 // Can't add a NULL event... 220 if (event_sp.get() == NULL) 221 return; 222 223 // Update the broadcaster on this event 224 event_sp->SetBroadcaster (this); 225 226 const uint32_t event_type = event_sp->GetType(); 227 228 Mutex::Locker event_types_locker(m_listeners_mutex); 229 230 Listener *hijacking_listener = NULL; 231 if (!m_hijacking_listeners.empty()) 232 { 233 assert (!m_hijacking_masks.empty()); 234 hijacking_listener = m_hijacking_listeners.back(); 235 if ((event_type & m_hijacking_masks.back()) == 0) 236 hijacking_listener = NULL; 237 } 238 239 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS)); 240 if (log) 241 { 242 StreamString event_description; 243 event_sp->Dump (&event_description); 244 log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p", 245 this, 246 m_broadcaster_name.AsCString(""), 247 event_description.GetData(), 248 unique, 249 hijacking_listener); 250 } 251 252 if (hijacking_listener) 253 { 254 if (unique && hijacking_listener->PeekAtNextEventForBroadcasterWithType (this, event_type)) 255 return; 256 hijacking_listener->AddEvent (event_sp); 257 } 258 else 259 { 260 collection::iterator pos, end = m_listeners.end(); 261 262 263 // Iterate through all listener/mask pairs 264 for (pos = m_listeners.begin(); pos != end; ++pos) 265 { 266 // If the listener's mask matches any bits that we just set, then 267 // put the new event on its event queue. 268 if (event_type & pos->second) 269 { 270 if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (this, event_type)) 271 continue; 272 pos->first->AddEvent (event_sp); 273 } 274 } 275 } 276} 277 278void 279Broadcaster::BroadcastEvent (uint32_t event_type, EventData *event_data) 280{ 281 EventSP event_sp (new Event (event_type, event_data)); 282 PrivateBroadcastEvent (event_sp, false); 283} 284 285void 286Broadcaster::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data) 287{ 288 EventSP event_sp (new Event (event_type, event_data)); 289 PrivateBroadcastEvent (event_sp, true); 290} 291 292bool 293Broadcaster::HijackBroadcaster (Listener *listener, uint32_t event_mask) 294{ 295 Mutex::Locker event_types_locker(m_listeners_mutex); 296 297 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS)); 298 if (log) 299 { 300 log->Printf ("%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)", 301 this, 302 m_broadcaster_name.AsCString(""), 303 listener->m_name.c_str(), 304 listener); 305 } 306 m_hijacking_listeners.push_back(listener); 307 m_hijacking_masks.push_back(event_mask); 308 return true; 309} 310 311void 312Broadcaster::RestoreBroadcaster () 313{ 314 Mutex::Locker event_types_locker(m_listeners_mutex); 315 316 if (!m_hijacking_listeners.empty()) 317 { 318 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS)); 319 if (log) 320 { 321 Listener *listener = m_hijacking_listeners.back(); 322 log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)", 323 this, 324 m_broadcaster_name.AsCString(""), 325 listener->m_name.c_str(), 326 listener); 327 } 328 m_hijacking_listeners.pop_back(); 329 } 330 if (!m_hijacking_masks.empty()) 331 m_hijacking_masks.pop_back(); 332} 333 334ConstString & 335Broadcaster::GetBroadcasterClass() const 336{ 337 static ConstString class_name ("lldb.anonymous"); 338 return class_name; 339} 340 341BroadcastEventSpec::BroadcastEventSpec (const BroadcastEventSpec &rhs) : 342 m_broadcaster_class (rhs.m_broadcaster_class), 343 m_event_bits (rhs.m_event_bits) 344{ 345} 346 347bool 348BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const 349{ 350 if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) 351 { 352 return GetEventBits() < rhs.GetEventBits(); 353 } 354 else 355 { 356 return GetBroadcasterClass() < rhs.GetBroadcasterClass(); 357 } 358} 359 360const BroadcastEventSpec & 361BroadcastEventSpec::operator= (const BroadcastEventSpec &rhs) 362{ 363 m_broadcaster_class = rhs.m_broadcaster_class; 364 m_event_bits = rhs.m_event_bits; 365 return *this; 366} 367 368BroadcasterManager::BroadcasterManager() : 369 m_manager_mutex(Mutex::eMutexTypeRecursive) 370{ 371 372} 373 374uint32_t 375BroadcasterManager::RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec) 376{ 377 Mutex::Locker locker(m_manager_mutex); 378 379 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); 380 uint32_t available_bits = event_spec.GetEventBits(); 381 382 while (iter != end_iter 383 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter) 384 { 385 available_bits &= ~((*iter).first.GetEventBits()); 386 iter++; 387 } 388 389 if (available_bits != 0) 390 { 391 m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), &listener)); 392 m_listeners.insert(&listener); 393 } 394 395 return available_bits; 396} 397 398bool 399BroadcasterManager::UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec) 400{ 401 Mutex::Locker locker(m_manager_mutex); 402 bool removed_some = false; 403 404 if (m_listeners.erase(&listener) == 0) 405 return false; 406 407 ListenerMatchesAndSharedBits predicate (event_spec, listener); 408 std::vector<BroadcastEventSpec> to_be_readded; 409 uint32_t event_bits_to_remove = event_spec.GetEventBits(); 410 411 // Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add: 412 while (1) 413 { 414 collection::iterator iter, end_iter = m_event_map.end(); 415 iter = find_if (m_event_map.begin(), end_iter, predicate); 416 if (iter == end_iter) 417 { 418 break; 419 } 420 else 421 { 422 uint32_t iter_event_bits = (*iter).first.GetEventBits(); 423 removed_some = true; 424 425 if (event_bits_to_remove != iter_event_bits) 426 { 427 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove; 428 to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits)); 429 } 430 m_event_map.erase (iter); 431 } 432 } 433 434 // Okay now add back the bits that weren't completely removed: 435 for (size_t i = 0; i < to_be_readded.size(); i++) 436 { 437 m_event_map.insert (event_listener_key (to_be_readded[i], &listener)); 438 } 439 440 return removed_some; 441} 442 443Listener * 444BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const 445{ 446 Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex))); 447 448 collection::const_iterator iter, end_iter = m_event_map.end(); 449 iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec)); 450 if (iter != end_iter) 451 return (*iter).second; 452 else 453 return NULL; 454} 455 456void 457BroadcasterManager::RemoveListener (Listener &listener) 458{ 459 Mutex::Locker locker(m_manager_mutex); 460 ListenerMatches predicate (listener); 461 462 463 if (m_listeners.erase (&listener) == 0) 464 return; 465 466 while (1) 467 { 468 collection::iterator iter, end_iter = m_event_map.end(); 469 iter = find_if (m_event_map.begin(), end_iter, predicate); 470 if (iter == end_iter) 471 break; 472 else 473 m_event_map.erase(iter); 474 } 475} 476 477void 478BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster) 479{ 480 Mutex::Locker locker(m_manager_mutex); 481 482 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); 483 484 while (iter != end_iter 485 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter) 486 { 487 (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits()); 488 iter++; 489 } 490} 491 492void 493BroadcasterManager::Clear () 494{ 495 Mutex::Locker locker(m_manager_mutex); 496 listener_collection::iterator end_iter = m_listeners.end(); 497 498 for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++) 499 (*iter)->BroadcasterManagerWillDestruct(this); 500 m_listeners.clear(); 501 m_event_map.clear(); 502 503} 504