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