blob: 30bc78b482206128440b681803b6bb7835cf04dd [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
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000035Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster)
36 : m_broadcaster(broadcaster), m_listeners(), m_listeners_mutex(), m_hijacking_listeners(), m_hijacking_masks()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037{
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038}
39
40Broadcaster::~Broadcaster()
41{
Greg Clayton5160ce52013-03-27 23:08:40 +000042 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +000044 log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")",
45 static_cast<void*>(this), m_broadcaster_name.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046
Greg Clayton1ed54f52011-10-01 00:45:15 +000047 Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048}
49
Greg Clayton1ed54f52011-10-01 00:45:15 +000050void
Jim Ingham4bddaeb2012-02-16 06:50:00 +000051Broadcaster::CheckInWithManager ()
52{
Jim Ingham583bbb12016-03-07 21:50:25 +000053 if (m_manager_sp)
Jim Ingham4bddaeb2012-02-16 06:50:00 +000054 {
Jim Ingham583bbb12016-03-07 21:50:25 +000055 m_manager_sp->SignUpListenersForBroadcaster(*this);
Jim Ingham4bddaeb2012-02-16 06:50:00 +000056 }
57}
58
59void
Greg Clayton1e20f022016-05-12 22:58:52 +000060Broadcaster::BroadcasterImpl::ListenerIterator (std::function <bool (const lldb::ListenerSP &listener_sp, uint32_t &event_mask)> const &callback)
61{
62 // Private iterator that should be used by everyone except BroadcasterImpl::RemoveListener().
63 // We have weak pointers to our listeners which means that at any point the listener can
64 // expire which means we will need to take it out of our list. To take care of this, we
65 // iterate and check that the weak pointer can be made into a valid shared pointer before
66 // we call the callback. If the weak pointer has expired, we remove it from our list.
67 collection::iterator pos = m_listeners.begin();
68 while (pos != m_listeners.end())
69 {
70 lldb::ListenerSP curr_listener_sp(pos->first.lock());
71 if (curr_listener_sp)
72 {
73 if (callback(curr_listener_sp, pos->second))
74 ++pos; // Keep iterating
75 else
76 return; // Done iterating
77 }
78 else
79 {
80 // The listener has been expired. Remove this entry.
81 pos = m_listeners.erase(pos);
82 }
83 }
84}
85
86void
Jim Ingham583bbb12016-03-07 21:50:25 +000087Broadcaster::BroadcasterImpl::Clear()
Greg Clayton1ed54f52011-10-01 00:45:15 +000088{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000089 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
90
Greg Clayton1ed54f52011-10-01 00:45:15 +000091 // Make sure the listener forgets about this broadcaster. We do
92 // this in the broadcaster in case the broadcaster object initiates
93 // the removal.
Greg Clayton1e20f022016-05-12 22:58:52 +000094
95 ListenerIterator([this](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
96 curr_listener_sp->BroadcasterWillDestruct (&m_broadcaster);
97 return true; // Keep iterating
98 });
Greg Clayton1ed54f52011-10-01 00:45:15 +000099
100 m_listeners.clear();
101}
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000102
Jim Ingham583bbb12016-03-07 21:50:25 +0000103Broadcaster *
104Broadcaster::BroadcasterImpl::GetBroadcaster()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000105{
Jim Ingham583bbb12016-03-07 21:50:25 +0000106 return &m_broadcaster;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000107}
108
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000109bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000110Broadcaster::BroadcasterImpl::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000111{
112 uint32_t num_names_added = 0;
113 if (event_mask && !m_event_names.empty())
114 {
115 event_names_map::const_iterator end = m_event_names.end();
116 for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1)
117 {
118 if (mask & 1)
119 {
120 event_names_map::const_iterator pos = m_event_names.find(bit);
121 if (pos != end)
122 {
123 if (num_names_added > 0)
124 s.PutCString(", ");
125
126 if (prefix_with_broadcaster_name)
127 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000128 s.PutCString (GetBroadcasterName());
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000129 s.PutChar('.');
130 }
131 s.PutCString(pos->second.c_str());
132 ++num_names_added;
133 }
134 }
135 }
136 }
137 return num_names_added > 0;
138}
139
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000140void
Greg Clayton1e20f022016-05-12 22:58:52 +0000141Broadcaster::AddInitialEventsToListener (const lldb::ListenerSP &listener_sp, uint32_t requested_events)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000142{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143}
144
145uint32_t
Greg Clayton1e20f022016-05-12 22:58:52 +0000146Broadcaster::BroadcasterImpl::AddListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147{
Jim Ingham583bbb12016-03-07 21:50:25 +0000148 if (!listener_sp)
Johnny Chend161a852010-12-22 19:29:31 +0000149 return 0;
150
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000151 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000152
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153 // See if we already have this listener, and if so, update its mask
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154
Greg Clayton1e20f022016-05-12 22:58:52 +0000155 bool handled = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156
Greg Clayton1e20f022016-05-12 22:58:52 +0000157 ListenerIterator([this, &listener_sp, &handled, event_mask](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
158 if (curr_listener_sp == listener_sp)
159 {
160 handled = true;
161 curr_event_mask |= event_mask;
162 m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask);
163 return false; // Stop iterating
164 }
165 return true; // Keep iterating
166 });
167
168 if (!handled)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 {
Greg Clayton1e20f022016-05-12 22:58:52 +0000170 // Grant a new listener the available event bits
171 m_listeners.push_back(std::make_pair(lldb::ListenerWP(listener_sp), event_mask));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000172
173 // Individual broadcasters decide whether they have outstanding data when a
174 // listener attaches, and insert it into the listener with this method.
Greg Clayton1e20f022016-05-12 22:58:52 +0000175 m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000176 }
177
178 // Return the event bits that were granted to the listener
Greg Clayton1e20f022016-05-12 22:58:52 +0000179 return event_mask;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180}
181
182bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000183Broadcaster::BroadcasterImpl::EventTypeHasListeners (uint32_t event_type)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000184{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000185 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
186
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000187 if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back())
Jim Ingham30f9b212010-10-11 23:53:14 +0000188 return true;
189
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000190 if (m_listeners.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 return false;
192
Greg Clayton1e20f022016-05-12 22:58:52 +0000193 bool result = false;
194 ListenerIterator([this, event_type, &result](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
195
196 if (curr_event_mask & event_type)
197 {
198 result = true;
199 return false; // Stop iterating
200 }
201 else
202 {
203 return true; // Keep iterating
204 }
205 });
206 return result;
207}
208
209bool
210Broadcaster::BroadcasterImpl::RemoveListener (lldb_private::Listener *listener, uint32_t event_mask)
211{
212 if (listener)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000213 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000214 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
Greg Clayton1e20f022016-05-12 22:58:52 +0000215 collection::iterator pos = m_listeners.begin();
216 // See if we already have this listener, and if so, update its mask
217 while (pos != m_listeners.end())
218 {
219 lldb::ListenerSP curr_listener_sp(pos->first.lock());
220 if (curr_listener_sp)
221 {
222 if (curr_listener_sp.get() == listener)
223 {
224 // Relinquish all event bits in "event_mask"
225 pos->second &= ~event_mask;
226 // If all bits have been relinquished then remove this listener
227 if (pos->second == 0)
228 m_listeners.erase (pos);
229 return true;
230 }
231 ++pos;
232 }
233 else
234 {
235 // The listener has been destroyed since we couldn't turn the std::weak_ptr
236 // into a valid shared pointer, so we can remove it.
237 pos = m_listeners.erase (pos);
238 }
239 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240 }
241 return false;
242}
243
244bool
Greg Clayton1e20f022016-05-12 22:58:52 +0000245Broadcaster::BroadcasterImpl::RemoveListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246{
Greg Clayton1e20f022016-05-12 22:58:52 +0000247 return RemoveListener (listener_sp.get(), event_mask);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000248}
249
250void
Jim Ingham583bbb12016-03-07 21:50:25 +0000251Broadcaster::BroadcasterImpl::BroadcastEvent (EventSP &event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000252{
253 return PrivateBroadcastEvent (event_sp, false);
254}
255
256void
Jim Ingham583bbb12016-03-07 21:50:25 +0000257Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (EventSP &event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258{
259 return PrivateBroadcastEvent (event_sp, true);
260}
261
262void
Jim Ingham583bbb12016-03-07 21:50:25 +0000263Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000264{
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000265 // Can't add a nullptr event...
266 if (!event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000267 return;
268
269 // Update the broadcaster on this event
Jim Ingham583bbb12016-03-07 21:50:25 +0000270 event_sp->SetBroadcaster (&m_broadcaster);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271
272 const uint32_t event_type = event_sp->GetType();
273
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000274 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000275
Jim Ingham583bbb12016-03-07 21:50:25 +0000276 ListenerSP hijacking_listener_sp;
277
Greg Clayton11177952011-02-10 06:51:22 +0000278 if (!m_hijacking_listeners.empty())
279 {
280 assert (!m_hijacking_masks.empty());
Jim Ingham583bbb12016-03-07 21:50:25 +0000281 hijacking_listener_sp = m_hijacking_listeners.back();
Greg Clayton11177952011-02-10 06:51:22 +0000282 if ((event_type & m_hijacking_masks.back()) == 0)
Jim Ingham583bbb12016-03-07 21:50:25 +0000283 hijacking_listener_sp.reset();
Greg Clayton11177952011-02-10 06:51:22 +0000284 }
285
Greg Clayton5160ce52013-03-27 23:08:40 +0000286 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000287 if (log)
288 {
289 StreamString event_description;
290 event_sp->Dump (&event_description);
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000291 log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p",
Jim Ingham583bbb12016-03-07 21:50:25 +0000292 static_cast<void*>(this), GetBroadcasterName(),
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000293 event_description.GetData(), unique,
Jim Ingham583bbb12016-03-07 21:50:25 +0000294 static_cast<void*>(hijacking_listener_sp.get()));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295 }
296
Jim Ingham583bbb12016-03-07 21:50:25 +0000297 if (hijacking_listener_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000298 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000299 if (unique && hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type))
Jim Ingham30f9b212010-10-11 23:53:14 +0000300 return;
Jim Ingham583bbb12016-03-07 21:50:25 +0000301 hijacking_listener_sp->AddEvent (event_sp);
Jim Ingham30f9b212010-10-11 23:53:14 +0000302 }
303 else
304 {
Jim Ingham30f9b212010-10-11 23:53:14 +0000305
Greg Clayton1e20f022016-05-12 22:58:52 +0000306 ListenerIterator([this, unique, event_type, &event_sp](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
307
308 if (event_type & curr_event_mask)
Jim Ingham30f9b212010-10-11 23:53:14 +0000309 {
Greg Clayton1e20f022016-05-12 22:58:52 +0000310 if (!unique || curr_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type) == nullptr)
311 curr_listener_sp->AddEvent (event_sp);
Jim Ingham30f9b212010-10-11 23:53:14 +0000312 }
Greg Clayton1e20f022016-05-12 22:58:52 +0000313 return true; // Keep iterating
314 });
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000315 }
316}
317
318void
Jim Ingham583bbb12016-03-07 21:50:25 +0000319Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, EventData *event_data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000320{
321 EventSP event_sp (new Event (event_type, event_data));
322 PrivateBroadcastEvent (event_sp, false);
323}
324
325void
Greg Clayton1e20f022016-05-12 22:58:52 +0000326Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, const lldb::EventDataSP &event_data_sp)
327{
328 EventSP event_sp (new Event (event_type, event_data_sp));
329 PrivateBroadcastEvent (event_sp, false);
330}
331
332void
Jim Ingham583bbb12016-03-07 21:50:25 +0000333Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000334{
335 EventSP event_sp (new Event (event_type, event_data));
336 PrivateBroadcastEvent (event_sp, true);
337}
338
Jim Ingham30f9b212010-10-11 23:53:14 +0000339bool
Greg Clayton1e20f022016-05-12 22:58:52 +0000340Broadcaster::BroadcasterImpl::HijackBroadcaster (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
Jim Ingham30f9b212010-10-11 23:53:14 +0000341{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000342 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000343
Greg Clayton5160ce52013-03-27 23:08:40 +0000344 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Johnny Chen55d85f32012-03-29 20:02:33 +0000345 if (log)
Johnny Chen55d85f32012-03-29 20:02:33 +0000346 log->Printf ("%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)",
Jim Ingham583bbb12016-03-07 21:50:25 +0000347 static_cast<void*>(this), GetBroadcasterName(),
348 listener_sp->m_name.c_str(), static_cast<void*>(listener_sp.get()));
349 m_hijacking_listeners.push_back(listener_sp);
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000350 m_hijacking_masks.push_back(event_mask);
Jim Ingham30f9b212010-10-11 23:53:14 +0000351 return true;
352}
353
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000354bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000355Broadcaster::BroadcasterImpl::IsHijackedForEvent (uint32_t event_mask)
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000356{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000357 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000358
359 if (!m_hijacking_listeners.empty())
360 return (event_mask & m_hijacking_masks.back()) != 0;
361 return false;
362}
363
Jim Ingham583bbb12016-03-07 21:50:25 +0000364const char *
365Broadcaster::BroadcasterImpl::GetHijackingListenerName()
366{
367 if (m_hijacking_listeners.size())
368 {
369 return m_hijacking_listeners.back()->GetName();
370 }
371 else
372 {
373 return nullptr;
374 }
375}
376
Jim Ingham30f9b212010-10-11 23:53:14 +0000377void
Jim Ingham583bbb12016-03-07 21:50:25 +0000378Broadcaster::BroadcasterImpl::RestoreBroadcaster ()
Jim Ingham30f9b212010-10-11 23:53:14 +0000379{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000380 std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
Johnny Chen55d85f32012-03-29 20:02:33 +0000381
Greg Clayton44d93782014-01-27 23:43:24 +0000382 if (!m_hijacking_listeners.empty())
Ed Masteaacfe092014-02-04 18:51:11 +0000383 {
384 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
385 if (log)
386 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000387 ListenerSP listener_sp = m_hijacking_listeners.back();
Ed Masteaacfe092014-02-04 18:51:11 +0000388 log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)",
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000389 static_cast<void*>(this),
Jim Ingham583bbb12016-03-07 21:50:25 +0000390 GetBroadcasterName(),
391 listener_sp->m_name.c_str(), static_cast<void*>(listener_sp.get()));
Ed Masteaacfe092014-02-04 18:51:11 +0000392 }
Greg Clayton44d93782014-01-27 23:43:24 +0000393 m_hijacking_listeners.pop_back();
Ed Masteaacfe092014-02-04 18:51:11 +0000394 }
Greg Clayton44d93782014-01-27 23:43:24 +0000395 if (!m_hijacking_masks.empty())
396 m_hijacking_masks.pop_back();
Jim Ingham30f9b212010-10-11 23:53:14 +0000397}
398
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000399ConstString &
400Broadcaster::GetBroadcasterClass() const
401{
402 static ConstString class_name ("lldb.anonymous");
403 return class_name;
404}
405
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000406BroadcastEventSpec::BroadcastEventSpec(const BroadcastEventSpec &rhs) = default;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000407
408bool
409BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const
410{
411 if (GetBroadcasterClass() == rhs.GetBroadcasterClass())
412 {
413 return GetEventBits() < rhs.GetEventBits();
414 }
415 else
416 {
417 return GetBroadcasterClass() < rhs.GetBroadcasterClass();
418 }
419}
420
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000421BroadcastEventSpec &
422BroadcastEventSpec::operator=(const BroadcastEventSpec &rhs) = default;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000423
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000424BroadcasterManager::BroadcasterManager() : m_manager_mutex()
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000425{
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000426}
427
Jim Ingham583bbb12016-03-07 21:50:25 +0000428lldb::BroadcasterManagerSP
429BroadcasterManager::MakeBroadcasterManager()
430{
431 return BroadcasterManagerSP(new BroadcasterManager());
432}
433
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000434uint32_t
Greg Clayton1e20f022016-05-12 22:58:52 +0000435BroadcasterManager::RegisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000436{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000437 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
438
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000439 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
440 uint32_t available_bits = event_spec.GetEventBits();
441
442 while (iter != end_iter
443 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter)
444 {
445 available_bits &= ~((*iter).first.GetEventBits());
446 iter++;
447 }
448
449 if (available_bits != 0)
450 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000451 m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), listener_sp));
452 m_listeners.insert(listener_sp);
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000453 }
454
455 return available_bits;
456}
457
458bool
Greg Clayton1e20f022016-05-12 22:58:52 +0000459BroadcasterManager::UnregisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000460{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000461 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000462 bool removed_some = false;
463
Jim Ingham583bbb12016-03-07 21:50:25 +0000464 if (m_listeners.erase(listener_sp) == 0)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000465 return false;
466
Jim Ingham583bbb12016-03-07 21:50:25 +0000467 ListenerMatchesAndSharedBits predicate (event_spec, listener_sp);
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000468 std::vector<BroadcastEventSpec> to_be_readded;
469 uint32_t event_bits_to_remove = event_spec.GetEventBits();
470
471 // 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 +0000472 while (true)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000473 {
474 collection::iterator iter, end_iter = m_event_map.end();
475 iter = find_if (m_event_map.begin(), end_iter, predicate);
476 if (iter == end_iter)
477 {
478 break;
479 }
480 else
481 {
482 uint32_t iter_event_bits = (*iter).first.GetEventBits();
483 removed_some = true;
484
485 if (event_bits_to_remove != iter_event_bits)
486 {
487 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
488 to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits));
489 }
490 m_event_map.erase (iter);
491 }
492 }
493
494 // Okay now add back the bits that weren't completely removed:
495 for (size_t i = 0; i < to_be_readded.size(); i++)
496 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000497 m_event_map.insert (event_listener_key (to_be_readded[i], listener_sp));
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000498 }
499
500 return removed_some;
501}
502
Jim Ingham583bbb12016-03-07 21:50:25 +0000503ListenerSP
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000504BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const
505{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000506 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
507
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000508 collection::const_iterator iter, end_iter = m_event_map.end();
509 iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec));
510 if (iter != end_iter)
511 return (*iter).second;
512 else
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000513 return nullptr;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000514}
515
516void
Jim Ingham583bbb12016-03-07 21:50:25 +0000517BroadcasterManager::RemoveListener(Listener *listener)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000518{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000519 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
Jim Ingham583bbb12016-03-07 21:50:25 +0000520 ListenerMatchesPointer predicate (listener);
521 listener_collection::iterator iter = m_listeners.begin(), end_iter = m_listeners.end();
522
523 std::find_if (iter, end_iter, predicate);
524 if (iter != end_iter)
525 m_listeners.erase(iter);
526
527 while (true)
528 {
529 collection::iterator iter, end_iter = m_event_map.end();
530 iter = find_if (m_event_map.begin(), end_iter, predicate);
531 if (iter == end_iter)
532 break;
533 else
534 m_event_map.erase(iter);
535 }
536}
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000537
Jim Ingham583bbb12016-03-07 21:50:25 +0000538void
Greg Clayton1e20f022016-05-12 22:58:52 +0000539BroadcasterManager::RemoveListener (const lldb::ListenerSP &listener_sp)
Jim Ingham583bbb12016-03-07 21:50:25 +0000540{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000541 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
Jim Ingham583bbb12016-03-07 21:50:25 +0000542 ListenerMatches predicate (listener_sp);
543
544 if (m_listeners.erase (listener_sp) == 0)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000545 return;
546
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000547 while (true)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000548 {
549 collection::iterator iter, end_iter = m_event_map.end();
550 iter = find_if (m_event_map.begin(), end_iter, predicate);
551 if (iter == end_iter)
552 break;
553 else
554 m_event_map.erase(iter);
555 }
556}
557
558void
559BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster)
560{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000561 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
562
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000563 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
564
565 while (iter != end_iter
566 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter)
567 {
568 (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits());
569 iter++;
570 }
571}
572
573void
574BroadcasterManager::Clear ()
575{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000576 std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000577 listener_collection::iterator end_iter = m_listeners.end();
578
579 for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++)
Jim Ingham583bbb12016-03-07 21:50:25 +0000580 (*iter)->BroadcasterManagerWillDestruct(this->shared_from_this());
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000581 m_listeners.clear();
582 m_event_map.clear();
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000583}