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