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