blob: ec91f8d8a7f1b23a5cd2c400cf9f4caac55e6157 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Broadcaster.cpp -----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/Broadcaster.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Log.h"
17#include "lldb/Core/Event.h"
Jim Ingham583bbb12016-03-07 21:50:25 +000018#include "lldb/Core/Listener.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020
21using namespace lldb;
22using namespace lldb_private;
23
Jim Ingham583bbb12016-03-07 21:50:25 +000024Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, const char *name) :
25 m_broadcaster_sp(new BroadcasterImpl(*this)),
26 m_manager_sp(manager_sp),
27 m_broadcaster_name(name)
Jim Ingham583bbb12016-03-07 21:50:25 +000028{
Tamas Berghammer77b93ad2016-03-08 13:33:14 +000029 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
30 if (log)
31 log->Printf ("%p Broadcaster::Broadcaster(\"%s\")",
32 static_cast<void*>(this), GetBroadcasterName().AsCString());
Jim Ingham583bbb12016-03-07 21:50:25 +000033}
34
35Broadcaster::BroadcasterImpl::BroadcasterImpl (Broadcaster &broadcaster) :
36 m_broadcaster(broadcaster),
Greg Claytoncfd1ace2010-10-31 03:01:06 +000037 m_listeners (),
38 m_listeners_mutex (Mutex::eMutexTypeRecursive),
Jim Inghamc4f4f7212011-02-08 05:16:50 +000039 m_hijacking_listeners(),
Jim Ingham583bbb12016-03-07 21:50:25 +000040 m_hijacking_masks()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041{
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042}
43
44Broadcaster::~Broadcaster()
45{
Greg Clayton5160ce52013-03-27 23:08:40 +000046 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +000048 log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")",
49 static_cast<void*>(this), m_broadcaster_name.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050
Greg Clayton1ed54f52011-10-01 00:45:15 +000051 Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052}
53
Greg Clayton1ed54f52011-10-01 00:45:15 +000054void
Jim Ingham4bddaeb2012-02-16 06:50:00 +000055Broadcaster::CheckInWithManager ()
56{
Jim Ingham583bbb12016-03-07 21:50:25 +000057 if (m_manager_sp)
Jim Ingham4bddaeb2012-02-16 06:50:00 +000058 {
Jim Ingham583bbb12016-03-07 21:50:25 +000059 m_manager_sp->SignUpListenersForBroadcaster(*this);
Jim Ingham4bddaeb2012-02-16 06:50:00 +000060 }
61}
62
63void
Greg Clayton1e20f022016-05-12 22:58:52 +000064Broadcaster::BroadcasterImpl::ListenerIterator (std::function <bool (const lldb::ListenerSP &listener_sp, uint32_t &event_mask)> const &callback)
65{
66 // Private iterator that should be used by everyone except BroadcasterImpl::RemoveListener().
67 // We have weak pointers to our listeners which means that at any point the listener can
68 // expire which means we will need to take it out of our list. To take care of this, we
69 // iterate and check that the weak pointer can be made into a valid shared pointer before
70 // we call the callback. If the weak pointer has expired, we remove it from our list.
71 collection::iterator pos = m_listeners.begin();
72 while (pos != m_listeners.end())
73 {
74 lldb::ListenerSP curr_listener_sp(pos->first.lock());
75 if (curr_listener_sp)
76 {
77 if (callback(curr_listener_sp, pos->second))
78 ++pos; // Keep iterating
79 else
80 return; // Done iterating
81 }
82 else
83 {
84 // The listener has been expired. Remove this entry.
85 pos = m_listeners.erase(pos);
86 }
87 }
88}
89
90void
Jim Ingham583bbb12016-03-07 21:50:25 +000091Broadcaster::BroadcasterImpl::Clear()
Greg Clayton1ed54f52011-10-01 00:45:15 +000092{
93 Mutex::Locker listeners_locker(m_listeners_mutex);
94
95 // Make sure the listener forgets about this broadcaster. We do
96 // this in the broadcaster in case the broadcaster object initiates
97 // the removal.
Greg Clayton1e20f022016-05-12 22:58:52 +000098
99 ListenerIterator([this](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
100 curr_listener_sp->BroadcasterWillDestruct (&m_broadcaster);
101 return true; // Keep iterating
102 });
Greg Clayton1ed54f52011-10-01 00:45:15 +0000103
104 m_listeners.clear();
105}
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000106
Jim Ingham583bbb12016-03-07 21:50:25 +0000107Broadcaster *
108Broadcaster::BroadcasterImpl::GetBroadcaster()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109{
Jim Ingham583bbb12016-03-07 21:50:25 +0000110 return &m_broadcaster;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111}
112
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000113bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000114Broadcaster::BroadcasterImpl::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000115{
116 uint32_t num_names_added = 0;
117 if (event_mask && !m_event_names.empty())
118 {
119 event_names_map::const_iterator end = m_event_names.end();
120 for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1)
121 {
122 if (mask & 1)
123 {
124 event_names_map::const_iterator pos = m_event_names.find(bit);
125 if (pos != end)
126 {
127 if (num_names_added > 0)
128 s.PutCString(", ");
129
130 if (prefix_with_broadcaster_name)
131 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000132 s.PutCString (GetBroadcasterName());
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000133 s.PutChar('.');
134 }
135 s.PutCString(pos->second.c_str());
136 ++num_names_added;
137 }
138 }
139 }
140 }
141 return num_names_added > 0;
142}
143
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000144void
Greg Clayton1e20f022016-05-12 22:58:52 +0000145Broadcaster::AddInitialEventsToListener (const lldb::ListenerSP &listener_sp, uint32_t requested_events)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000146{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147}
148
149uint32_t
Greg Clayton1e20f022016-05-12 22:58:52 +0000150Broadcaster::BroadcasterImpl::AddListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151{
Jim Ingham583bbb12016-03-07 21:50:25 +0000152 if (!listener_sp)
Johnny Chend161a852010-12-22 19:29:31 +0000153 return 0;
154
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000155 Mutex::Locker locker(m_listeners_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000157 // See if we already have this listener, and if so, update its mask
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158
Greg Clayton1e20f022016-05-12 22:58:52 +0000159 bool handled = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160
Greg Clayton1e20f022016-05-12 22:58:52 +0000161 ListenerIterator([this, &listener_sp, &handled, event_mask](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
162 if (curr_listener_sp == listener_sp)
163 {
164 handled = true;
165 curr_event_mask |= event_mask;
166 m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask);
167 return false; // Stop iterating
168 }
169 return true; // Keep iterating
170 });
171
172 if (!handled)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 {
Greg Clayton1e20f022016-05-12 22:58:52 +0000174 // Grant a new listener the available event bits
175 m_listeners.push_back(std::make_pair(lldb::ListenerWP(listener_sp), event_mask));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000176
177 // Individual broadcasters decide whether they have outstanding data when a
178 // listener attaches, and insert it into the listener with this method.
Greg Clayton1e20f022016-05-12 22:58:52 +0000179 m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180 }
181
182 // Return the event bits that were granted to the listener
Greg Clayton1e20f022016-05-12 22:58:52 +0000183 return event_mask;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000184}
185
186bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000187Broadcaster::BroadcasterImpl::EventTypeHasListeners (uint32_t event_type)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000189 Mutex::Locker locker (m_listeners_mutex);
Jim Ingham30f9b212010-10-11 23:53:14 +0000190
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000191 if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back())
Jim Ingham30f9b212010-10-11 23:53:14 +0000192 return true;
193
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000194 if (m_listeners.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000195 return false;
196
Greg Clayton1e20f022016-05-12 22:58:52 +0000197 bool result = false;
198 ListenerIterator([this, event_type, &result](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
199
200 if (curr_event_mask & event_type)
201 {
202 result = true;
203 return false; // Stop iterating
204 }
205 else
206 {
207 return true; // Keep iterating
208 }
209 });
210 return result;
211}
212
213bool
214Broadcaster::BroadcasterImpl::RemoveListener (lldb_private::Listener *listener, uint32_t event_mask)
215{
216 if (listener)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000217 {
Greg Clayton1e20f022016-05-12 22:58:52 +0000218 Mutex::Locker locker(m_listeners_mutex);
219 collection::iterator pos = m_listeners.begin();
220 // See if we already have this listener, and if so, update its mask
221 while (pos != m_listeners.end())
222 {
223 lldb::ListenerSP curr_listener_sp(pos->first.lock());
224 if (curr_listener_sp)
225 {
226 if (curr_listener_sp.get() == listener)
227 {
228 // Relinquish all event bits in "event_mask"
229 pos->second &= ~event_mask;
230 // If all bits have been relinquished then remove this listener
231 if (pos->second == 0)
232 m_listeners.erase (pos);
233 return true;
234 }
235 ++pos;
236 }
237 else
238 {
239 // The listener has been destroyed since we couldn't turn the std::weak_ptr
240 // into a valid shared pointer, so we can remove it.
241 pos = m_listeners.erase (pos);
242 }
243 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 }
245 return false;
246}
247
248bool
Greg Clayton1e20f022016-05-12 22:58:52 +0000249Broadcaster::BroadcasterImpl::RemoveListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000250{
Greg Clayton1e20f022016-05-12 22:58:52 +0000251 return RemoveListener (listener_sp.get(), event_mask);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000252}
253
254void
Jim Ingham583bbb12016-03-07 21:50:25 +0000255Broadcaster::BroadcasterImpl::BroadcastEvent (EventSP &event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256{
257 return PrivateBroadcastEvent (event_sp, false);
258}
259
260void
Jim Ingham583bbb12016-03-07 21:50:25 +0000261Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (EventSP &event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000262{
263 return PrivateBroadcastEvent (event_sp, true);
264}
265
266void
Jim Ingham583bbb12016-03-07 21:50:25 +0000267Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000268{
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000269 // Can't add a nullptr event...
270 if (!event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271 return;
272
273 // Update the broadcaster on this event
Jim Ingham583bbb12016-03-07 21:50:25 +0000274 event_sp->SetBroadcaster (&m_broadcaster);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000275
276 const uint32_t event_type = event_sp->GetType();
277
Greg Clayton1e20f022016-05-12 22:58:52 +0000278 Mutex::Locker locker(m_listeners_mutex);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000279
Jim Ingham583bbb12016-03-07 21:50:25 +0000280 ListenerSP hijacking_listener_sp;
281
Greg Clayton11177952011-02-10 06:51:22 +0000282 if (!m_hijacking_listeners.empty())
283 {
284 assert (!m_hijacking_masks.empty());
Jim Ingham583bbb12016-03-07 21:50:25 +0000285 hijacking_listener_sp = m_hijacking_listeners.back();
Greg Clayton11177952011-02-10 06:51:22 +0000286 if ((event_type & m_hijacking_masks.back()) == 0)
Jim Ingham583bbb12016-03-07 21:50:25 +0000287 hijacking_listener_sp.reset();
Greg Clayton11177952011-02-10 06:51:22 +0000288 }
289
Greg Clayton5160ce52013-03-27 23:08:40 +0000290 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000291 if (log)
292 {
293 StreamString event_description;
294 event_sp->Dump (&event_description);
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000295 log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p",
Jim Ingham583bbb12016-03-07 21:50:25 +0000296 static_cast<void*>(this), GetBroadcasterName(),
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000297 event_description.GetData(), unique,
Jim Ingham583bbb12016-03-07 21:50:25 +0000298 static_cast<void*>(hijacking_listener_sp.get()));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000299 }
300
Jim Ingham583bbb12016-03-07 21:50:25 +0000301 if (hijacking_listener_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000302 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000303 if (unique && hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type))
Jim Ingham30f9b212010-10-11 23:53:14 +0000304 return;
Jim Ingham583bbb12016-03-07 21:50:25 +0000305 hijacking_listener_sp->AddEvent (event_sp);
Jim Ingham30f9b212010-10-11 23:53:14 +0000306 }
307 else
308 {
Jim Ingham30f9b212010-10-11 23:53:14 +0000309
Greg Clayton1e20f022016-05-12 22:58:52 +0000310 ListenerIterator([this, unique, event_type, &event_sp](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
311
312 if (event_type & curr_event_mask)
Jim Ingham30f9b212010-10-11 23:53:14 +0000313 {
Greg Clayton1e20f022016-05-12 22:58:52 +0000314 if (!unique || curr_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type) == nullptr)
315 curr_listener_sp->AddEvent (event_sp);
Jim Ingham30f9b212010-10-11 23:53:14 +0000316 }
Greg Clayton1e20f022016-05-12 22:58:52 +0000317 return true; // Keep iterating
318 });
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000319 }
320}
321
322void
Jim Ingham583bbb12016-03-07 21:50:25 +0000323Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, EventData *event_data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324{
325 EventSP event_sp (new Event (event_type, event_data));
326 PrivateBroadcastEvent (event_sp, false);
327}
328
329void
Greg Clayton1e20f022016-05-12 22:58:52 +0000330Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, const lldb::EventDataSP &event_data_sp)
331{
332 EventSP event_sp (new Event (event_type, event_data_sp));
333 PrivateBroadcastEvent (event_sp, false);
334}
335
336void
Jim Ingham583bbb12016-03-07 21:50:25 +0000337Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000338{
339 EventSP event_sp (new Event (event_type, event_data));
340 PrivateBroadcastEvent (event_sp, true);
341}
342
Jim Ingham30f9b212010-10-11 23:53:14 +0000343bool
Greg Clayton1e20f022016-05-12 22:58:52 +0000344Broadcaster::BroadcasterImpl::HijackBroadcaster (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
Jim Ingham30f9b212010-10-11 23:53:14 +0000345{
Greg Clayton1e20f022016-05-12 22:58:52 +0000346 Mutex::Locker locker(m_listeners_mutex);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000347
Greg Clayton5160ce52013-03-27 23:08:40 +0000348 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Johnny Chen55d85f32012-03-29 20:02:33 +0000349 if (log)
Johnny Chen55d85f32012-03-29 20:02:33 +0000350 log->Printf ("%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)",
Jim Ingham583bbb12016-03-07 21:50:25 +0000351 static_cast<void*>(this), GetBroadcasterName(),
352 listener_sp->m_name.c_str(), static_cast<void*>(listener_sp.get()));
353 m_hijacking_listeners.push_back(listener_sp);
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000354 m_hijacking_masks.push_back(event_mask);
Jim Ingham30f9b212010-10-11 23:53:14 +0000355 return true;
356}
357
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000358bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000359Broadcaster::BroadcasterImpl::IsHijackedForEvent (uint32_t event_mask)
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000360{
Greg Clayton1e20f022016-05-12 22:58:52 +0000361 Mutex::Locker locker(m_listeners_mutex);
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000362
363 if (!m_hijacking_listeners.empty())
364 return (event_mask & m_hijacking_masks.back()) != 0;
365 return false;
366}
367
Jim Ingham583bbb12016-03-07 21:50:25 +0000368const char *
369Broadcaster::BroadcasterImpl::GetHijackingListenerName()
370{
371 if (m_hijacking_listeners.size())
372 {
373 return m_hijacking_listeners.back()->GetName();
374 }
375 else
376 {
377 return nullptr;
378 }
379}
380
Jim Ingham30f9b212010-10-11 23:53:14 +0000381void
Jim Ingham583bbb12016-03-07 21:50:25 +0000382Broadcaster::BroadcasterImpl::RestoreBroadcaster ()
Jim Ingham30f9b212010-10-11 23:53:14 +0000383{
Greg Clayton1e20f022016-05-12 22:58:52 +0000384 Mutex::Locker locker(m_listeners_mutex);
Johnny Chen55d85f32012-03-29 20:02:33 +0000385
Greg Clayton44d93782014-01-27 23:43:24 +0000386 if (!m_hijacking_listeners.empty())
Ed Masteaacfe092014-02-04 18:51:11 +0000387 {
388 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
389 if (log)
390 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000391 ListenerSP listener_sp = m_hijacking_listeners.back();
Ed Masteaacfe092014-02-04 18:51:11 +0000392 log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)",
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000393 static_cast<void*>(this),
Jim Ingham583bbb12016-03-07 21:50:25 +0000394 GetBroadcasterName(),
395 listener_sp->m_name.c_str(), static_cast<void*>(listener_sp.get()));
Ed Masteaacfe092014-02-04 18:51:11 +0000396 }
Greg Clayton44d93782014-01-27 23:43:24 +0000397 m_hijacking_listeners.pop_back();
Ed Masteaacfe092014-02-04 18:51:11 +0000398 }
Greg Clayton44d93782014-01-27 23:43:24 +0000399 if (!m_hijacking_masks.empty())
400 m_hijacking_masks.pop_back();
Jim Ingham30f9b212010-10-11 23:53:14 +0000401}
402
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000403ConstString &
404Broadcaster::GetBroadcasterClass() const
405{
406 static ConstString class_name ("lldb.anonymous");
407 return class_name;
408}
409
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000410BroadcastEventSpec::BroadcastEventSpec(const BroadcastEventSpec &rhs) = default;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000411
412bool
413BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const
414{
415 if (GetBroadcasterClass() == rhs.GetBroadcasterClass())
416 {
417 return GetEventBits() < rhs.GetEventBits();
418 }
419 else
420 {
421 return GetBroadcasterClass() < rhs.GetBroadcasterClass();
422 }
423}
424
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000425BroadcastEventSpec &
426BroadcastEventSpec::operator=(const BroadcastEventSpec &rhs) = default;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000427
428BroadcasterManager::BroadcasterManager() :
429 m_manager_mutex(Mutex::eMutexTypeRecursive)
430{
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000431}
432
Jim Ingham583bbb12016-03-07 21:50:25 +0000433lldb::BroadcasterManagerSP
434BroadcasterManager::MakeBroadcasterManager()
435{
436 return BroadcasterManagerSP(new BroadcasterManager());
437}
438
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000439uint32_t
Greg Clayton1e20f022016-05-12 22:58:52 +0000440BroadcasterManager::RegisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000441{
442 Mutex::Locker locker(m_manager_mutex);
443
444 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
445 uint32_t available_bits = event_spec.GetEventBits();
446
447 while (iter != end_iter
448 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter)
449 {
450 available_bits &= ~((*iter).first.GetEventBits());
451 iter++;
452 }
453
454 if (available_bits != 0)
455 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000456 m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), listener_sp));
457 m_listeners.insert(listener_sp);
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000458 }
459
460 return available_bits;
461}
462
463bool
Greg Clayton1e20f022016-05-12 22:58:52 +0000464BroadcasterManager::UnregisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000465{
466 Mutex::Locker locker(m_manager_mutex);
467 bool removed_some = false;
468
Jim Ingham583bbb12016-03-07 21:50:25 +0000469 if (m_listeners.erase(listener_sp) == 0)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000470 return false;
471
Jim Ingham583bbb12016-03-07 21:50:25 +0000472 ListenerMatchesAndSharedBits predicate (event_spec, listener_sp);
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000473 std::vector<BroadcastEventSpec> to_be_readded;
474 uint32_t event_bits_to_remove = event_spec.GetEventBits();
475
476 // Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add:
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000477 while (true)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000478 {
479 collection::iterator iter, end_iter = m_event_map.end();
480 iter = find_if (m_event_map.begin(), end_iter, predicate);
481 if (iter == end_iter)
482 {
483 break;
484 }
485 else
486 {
487 uint32_t iter_event_bits = (*iter).first.GetEventBits();
488 removed_some = true;
489
490 if (event_bits_to_remove != iter_event_bits)
491 {
492 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
493 to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits));
494 }
495 m_event_map.erase (iter);
496 }
497 }
498
499 // Okay now add back the bits that weren't completely removed:
500 for (size_t i = 0; i < to_be_readded.size(); i++)
501 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000502 m_event_map.insert (event_listener_key (to_be_readded[i], listener_sp));
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000503 }
504
505 return removed_some;
506}
507
Jim Ingham583bbb12016-03-07 21:50:25 +0000508ListenerSP
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000509BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const
510{
511 Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex)));
512
513 collection::const_iterator iter, end_iter = m_event_map.end();
514 iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec));
515 if (iter != end_iter)
516 return (*iter).second;
517 else
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000518 return nullptr;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000519}
520
521void
Jim Ingham583bbb12016-03-07 21:50:25 +0000522BroadcasterManager::RemoveListener(Listener *listener)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000523{
524 Mutex::Locker locker(m_manager_mutex);
Jim Ingham583bbb12016-03-07 21:50:25 +0000525 ListenerMatchesPointer predicate (listener);
526 listener_collection::iterator iter = m_listeners.begin(), end_iter = m_listeners.end();
527
528 std::find_if (iter, end_iter, predicate);
529 if (iter != end_iter)
530 m_listeners.erase(iter);
531
532 while (true)
533 {
534 collection::iterator iter, end_iter = m_event_map.end();
535 iter = find_if (m_event_map.begin(), end_iter, predicate);
536 if (iter == end_iter)
537 break;
538 else
539 m_event_map.erase(iter);
540 }
541}
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000542
Jim Ingham583bbb12016-03-07 21:50:25 +0000543void
Greg Clayton1e20f022016-05-12 22:58:52 +0000544BroadcasterManager::RemoveListener (const lldb::ListenerSP &listener_sp)
Jim Ingham583bbb12016-03-07 21:50:25 +0000545{
546 Mutex::Locker locker(m_manager_mutex);
547 ListenerMatches predicate (listener_sp);
548
549 if (m_listeners.erase (listener_sp) == 0)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000550 return;
551
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000552 while (true)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000553 {
554 collection::iterator iter, end_iter = m_event_map.end();
555 iter = find_if (m_event_map.begin(), end_iter, predicate);
556 if (iter == end_iter)
557 break;
558 else
559 m_event_map.erase(iter);
560 }
561}
562
563void
564BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster)
565{
566 Mutex::Locker locker(m_manager_mutex);
567
568 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
569
570 while (iter != end_iter
571 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter)
572 {
573 (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits());
574 iter++;
575 }
576}
577
578void
579BroadcasterManager::Clear ()
580{
581 Mutex::Locker locker(m_manager_mutex);
582 listener_collection::iterator end_iter = m_listeners.end();
583
584 for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++)
Jim Ingham583bbb12016-03-07 21:50:25 +0000585 (*iter)->BroadcasterManagerWillDestruct(this->shared_from_this());
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000586 m_listeners.clear();
587 m_event_map.clear();
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000588}