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