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 21 using namespace lldb; 22 using namespace lldb_private; 23 24 Broadcaster::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 38 Broadcaster::~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 47 void 48 Broadcaster::CheckInWithManager () 49 { 50 if (m_manager != NULL) 51 { 52 m_manager->SignUpListenersForBroadcaster(*this); 53 } 54 } 55 56 void 57 Broadcaster::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 } 71 const ConstString & 72 Broadcaster::GetBroadcasterName () 73 { 74 return m_broadcaster_name; 75 } 76 77 bool 78 Broadcaster::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 108 void 109 Broadcaster::AddInitialEventsToListener (Listener *listener, uint32_t requested_events) 110 { 111 112 } 113 114 uint32_t 115 Broadcaster::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 163 bool 164 Broadcaster::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 183 bool 184 Broadcaster::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 204 void 205 Broadcaster::BroadcastEvent (EventSP &event_sp) 206 { 207 return PrivateBroadcastEvent (event_sp, false); 208 } 209 210 void 211 Broadcaster::BroadcastEventIfUnique (EventSP &event_sp) 212 { 213 return PrivateBroadcastEvent (event_sp, true); 214 } 215 216 void 217 Broadcaster::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 278 void 279 Broadcaster::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 285 void 286 Broadcaster::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 292 bool 293 Broadcaster::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 311 void 312 Broadcaster::RestoreBroadcaster () 313 { 314 Mutex::Locker event_types_locker(m_listeners_mutex); 315 316 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS)); 317 if (log) 318 { 319 Listener *listener = m_hijacking_listeners.back(); 320 log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)", 321 this, 322 m_broadcaster_name.AsCString(""), 323 listener->m_name.c_str(), 324 listener); 325 } 326 m_hijacking_listeners.pop_back(); 327 m_hijacking_masks.pop_back(); 328 } 329 330 ConstString & 331 Broadcaster::GetBroadcasterClass() const 332 { 333 static ConstString class_name ("lldb.anonymous"); 334 return class_name; 335 } 336 337 BroadcastEventSpec::BroadcastEventSpec (const BroadcastEventSpec &rhs) : 338 m_broadcaster_class (rhs.m_broadcaster_class), 339 m_event_bits (rhs.m_event_bits) 340 { 341 } 342 343 bool 344 BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const 345 { 346 if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) 347 { 348 return GetEventBits() < rhs.GetEventBits(); 349 } 350 else 351 { 352 return GetBroadcasterClass() < rhs.GetBroadcasterClass(); 353 } 354 } 355 356 const BroadcastEventSpec & 357 BroadcastEventSpec::operator= (const BroadcastEventSpec &rhs) 358 { 359 m_broadcaster_class = rhs.m_broadcaster_class; 360 m_event_bits = rhs.m_event_bits; 361 return *this; 362 } 363 364 BroadcasterManager::BroadcasterManager() : 365 m_manager_mutex(Mutex::eMutexTypeRecursive) 366 { 367 368 } 369 370 uint32_t 371 BroadcasterManager::RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec) 372 { 373 Mutex::Locker locker(m_manager_mutex); 374 375 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); 376 uint32_t available_bits = event_spec.GetEventBits(); 377 378 while (iter != end_iter 379 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter) 380 { 381 available_bits &= ~((*iter).first.GetEventBits()); 382 iter++; 383 } 384 385 if (available_bits != 0) 386 { 387 m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), &listener)); 388 m_listeners.insert(&listener); 389 } 390 391 return available_bits; 392 } 393 394 bool 395 BroadcasterManager::UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec) 396 { 397 Mutex::Locker locker(m_manager_mutex); 398 bool removed_some = false; 399 400 if (m_listeners.erase(&listener) == 0) 401 return false; 402 403 ListenerMatchesAndSharedBits predicate (event_spec, listener); 404 std::vector<BroadcastEventSpec> to_be_readded; 405 uint32_t event_bits_to_remove = event_spec.GetEventBits(); 406 407 // Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add: 408 while (1) 409 { 410 collection::iterator iter, end_iter = m_event_map.end(); 411 iter = find_if (m_event_map.begin(), end_iter, predicate); 412 if (iter == end_iter) 413 { 414 break; 415 } 416 else 417 { 418 uint32_t iter_event_bits = (*iter).first.GetEventBits(); 419 removed_some = true; 420 421 if (event_bits_to_remove != iter_event_bits) 422 { 423 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove; 424 to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits)); 425 } 426 m_event_map.erase (iter); 427 } 428 } 429 430 // Okay now add back the bits that weren't completely removed: 431 for (size_t i = 0; i < to_be_readded.size(); i++) 432 { 433 m_event_map.insert (event_listener_key (to_be_readded[i], &listener)); 434 } 435 436 return removed_some; 437 } 438 439 Listener * 440 BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const 441 { 442 Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex))); 443 444 collection::const_iterator iter, end_iter = m_event_map.end(); 445 iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec)); 446 if (iter != end_iter) 447 return (*iter).second; 448 else 449 return NULL; 450 } 451 452 void 453 BroadcasterManager::RemoveListener (Listener &listener) 454 { 455 Mutex::Locker locker(m_manager_mutex); 456 ListenerMatches predicate (listener); 457 458 459 if (m_listeners.erase (&listener) == 0) 460 return; 461 462 while (1) 463 { 464 collection::iterator iter, end_iter = m_event_map.end(); 465 iter = find_if (m_event_map.begin(), end_iter, predicate); 466 if (iter == end_iter) 467 break; 468 else 469 m_event_map.erase(iter); 470 } 471 } 472 473 void 474 BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster) 475 { 476 Mutex::Locker locker(m_manager_mutex); 477 478 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); 479 480 while (iter != end_iter 481 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter) 482 { 483 (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits()); 484 iter++; 485 } 486 } 487 488 void 489 BroadcasterManager::Clear () 490 { 491 Mutex::Locker locker(m_manager_mutex); 492 listener_collection::iterator end_iter = m_listeners.end(); 493 494 for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++) 495 (*iter)->BroadcasterManagerWillDestruct(this); 496 m_listeners.clear(); 497 m_event_map.clear(); 498 499 } 500