1 //===-- Listener.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/Listener.h" 10 #include "lldb/Utility/Broadcaster.h" 11 #include "lldb/Utility/ConstString.h" 12 #include "lldb/Utility/Event.h" 13 #include "lldb/Utility/LLDBLog.h" 14 15 #include <algorithm> 16 #include <memory> 17 #include <utility> 18 19 using namespace lldb; 20 using namespace lldb_private; 21 22 namespace { 23 class BroadcasterManagerWPMatcher { 24 public: 25 BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp) 26 : m_manager_sp(std::move(manager_sp)) {} 27 bool operator()(const BroadcasterManagerWP &input_wp) const { 28 BroadcasterManagerSP input_sp = input_wp.lock(); 29 return (input_sp && input_sp == m_manager_sp); 30 } 31 32 BroadcasterManagerSP m_manager_sp; 33 }; 34 } // anonymous namespace 35 36 Listener::Listener(const char *name) 37 : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(), 38 m_events_mutex() { 39 Log *log = GetLog(LLDBLog::Object); 40 if (log != nullptr) 41 LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this), 42 m_name.c_str()); 43 } 44 45 Listener::~Listener() { 46 Log *log = GetLog(LLDBLog::Object); 47 48 Clear(); 49 50 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this), 51 __FUNCTION__, m_name.c_str()); 52 } 53 54 void Listener::Clear() { 55 Log *log = GetLog(LLDBLog::Object); 56 std::lock_guard<std::recursive_mutex> broadcasters_guard( 57 m_broadcasters_mutex); 58 broadcaster_collection::iterator pos, end = m_broadcasters.end(); 59 for (pos = m_broadcasters.begin(); pos != end; ++pos) { 60 Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock()); 61 if (broadcaster_sp) 62 broadcaster_sp->RemoveListener(this, pos->second.event_mask); 63 } 64 m_broadcasters.clear(); 65 66 std::lock_guard<std::mutex> events_guard(m_events_mutex); 67 m_events.clear(); 68 size_t num_managers = m_broadcaster_managers.size(); 69 70 for (size_t i = 0; i < num_managers; i++) { 71 BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock()); 72 if (manager_sp) 73 manager_sp->RemoveListener(this); 74 } 75 76 LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this), 77 __FUNCTION__, m_name.c_str()); 78 } 79 80 uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, 81 uint32_t event_mask) { 82 if (broadcaster) { 83 // Scope for "locker" 84 // Tell the broadcaster to add this object as a listener 85 { 86 std::lock_guard<std::recursive_mutex> broadcasters_guard( 87 m_broadcasters_mutex); 88 Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); 89 m_broadcasters.insert( 90 std::make_pair(impl_wp, BroadcasterInfo(event_mask))); 91 } 92 93 uint32_t acquired_mask = 94 broadcaster->AddListener(this->shared_from_this(), event_mask); 95 96 Log *log = GetLog(LLDBLog::Events); 97 if (log != nullptr) 98 LLDB_LOGF(log, 99 "%p Listener::StartListeningForEvents (broadcaster = %p, " 100 "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", 101 static_cast<void *>(this), static_cast<void *>(broadcaster), 102 event_mask, acquired_mask, m_name.c_str()); 103 104 return acquired_mask; 105 } 106 return 0; 107 } 108 109 uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, 110 uint32_t event_mask, 111 HandleBroadcastCallback callback, 112 void *callback_user_data) { 113 if (broadcaster) { 114 // Scope for "locker" 115 // Tell the broadcaster to add this object as a listener 116 { 117 std::lock_guard<std::recursive_mutex> broadcasters_guard( 118 m_broadcasters_mutex); 119 Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); 120 m_broadcasters.insert(std::make_pair( 121 impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data))); 122 } 123 124 uint32_t acquired_mask = 125 broadcaster->AddListener(this->shared_from_this(), event_mask); 126 127 Log *log = GetLog(LLDBLog::Events); 128 if (log != nullptr) { 129 void **pointer = reinterpret_cast<void **>(&callback); 130 LLDB_LOGF(log, 131 "%p Listener::StartListeningForEvents (broadcaster = %p, " 132 "mask = 0x%8.8x, callback = %p, user_data = %p) " 133 "acquired_mask = 0x%8.8x for %s", 134 static_cast<void *>(this), static_cast<void *>(broadcaster), 135 event_mask, *pointer, static_cast<void *>(callback_user_data), 136 acquired_mask, m_name.c_str()); 137 } 138 139 return acquired_mask; 140 } 141 return 0; 142 } 143 144 bool Listener::StopListeningForEvents(Broadcaster *broadcaster, 145 uint32_t event_mask) { 146 if (broadcaster) { 147 // Scope for "locker" 148 { 149 std::lock_guard<std::recursive_mutex> broadcasters_guard( 150 m_broadcasters_mutex); 151 m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); 152 } 153 // Remove the broadcaster from our set of broadcasters 154 return broadcaster->RemoveListener(this->shared_from_this(), event_mask); 155 } 156 157 return false; 158 } 159 160 // Called when a Broadcaster is in its destructor. We need to remove all 161 // knowledge of this broadcaster and any events that it may have queued up 162 void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) { 163 // Scope for "broadcasters_locker" 164 { 165 std::lock_guard<std::recursive_mutex> broadcasters_guard( 166 m_broadcasters_mutex); 167 m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); 168 } 169 170 // Scope for "event_locker" 171 { 172 std::lock_guard<std::mutex> events_guard(m_events_mutex); 173 // Remove all events for this broadcaster object. 174 event_collection::iterator pos = m_events.begin(); 175 while (pos != m_events.end()) { 176 if ((*pos)->GetBroadcaster() == broadcaster) 177 pos = m_events.erase(pos); 178 else 179 ++pos; 180 } 181 } 182 } 183 184 void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { 185 // Just need to remove this broadcast manager from the list of managers: 186 broadcaster_manager_collection::iterator iter, 187 end_iter = m_broadcaster_managers.end(); 188 BroadcasterManagerWP manager_wp; 189 190 BroadcasterManagerWPMatcher matcher(std::move(manager_sp)); 191 iter = std::find_if<broadcaster_manager_collection::iterator, 192 BroadcasterManagerWPMatcher>( 193 m_broadcaster_managers.begin(), end_iter, matcher); 194 if (iter != end_iter) 195 m_broadcaster_managers.erase(iter); 196 } 197 198 void Listener::AddEvent(EventSP &event_sp) { 199 Log *log = GetLog(LLDBLog::Events); 200 if (log != nullptr) 201 LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})", 202 static_cast<void *>(this), m_name.c_str(), 203 static_cast<void *>(event_sp.get())); 204 205 std::lock_guard<std::mutex> guard(m_events_mutex); 206 m_events.push_back(event_sp); 207 m_events_condition.notify_all(); 208 } 209 210 class EventBroadcasterMatches { 211 public: 212 EventBroadcasterMatches(Broadcaster *broadcaster) 213 : m_broadcaster(broadcaster) {} 214 215 bool operator()(const EventSP &event_sp) const { 216 return event_sp->BroadcasterIs(m_broadcaster); 217 } 218 219 private: 220 Broadcaster *m_broadcaster; 221 }; 222 223 class EventMatcher { 224 public: 225 EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names, 226 uint32_t num_broadcaster_names, uint32_t event_type_mask) 227 : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names), 228 m_num_broadcaster_names(num_broadcaster_names), 229 m_event_type_mask(event_type_mask) {} 230 231 bool operator()(const EventSP &event_sp) const { 232 if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster)) 233 return false; 234 235 if (m_broadcaster_names) { 236 bool found_source = false; 237 ConstString event_broadcaster_name = 238 event_sp->GetBroadcaster()->GetBroadcasterName(); 239 for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) { 240 if (m_broadcaster_names[i] == event_broadcaster_name) { 241 found_source = true; 242 break; 243 } 244 } 245 if (!found_source) 246 return false; 247 } 248 249 return m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType(); 250 } 251 252 private: 253 Broadcaster *m_broadcaster; 254 const ConstString *m_broadcaster_names; 255 const uint32_t m_num_broadcaster_names; 256 const uint32_t m_event_type_mask; 257 }; 258 259 bool Listener::FindNextEventInternal( 260 std::unique_lock<std::mutex> &lock, 261 Broadcaster *broadcaster, // nullptr for any broadcaster 262 const ConstString *broadcaster_names, // nullptr for any event 263 uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp, 264 bool remove) { 265 // NOTE: callers of this function must lock m_events_mutex using a 266 // Mutex::Locker 267 // and pass the locker as the first argument. m_events_mutex is no longer 268 // recursive. 269 Log *log = GetLog(LLDBLog::Events); 270 271 if (m_events.empty()) 272 return false; 273 274 Listener::event_collection::iterator pos = m_events.end(); 275 276 if (broadcaster == nullptr && broadcaster_names == nullptr && 277 event_type_mask == 0) { 278 pos = m_events.begin(); 279 } else { 280 pos = std::find_if(m_events.begin(), m_events.end(), 281 EventMatcher(broadcaster, broadcaster_names, 282 num_broadcaster_names, event_type_mask)); 283 } 284 285 if (pos != m_events.end()) { 286 event_sp = *pos; 287 288 if (log != nullptr) 289 LLDB_LOGF(log, 290 "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " 291 "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " 292 "remove=%i) event %p", 293 static_cast<void *>(this), GetName(), 294 static_cast<void *>(broadcaster), 295 static_cast<const void *>(broadcaster_names), 296 num_broadcaster_names, event_type_mask, remove, 297 static_cast<void *>(event_sp.get())); 298 299 if (remove) { 300 m_events.erase(pos); 301 // Unlock the event queue here. We've removed this event and are about 302 // to return it so it should be okay to get the next event off the queue 303 // here - and it might be useful to do that in the "DoOnRemoval". 304 lock.unlock(); 305 event_sp->DoOnRemoval(); 306 } 307 return true; 308 } 309 310 event_sp.reset(); 311 return false; 312 } 313 314 Event *Listener::PeekAtNextEvent() { 315 std::unique_lock<std::mutex> guard(m_events_mutex); 316 EventSP event_sp; 317 if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false)) 318 return event_sp.get(); 319 return nullptr; 320 } 321 322 Event *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) { 323 std::unique_lock<std::mutex> guard(m_events_mutex); 324 EventSP event_sp; 325 if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false)) 326 return event_sp.get(); 327 return nullptr; 328 } 329 330 Event * 331 Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, 332 uint32_t event_type_mask) { 333 std::unique_lock<std::mutex> guard(m_events_mutex); 334 EventSP event_sp; 335 if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask, 336 event_sp, false)) 337 return event_sp.get(); 338 return nullptr; 339 } 340 341 bool Listener::GetEventInternal( 342 const Timeout<std::micro> &timeout, 343 Broadcaster *broadcaster, // nullptr for any broadcaster 344 const ConstString *broadcaster_names, // nullptr for any event 345 uint32_t num_broadcaster_names, uint32_t event_type_mask, 346 EventSP &event_sp) { 347 Log *log = GetLog(LLDBLog::Events); 348 LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name); 349 350 std::unique_lock<std::mutex> lock(m_events_mutex); 351 352 while (true) { 353 if (FindNextEventInternal(lock, broadcaster, broadcaster_names, 354 num_broadcaster_names, event_type_mask, event_sp, 355 true)) { 356 return true; 357 } else { 358 std::cv_status result = std::cv_status::no_timeout; 359 if (!timeout) 360 m_events_condition.wait(lock); 361 else 362 result = m_events_condition.wait_for(lock, *timeout); 363 364 if (result == std::cv_status::timeout) { 365 log = GetLog(LLDBLog::Events); 366 LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s", 367 static_cast<void *>(this), m_name.c_str()); 368 return false; 369 } else if (result != std::cv_status::no_timeout) { 370 log = GetLog(LLDBLog::Events); 371 LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s", 372 static_cast<void *>(this), m_name.c_str()); 373 return false; 374 } 375 } 376 } 377 378 return false; 379 } 380 381 bool Listener::GetEventForBroadcasterWithType( 382 Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp, 383 const Timeout<std::micro> &timeout) { 384 return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask, 385 event_sp); 386 } 387 388 bool Listener::GetEventForBroadcaster(Broadcaster *broadcaster, 389 EventSP &event_sp, 390 const Timeout<std::micro> &timeout) { 391 return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp); 392 } 393 394 bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) { 395 return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp); 396 } 397 398 size_t Listener::HandleBroadcastEvent(EventSP &event_sp) { 399 size_t num_handled = 0; 400 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 401 Broadcaster *broadcaster = event_sp->GetBroadcaster(); 402 if (!broadcaster) 403 return 0; 404 broadcaster_collection::iterator pos; 405 broadcaster_collection::iterator end = m_broadcasters.end(); 406 Broadcaster::BroadcasterImplSP broadcaster_impl_sp( 407 broadcaster->GetBroadcasterImpl()); 408 for (pos = m_broadcasters.find(broadcaster_impl_sp); 409 pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) { 410 BroadcasterInfo info = pos->second; 411 if (event_sp->GetType() & info.event_mask) { 412 if (info.callback != nullptr) { 413 info.callback(event_sp, info.callback_user_data); 414 ++num_handled; 415 } 416 } 417 } 418 return num_handled; 419 } 420 421 uint32_t 422 Listener::StartListeningForEventSpec(const BroadcasterManagerSP &manager_sp, 423 const BroadcastEventSpec &event_spec) { 424 if (!manager_sp) 425 return 0; 426 427 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to 428 // avoid violating the lock hierarchy (manager before broadcasters). 429 std::lock_guard<std::recursive_mutex> manager_guard( 430 manager_sp->m_manager_mutex); 431 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 432 433 uint32_t bits_acquired = manager_sp->RegisterListenerForEvents( 434 this->shared_from_this(), event_spec); 435 if (bits_acquired) { 436 broadcaster_manager_collection::iterator iter, 437 end_iter = m_broadcaster_managers.end(); 438 BroadcasterManagerWP manager_wp(manager_sp); 439 BroadcasterManagerWPMatcher matcher(manager_sp); 440 iter = std::find_if<broadcaster_manager_collection::iterator, 441 BroadcasterManagerWPMatcher>( 442 m_broadcaster_managers.begin(), end_iter, matcher); 443 if (iter == end_iter) 444 m_broadcaster_managers.push_back(manager_wp); 445 } 446 447 return bits_acquired; 448 } 449 450 bool Listener::StopListeningForEventSpec(const BroadcasterManagerSP &manager_sp, 451 const BroadcastEventSpec &event_spec) { 452 if (!manager_sp) 453 return false; 454 455 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 456 return manager_sp->UnregisterListenerForEvents(this->shared_from_this(), 457 event_spec); 458 } 459 460 ListenerSP Listener::MakeListener(const char *name) { 461 return ListenerSP(new Listener(name)); 462 } 463