1//===-- Listener.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/Listener.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Core/Broadcaster.h" 17#include "lldb/Core/Log.h" 18#include "lldb/Core/StreamString.h" 19#include "lldb/Core/Event.h" 20#include "lldb/Host/TimeValue.h" 21#include "lldb/lldb-private-log.h" 22#include <algorithm> 23 24using namespace lldb; 25using namespace lldb_private; 26 27Listener::Listener(const char *name) : 28 m_name (name), 29 m_broadcasters(), 30 m_broadcasters_mutex (Mutex::eMutexTypeRecursive), 31 m_events (), 32 m_events_mutex (Mutex::eMutexTypeRecursive), 33 m_cond_wait() 34{ 35 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 36 if (log) 37 log->Printf ("%p Listener::Listener('%s')", this, m_name.c_str()); 38} 39 40Listener::~Listener() 41{ 42 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 43 Mutex::Locker locker (m_broadcasters_mutex); 44 45 size_t num_managers = m_broadcaster_managers.size(); 46 47 for (size_t i = 0; i < num_managers; i++) 48 m_broadcaster_managers[i]->RemoveListener(*this); 49 50 if (log) 51 log->Printf ("%p Listener::~Listener('%s')", this, m_name.c_str()); 52 Clear(); 53} 54 55void 56Listener::Clear() 57{ 58 Mutex::Locker locker(m_broadcasters_mutex); 59 broadcaster_collection::iterator pos, end = m_broadcasters.end(); 60 for (pos = m_broadcasters.begin(); pos != end; ++pos) 61 pos->first->RemoveListener (this, pos->second.event_mask); 62 m_broadcasters.clear(); 63 m_cond_wait.SetValue (false, eBroadcastNever); 64 m_broadcasters.clear(); 65 Mutex::Locker event_locker(m_events_mutex); 66 m_events.clear(); 67} 68 69uint32_t 70Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask) 71{ 72 if (broadcaster) 73 { 74 // Scope for "locker" 75 // Tell the broadcaster to add this object as a listener 76 { 77 Mutex::Locker locker(m_broadcasters_mutex); 78 m_broadcasters.insert(std::make_pair(broadcaster, BroadcasterInfo(event_mask))); 79 } 80 81 uint32_t acquired_mask = broadcaster->AddListener (this, event_mask); 82 83 if (event_mask != acquired_mask) 84 { 85 86 } 87 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); 88 if (log) 89 log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", 90 this, 91 broadcaster, 92 event_mask, 93 acquired_mask, 94 m_name.c_str()); 95 96 return acquired_mask; 97 98 } 99 return 0; 100} 101 102uint32_t 103Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask, HandleBroadcastCallback callback, void *callback_user_data) 104{ 105 if (broadcaster) 106 { 107 // Scope for "locker" 108 // Tell the broadcaster to add this object as a listener 109 { 110 Mutex::Locker locker(m_broadcasters_mutex); 111 m_broadcasters.insert(std::make_pair(broadcaster, BroadcasterInfo(event_mask, callback, callback_user_data))); 112 } 113 114 uint32_t acquired_mask = broadcaster->AddListener (this, event_mask); 115 116 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); 117 if (log) 118 log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x, callback = %p, user_data = %p) acquired_mask = 0x%8.8x for %s", 119 this, broadcaster, event_mask, callback, callback_user_data, acquired_mask, m_name.c_str()); 120 121 return acquired_mask; 122 } 123 return 0; 124} 125 126bool 127Listener::StopListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask) 128{ 129 if (broadcaster) 130 { 131 // Scope for "locker" 132 { 133 Mutex::Locker locker(m_broadcasters_mutex); 134 m_broadcasters.erase (broadcaster); 135 } 136 // Remove the broadcaster from our set of broadcasters 137 return broadcaster->RemoveListener (this, event_mask); 138 } 139 140 return false; 141} 142 143// Called when a Broadcaster is in its destuctor. We need to remove all 144// knowledge of this broadcaster and any events that it may have queued up 145void 146Listener::BroadcasterWillDestruct (Broadcaster *broadcaster) 147{ 148 // Scope for "broadcasters_locker" 149 { 150 Mutex::Locker broadcasters_locker(m_broadcasters_mutex); 151 m_broadcasters.erase (broadcaster); 152 } 153 154 // Scope for "event_locker" 155 { 156 Mutex::Locker event_locker(m_events_mutex); 157 // Remove all events for this broadcaster object. 158 event_collection::iterator pos = m_events.begin(); 159 while (pos != m_events.end()) 160 { 161 if ((*pos)->GetBroadcaster() == broadcaster) 162 pos = m_events.erase(pos); 163 else 164 ++pos; 165 } 166 167 if (m_events.empty()) 168 m_cond_wait.SetValue (false, eBroadcastNever); 169 170 } 171} 172 173void 174Listener::BroadcasterManagerWillDestruct (BroadcasterManager *manager) 175{ 176 // Just need to remove this broadcast manager from the list of managers: 177 broadcaster_manager_collection::iterator iter, end_iter = m_broadcaster_managers.end(); 178 iter = find(m_broadcaster_managers.begin(), end_iter, manager); 179 if (iter != end_iter) 180 m_broadcaster_managers.erase (iter); 181} 182 183void 184Listener::AddEvent (EventSP &event_sp) 185{ 186 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); 187 if (log) 188 log->Printf ("%p Listener('%s')::AddEvent (event_sp = {%p})", this, m_name.c_str(), event_sp.get()); 189 190 // Scope for "locker" 191 { 192 Mutex::Locker locker(m_events_mutex); 193 m_events.push_back (event_sp); 194 } 195 m_cond_wait.SetValue (true, eBroadcastAlways); 196} 197 198class EventBroadcasterMatches 199{ 200public: 201 EventBroadcasterMatches (Broadcaster *broadcaster) : 202 m_broadcaster (broadcaster) { 203 } 204 205 bool operator() (const EventSP &event_sp) const 206 { 207 if (event_sp->BroadcasterIs(m_broadcaster)) 208 return true; 209 else 210 return false; 211 } 212 213private: 214 Broadcaster *m_broadcaster; 215 216}; 217 218class EventMatcher 219{ 220public: 221 EventMatcher (Broadcaster *broadcaster, const ConstString *broadcaster_names, uint32_t num_broadcaster_names, uint32_t event_type_mask) : 222 m_broadcaster (broadcaster), 223 m_broadcaster_names (broadcaster_names), 224 m_num_broadcaster_names (num_broadcaster_names), 225 m_event_type_mask (event_type_mask) 226 { 227 } 228 229 bool operator() (const EventSP &event_sp) const 230 { 231 if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster)) 232 return false; 233 234 if (m_broadcaster_names) 235 { 236 bool found_source = false; 237 const ConstString &event_broadcaster_name = event_sp->GetBroadcaster()->GetBroadcasterName(); 238 for (uint32_t i=0; i<m_num_broadcaster_names; ++i) 239 { 240 if (m_broadcaster_names[i] == event_broadcaster_name) 241 { 242 found_source = true; 243 break; 244 } 245 } 246 if (!found_source) 247 return false; 248 } 249 250 if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType()) 251 return true; 252 return false; 253 } 254 255private: 256 Broadcaster *m_broadcaster; 257 const ConstString *m_broadcaster_names; 258 const uint32_t m_num_broadcaster_names; 259 const uint32_t m_event_type_mask; 260}; 261 262 263bool 264Listener::FindNextEventInternal 265( 266 Broadcaster *broadcaster, // NULL for any broadcaster 267 const ConstString *broadcaster_names, // NULL for any event 268 uint32_t num_broadcaster_names, 269 uint32_t event_type_mask, 270 EventSP &event_sp, 271 bool remove) 272{ 273 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); 274 275 Mutex::Locker lock(m_events_mutex); 276 277 if (m_events.empty()) 278 return false; 279 280 281 Listener::event_collection::iterator pos = m_events.end(); 282 283 if (broadcaster == NULL && broadcaster_names == NULL && event_type_mask == 0) 284 { 285 pos = m_events.begin(); 286 } 287 else 288 { 289 pos = std::find_if (m_events.begin(), m_events.end(), EventMatcher (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask)); 290 } 291 292 if (pos != m_events.end()) 293 { 294 event_sp = *pos; 295 296 if (log) 297 log->Printf ("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, broadcaster_names=%p[%u], event_type_mask=0x%8.8x, remove=%i) event %p", 298 this, 299 GetName(), 300 broadcaster, 301 broadcaster_names, 302 num_broadcaster_names, 303 event_type_mask, 304 remove, 305 event_sp.get()); 306 307 if (remove) 308 { 309 m_events.erase(pos); 310 311 if (m_events.empty()) 312 m_cond_wait.SetValue (false, eBroadcastNever); 313 } 314 315 // Unlock the event queue here. We've removed this event and are about to return 316 // it so it should be okay to get the next event off the queue here - and it might 317 // be useful to do that in the "DoOnRemoval". 318 lock.Unlock(); 319 320 // Don't call DoOnRemoval if you aren't removing the event... 321 if (remove) 322 event_sp->DoOnRemoval(); 323 324 return true; 325 } 326 327 event_sp.reset(); 328 return false; 329} 330 331Event * 332Listener::PeekAtNextEvent () 333{ 334 EventSP event_sp; 335 if (FindNextEventInternal (NULL, NULL, 0, 0, event_sp, false)) 336 return event_sp.get(); 337 return NULL; 338} 339 340Event * 341Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster) 342{ 343 EventSP event_sp; 344 if (FindNextEventInternal (broadcaster, NULL, 0, 0, event_sp, false)) 345 return event_sp.get(); 346 return NULL; 347} 348 349Event * 350Listener::PeekAtNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask) 351{ 352 EventSP event_sp; 353 if (FindNextEventInternal (broadcaster, NULL, 0, event_type_mask, event_sp, false)) 354 return event_sp.get(); 355 return NULL; 356} 357 358 359bool 360Listener::GetNextEventInternal 361( 362 Broadcaster *broadcaster, // NULL for any broadcaster 363 const ConstString *broadcaster_names, // NULL for any event 364 uint32_t num_broadcaster_names, 365 uint32_t event_type_mask, 366 EventSP &event_sp 367) 368{ 369 return FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true); 370} 371 372bool 373Listener::GetNextEvent (EventSP &event_sp) 374{ 375 return GetNextEventInternal (NULL, NULL, 0, 0, event_sp); 376} 377 378 379bool 380Listener::GetNextEventForBroadcaster (Broadcaster *broadcaster, EventSP &event_sp) 381{ 382 return GetNextEventInternal (broadcaster, NULL, 0, 0, event_sp); 383} 384 385bool 386Listener::GetNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp) 387{ 388 return GetNextEventInternal (broadcaster, NULL, 0, event_type_mask, event_sp); 389} 390 391 392bool 393Listener::WaitForEventsInternal 394( 395 const TimeValue *timeout, 396 Broadcaster *broadcaster, // NULL for any broadcaster 397 const ConstString *broadcaster_names, // NULL for any event 398 uint32_t num_broadcaster_names, 399 uint32_t event_type_mask, 400 EventSP &event_sp 401) 402{ 403 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); 404 bool timed_out = false; 405 406 if (log) 407 { 408 log->Printf ("%p Listener::WaitForEventsInternal (timeout = { %p }) for %s", 409 this, timeout, m_name.c_str()); 410 } 411 412 while (1) 413 { 414 // Note, we don't want to lock the m_events_mutex in the call to GetNextEventInternal, since the DoOnRemoval 415 // code might require that new events be serviced. For instance, the Breakpoint Command's 416 if (GetNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp)) 417 return true; 418 419 { 420 // Reset condition value to false, so we can wait for new events to be 421 // added that might meet our current filter 422 // But first poll for any new event that might satisfy our condition, and if so consume it, 423 // otherwise wait. 424 425 Mutex::Locker event_locker(m_events_mutex); 426 const bool remove = false; 427 if (FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, remove)) 428 continue; 429 else 430 m_cond_wait.SetValue (false, eBroadcastNever); 431 } 432 433 if (m_cond_wait.WaitForValueEqualTo (true, timeout, &timed_out)) 434 continue; 435 436 else if (timed_out) 437 { 438 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS); 439 if (log) 440 log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s", this, m_name.c_str()); 441 break; 442 } 443 else 444 { 445 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS); 446 if (log) 447 log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s", this, m_name.c_str()); 448 break; 449 } 450 } 451 452 return false; 453} 454 455bool 456Listener::WaitForEventForBroadcasterWithType 457( 458 const TimeValue *timeout, 459 Broadcaster *broadcaster, 460 uint32_t event_type_mask, 461 EventSP &event_sp 462) 463{ 464 return WaitForEventsInternal (timeout, broadcaster, NULL, 0, event_type_mask, event_sp); 465} 466 467bool 468Listener::WaitForEventForBroadcaster 469( 470 const TimeValue *timeout, 471 Broadcaster *broadcaster, 472 EventSP &event_sp 473) 474{ 475 return WaitForEventsInternal (timeout, broadcaster, NULL, 0, 0, event_sp); 476} 477 478bool 479Listener::WaitForEvent (const TimeValue *timeout, EventSP &event_sp) 480{ 481 return WaitForEventsInternal (timeout, NULL, NULL, 0, 0, event_sp); 482} 483 484//Listener::broadcaster_collection::iterator 485//Listener::FindBroadcasterWithMask (Broadcaster *broadcaster, uint32_t event_mask, bool exact) 486//{ 487// broadcaster_collection::iterator pos; 488// broadcaster_collection::iterator end = m_broadcasters.end(); 489// for (pos = m_broadcasters.find (broadcaster); 490// pos != end && pos->first == broadcaster; 491// ++pos) 492// { 493// if (exact) 494// { 495// if ((event_mask & pos->second.event_mask) == event_mask) 496// return pos; 497// } 498// else 499// { 500// if (event_mask & pos->second.event_mask) 501// return pos; 502// } 503// } 504// return end; 505//} 506 507size_t 508Listener::HandleBroadcastEvent (EventSP &event_sp) 509{ 510 size_t num_handled = 0; 511 Mutex::Locker locker(m_broadcasters_mutex); 512 Broadcaster *broadcaster = event_sp->GetBroadcaster(); 513 broadcaster_collection::iterator pos; 514 broadcaster_collection::iterator end = m_broadcasters.end(); 515 for (pos = m_broadcasters.find (broadcaster); 516 pos != end && pos->first == broadcaster; 517 ++pos) 518 { 519 BroadcasterInfo info = pos->second; 520 if (event_sp->GetType () & info.event_mask) 521 { 522 if (info.callback != NULL) 523 { 524 info.callback (event_sp, info.callback_user_data); 525 ++num_handled; 526 } 527 } 528 } 529 return num_handled; 530} 531 532uint32_t 533Listener::StartListeningForEventSpec (BroadcasterManager &manager, 534 const BroadcastEventSpec &event_spec) 535{ 536 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex 537 // to avoid violating the lock hierarchy (manager before broadcasters). 538 Mutex::Locker manager_locker(manager.m_manager_mutex); 539 Mutex::Locker locker(m_broadcasters_mutex); 540 541 uint32_t bits_acquired = manager.RegisterListenerForEvents(*this, event_spec); 542 if (bits_acquired) 543 m_broadcaster_managers.push_back(&manager); 544 545 return bits_acquired; 546} 547 548bool 549Listener::StopListeningForEventSpec (BroadcasterManager &manager, 550 const BroadcastEventSpec &event_spec) 551{ 552 Mutex::Locker locker(m_broadcasters_mutex); 553 return manager.UnregisterListenerForEvents (*this, event_spec); 554 555} 556 557 558