Listener.cpp revision 344779
1235537Sgber//===-- Listener.cpp --------------------------------------------*- C++ -*-===// 2235537Sgber// 3235537Sgber// The LLVM Compiler Infrastructure 4235537Sgber// 5235537Sgber// This file is distributed under the University of Illinois Open Source 6235537Sgber// License. See LICENSE.TXT for details. 7235537Sgber// 8235537Sgber//===----------------------------------------------------------------------===// 9235537Sgber 10235537Sgber#include "lldb/Utility/Listener.h" 11235537Sgber 12235537Sgber#include "lldb/Utility/Broadcaster.h" 13235537Sgber#include "lldb/Utility/ConstString.h" 14235537Sgber#include "lldb/Utility/Event.h" 15235537Sgber#include "lldb/Utility/Log.h" 16235537Sgber#include "lldb/Utility/Logging.h" 17235537Sgber 18235537Sgber#include "llvm/ADT/Optional.h" 19235537Sgber 20235537Sgber#include <algorithm> 21235537Sgber#include <memory> 22235537Sgber#include <utility> 23235537Sgber 24235537Sgberusing namespace lldb; 25235537Sgberusing namespace lldb_private; 26235537Sgber 27235537Sgbernamespace { 28235537Sgberclass BroadcasterManagerWPMatcher { 29235537Sgberpublic: 30235537Sgber BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp) 31235537Sgber : m_manager_sp(manager_sp) {} 32235537Sgber bool operator()(const BroadcasterManagerWP input_wp) const { 33235537Sgber BroadcasterManagerSP input_sp = input_wp.lock(); 34235537Sgber return (input_sp && input_sp == m_manager_sp); 35235537Sgber } 36235537Sgber 37235537Sgber BroadcasterManagerSP m_manager_sp; 38235537Sgber}; 39235537Sgber} // anonymous namespace 40235537Sgber 41235537SgberListener::Listener(const char *name) 42235537Sgber : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(), 43235537Sgber m_events_mutex() { 44235537Sgber Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 45235537Sgber if (log != nullptr) 46235537Sgber log->Printf("%p Listener::Listener('%s')", static_cast<void *>(this), 47235537Sgber m_name.c_str()); 48235537Sgber} 49235537Sgber 50235537SgberListener::~Listener() { 51235537Sgber Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 52235537Sgber 53235537Sgber Clear(); 54235537Sgber 55235537Sgber if (log) 56235537Sgber log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), 57235537Sgber __FUNCTION__, m_name.c_str()); 58235537Sgber} 59235537Sgber 60235537Sgbervoid Listener::Clear() { 61235537Sgber Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 62235537Sgber std::lock_guard<std::recursive_mutex> broadcasters_guard( 63235537Sgber m_broadcasters_mutex); 64235537Sgber broadcaster_collection::iterator pos, end = m_broadcasters.end(); 65235537Sgber for (pos = m_broadcasters.begin(); pos != end; ++pos) { 66235537Sgber Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock()); 67235537Sgber if (broadcaster_sp) 68235537Sgber broadcaster_sp->RemoveListener(this, pos->second.event_mask); 69235537Sgber } 70235537Sgber m_broadcasters.clear(); 71235537Sgber 72235537Sgber std::lock_guard<std::mutex> events_guard(m_events_mutex); 73235537Sgber m_events.clear(); 74235537Sgber size_t num_managers = m_broadcaster_managers.size(); 75235537Sgber 76235537Sgber for (size_t i = 0; i < num_managers; i++) { 77235537Sgber BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock()); 78235537Sgber if (manager_sp) 79235537Sgber manager_sp->RemoveListener(this); 80235537Sgber } 81235537Sgber 82235537Sgber if (log) 83235537Sgber log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), 84235537Sgber __FUNCTION__, m_name.c_str()); 85235537Sgber} 86235537Sgber 87235537Sgberuint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, 88235537Sgber uint32_t event_mask) { 89235537Sgber if (broadcaster) { 90235537Sgber // Scope for "locker" 91235537Sgber // Tell the broadcaster to add this object as a listener 92235537Sgber { 93235537Sgber std::lock_guard<std::recursive_mutex> broadcasters_guard( 94235537Sgber m_broadcasters_mutex); 95235537Sgber Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); 96235537Sgber m_broadcasters.insert( 97235537Sgber std::make_pair(impl_wp, BroadcasterInfo(event_mask))); 98235537Sgber } 99235537Sgber 100235537Sgber uint32_t acquired_mask = 101235537Sgber broadcaster->AddListener(this->shared_from_this(), event_mask); 102235537Sgber 103235537Sgber Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 104235537Sgber if (log != nullptr) 105235537Sgber log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " 106235537Sgber "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", 107235537Sgber static_cast<void *>(this), static_cast<void *>(broadcaster), 108235537Sgber event_mask, acquired_mask, m_name.c_str()); 109235537Sgber 110235537Sgber return acquired_mask; 111235537Sgber } 112235537Sgber return 0; 113235537Sgber} 114235537Sgber 115235537Sgberuint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, 116235537Sgber uint32_t event_mask, 117235537Sgber HandleBroadcastCallback callback, 118235537Sgber void *callback_user_data) { 119235537Sgber if (broadcaster) { 120235537Sgber // Scope for "locker" 121235537Sgber // Tell the broadcaster to add this object as a listener 122235537Sgber { 123235537Sgber std::lock_guard<std::recursive_mutex> broadcasters_guard( 124235537Sgber m_broadcasters_mutex); 125235537Sgber Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); 126235537Sgber m_broadcasters.insert(std::make_pair( 127235537Sgber impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data))); 128235537Sgber } 129235537Sgber 130235537Sgber uint32_t acquired_mask = 131235537Sgber broadcaster->AddListener(this->shared_from_this(), event_mask); 132235537Sgber 133235537Sgber Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 134235537Sgber if (log != nullptr) { 135235537Sgber void **pointer = reinterpret_cast<void **>(&callback); 136235537Sgber log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " 137235537Sgber "mask = 0x%8.8x, callback = %p, user_data = %p) " 138235537Sgber "acquired_mask = 0x%8.8x for %s", 139235537Sgber static_cast<void *>(this), static_cast<void *>(broadcaster), 140235537Sgber event_mask, *pointer, static_cast<void *>(callback_user_data), 141235537Sgber acquired_mask, m_name.c_str()); 142235537Sgber } 143235537Sgber 144235537Sgber return acquired_mask; 145235537Sgber } 146235537Sgber return 0; 147235537Sgber} 148235537Sgber 149235537Sgberbool Listener::StopListeningForEvents(Broadcaster *broadcaster, 150235537Sgber uint32_t event_mask) { 151235537Sgber if (broadcaster) { 152235537Sgber // Scope for "locker" 153235537Sgber { 154235537Sgber std::lock_guard<std::recursive_mutex> broadcasters_guard( 155235537Sgber m_broadcasters_mutex); 156235537Sgber m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); 157235537Sgber } 158235537Sgber // Remove the broadcaster from our set of broadcasters 159235537Sgber return broadcaster->RemoveListener(this->shared_from_this(), event_mask); 160235537Sgber } 161235537Sgber 162235537Sgber return false; 163235537Sgber} 164235537Sgber 165235537Sgber// Called when a Broadcaster is in its destructor. We need to remove all 166// knowledge of this broadcaster and any events that it may have queued up 167void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) { 168 // Scope for "broadcasters_locker" 169 { 170 std::lock_guard<std::recursive_mutex> broadcasters_guard( 171 m_broadcasters_mutex); 172 m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); 173 } 174 175 // Scope for "event_locker" 176 { 177 std::lock_guard<std::mutex> events_guard(m_events_mutex); 178 // Remove all events for this broadcaster object. 179 event_collection::iterator pos = m_events.begin(); 180 while (pos != m_events.end()) { 181 if ((*pos)->GetBroadcaster() == broadcaster) 182 pos = m_events.erase(pos); 183 else 184 ++pos; 185 } 186 } 187} 188 189void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { 190 // Just need to remove this broadcast manager from the list of managers: 191 broadcaster_manager_collection::iterator iter, 192 end_iter = m_broadcaster_managers.end(); 193 BroadcasterManagerWP manager_wp; 194 195 BroadcasterManagerWPMatcher matcher(manager_sp); 196 iter = std::find_if<broadcaster_manager_collection::iterator, 197 BroadcasterManagerWPMatcher>( 198 m_broadcaster_managers.begin(), end_iter, matcher); 199 if (iter != end_iter) 200 m_broadcaster_managers.erase(iter); 201} 202 203void Listener::AddEvent(EventSP &event_sp) { 204 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 205 if (log != nullptr) 206 log->Printf("%p Listener('%s')::AddEvent (event_sp = {%p})", 207 static_cast<void *>(this), m_name.c_str(), 208 static_cast<void *>(event_sp.get())); 209 210 std::lock_guard<std::mutex> guard(m_events_mutex); 211 m_events.push_back(event_sp); 212 m_events_condition.notify_all(); 213} 214 215class EventBroadcasterMatches { 216public: 217 EventBroadcasterMatches(Broadcaster *broadcaster) 218 : m_broadcaster(broadcaster) {} 219 220 bool operator()(const EventSP &event_sp) const { 221 return event_sp->BroadcasterIs(m_broadcaster); 222 } 223 224private: 225 Broadcaster *m_broadcaster; 226}; 227 228class EventMatcher { 229public: 230 EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names, 231 uint32_t num_broadcaster_names, uint32_t event_type_mask) 232 : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names), 233 m_num_broadcaster_names(num_broadcaster_names), 234 m_event_type_mask(event_type_mask) {} 235 236 bool operator()(const EventSP &event_sp) const { 237 if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster)) 238 return false; 239 240 if (m_broadcaster_names) { 241 bool found_source = false; 242 const ConstString &event_broadcaster_name = 243 event_sp->GetBroadcaster()->GetBroadcasterName(); 244 for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) { 245 if (m_broadcaster_names[i] == event_broadcaster_name) { 246 found_source = true; 247 break; 248 } 249 } 250 if (!found_source) 251 return false; 252 } 253 254 return m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType(); 255 } 256 257private: 258 Broadcaster *m_broadcaster; 259 const ConstString *m_broadcaster_names; 260 const uint32_t m_num_broadcaster_names; 261 const uint32_t m_event_type_mask; 262}; 263 264bool Listener::FindNextEventInternal( 265 std::unique_lock<std::mutex> &lock, 266 Broadcaster *broadcaster, // nullptr for any broadcaster 267 const ConstString *broadcaster_names, // nullptr for any event 268 uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp, 269 bool remove) { 270 // NOTE: callers of this function must lock m_events_mutex using a 271 // Mutex::Locker 272 // and pass the locker as the first argument. m_events_mutex is no longer 273 // recursive. 274 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 275 276 if (m_events.empty()) 277 return false; 278 279 Listener::event_collection::iterator pos = m_events.end(); 280 281 if (broadcaster == nullptr && broadcaster_names == nullptr && 282 event_type_mask == 0) { 283 pos = m_events.begin(); 284 } else { 285 pos = std::find_if(m_events.begin(), m_events.end(), 286 EventMatcher(broadcaster, broadcaster_names, 287 num_broadcaster_names, event_type_mask)); 288 } 289 290 if (pos != m_events.end()) { 291 event_sp = *pos; 292 293 if (log != nullptr) 294 log->Printf("%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 if (log) 371 log->Printf("%p Listener::GetEventInternal() timed out for %s", 372 static_cast<void *>(this), m_name.c_str()); 373 return false; 374 } else if (result != std::cv_status::no_timeout) { 375 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); 376 if (log) 377 log->Printf("%p Listener::GetEventInternal() unknown error for %s", 378 static_cast<void *>(this), m_name.c_str()); 379 return false; 380 } 381 } 382 } 383 384 return false; 385} 386 387bool Listener::GetEventForBroadcasterWithType( 388 Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp, 389 const Timeout<std::micro> &timeout) { 390 return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask, 391 event_sp); 392} 393 394bool Listener::GetEventForBroadcaster(Broadcaster *broadcaster, 395 EventSP &event_sp, 396 const Timeout<std::micro> &timeout) { 397 return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp); 398} 399 400bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) { 401 return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp); 402} 403 404size_t Listener::HandleBroadcastEvent(EventSP &event_sp) { 405 size_t num_handled = 0; 406 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 407 Broadcaster *broadcaster = event_sp->GetBroadcaster(); 408 if (!broadcaster) 409 return 0; 410 broadcaster_collection::iterator pos; 411 broadcaster_collection::iterator end = m_broadcasters.end(); 412 Broadcaster::BroadcasterImplSP broadcaster_impl_sp( 413 broadcaster->GetBroadcasterImpl()); 414 for (pos = m_broadcasters.find(broadcaster_impl_sp); 415 pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) { 416 BroadcasterInfo info = pos->second; 417 if (event_sp->GetType() & info.event_mask) { 418 if (info.callback != nullptr) { 419 info.callback(event_sp, info.callback_user_data); 420 ++num_handled; 421 } 422 } 423 } 424 return num_handled; 425} 426 427uint32_t 428Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp, 429 const BroadcastEventSpec &event_spec) { 430 if (!manager_sp) 431 return 0; 432 433 // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to 434 // avoid violating the lock hierarchy (manager before broadcasters). 435 std::lock_guard<std::recursive_mutex> manager_guard( 436 manager_sp->m_manager_mutex); 437 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 438 439 uint32_t bits_acquired = manager_sp->RegisterListenerForEvents( 440 this->shared_from_this(), event_spec); 441 if (bits_acquired) { 442 broadcaster_manager_collection::iterator iter, 443 end_iter = m_broadcaster_managers.end(); 444 BroadcasterManagerWP manager_wp(manager_sp); 445 BroadcasterManagerWPMatcher matcher(manager_sp); 446 iter = std::find_if<broadcaster_manager_collection::iterator, 447 BroadcasterManagerWPMatcher>( 448 m_broadcaster_managers.begin(), end_iter, matcher); 449 if (iter == end_iter) 450 m_broadcaster_managers.push_back(manager_wp); 451 } 452 453 return bits_acquired; 454} 455 456bool Listener::StopListeningForEventSpec(BroadcasterManagerSP manager_sp, 457 const BroadcastEventSpec &event_spec) { 458 if (!manager_sp) 459 return false; 460 461 std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 462 return manager_sp->UnregisterListenerForEvents(this->shared_from_this(), 463 event_spec); 464} 465 466ListenerSP Listener::MakeListener(const char *name) { 467 return ListenerSP(new Listener(name)); 468} 469