blob: 6494e3d85bc6afac64995d9b89cdd331aaf7dc3d [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)
28
29{
30}
31
32Broadcaster::BroadcasterImpl::BroadcasterImpl (Broadcaster &broadcaster) :
33 m_broadcaster(broadcaster),
Greg Claytoncfd1ace2010-10-31 03:01:06 +000034 m_listeners (),
35 m_listeners_mutex (Mutex::eMutexTypeRecursive),
Jim Inghamc4f4f7212011-02-08 05:16:50 +000036 m_hijacking_listeners(),
Jim Ingham583bbb12016-03-07 21:50:25 +000037 m_hijacking_masks()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038{
Greg Clayton5160ce52013-03-27 23:08:40 +000039 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +000041 log->Printf ("%p Broadcaster::Broadcaster(\"%s\")",
Jim Ingham583bbb12016-03-07 21:50:25 +000042 static_cast<void*>(this), m_broadcaster.GetBroadcasterName().AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043}
44
45Broadcaster::~Broadcaster()
46{
Greg Clayton5160ce52013-03-27 23:08:40 +000047 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +000049 log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")",
50 static_cast<void*>(this), m_broadcaster_name.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051
Greg Clayton1ed54f52011-10-01 00:45:15 +000052 Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053}
54
Greg Clayton1ed54f52011-10-01 00:45:15 +000055void
Jim Ingham4bddaeb2012-02-16 06:50:00 +000056Broadcaster::CheckInWithManager ()
57{
Jim Ingham583bbb12016-03-07 21:50:25 +000058 if (m_manager_sp)
Jim Ingham4bddaeb2012-02-16 06:50:00 +000059 {
Jim Ingham583bbb12016-03-07 21:50:25 +000060 m_manager_sp->SignUpListenersForBroadcaster(*this);
Jim Ingham4bddaeb2012-02-16 06:50:00 +000061 }
62}
63
64void
Jim Ingham583bbb12016-03-07 21:50:25 +000065Broadcaster::BroadcasterImpl::Clear()
Greg Clayton1ed54f52011-10-01 00:45:15 +000066{
67 Mutex::Locker listeners_locker(m_listeners_mutex);
68
69 // Make sure the listener forgets about this broadcaster. We do
70 // this in the broadcaster in case the broadcaster object initiates
71 // the removal.
72
73 collection::iterator pos, end = m_listeners.end();
74 for (pos = m_listeners.begin(); pos != end; ++pos)
Jim Ingham583bbb12016-03-07 21:50:25 +000075 pos->first->BroadcasterWillDestruct (&m_broadcaster);
Greg Clayton1ed54f52011-10-01 00:45:15 +000076
77 m_listeners.clear();
78}
Eugene Zelenko896ddd02016-03-02 01:09:03 +000079
Jim Ingham583bbb12016-03-07 21:50:25 +000080Broadcaster *
81Broadcaster::BroadcasterImpl::GetBroadcaster()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082{
Jim Ingham583bbb12016-03-07 21:50:25 +000083 return &m_broadcaster;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084}
85
Greg Claytoncfd1ace2010-10-31 03:01:06 +000086bool
Jim Ingham583bbb12016-03-07 21:50:25 +000087Broadcaster::BroadcasterImpl::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const
Greg Claytoncfd1ace2010-10-31 03:01:06 +000088{
89 uint32_t num_names_added = 0;
90 if (event_mask && !m_event_names.empty())
91 {
92 event_names_map::const_iterator end = m_event_names.end();
93 for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1)
94 {
95 if (mask & 1)
96 {
97 event_names_map::const_iterator pos = m_event_names.find(bit);
98 if (pos != end)
99 {
100 if (num_names_added > 0)
101 s.PutCString(", ");
102
103 if (prefix_with_broadcaster_name)
104 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000105 s.PutCString (GetBroadcasterName());
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000106 s.PutChar('.');
107 }
108 s.PutCString(pos->second.c_str());
109 ++num_names_added;
110 }
111 }
112 }
113 }
114 return num_names_added > 0;
115}
116
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117void
Jim Ingham583bbb12016-03-07 21:50:25 +0000118Broadcaster::AddInitialEventsToListener (lldb::ListenerSP listener_sp, uint32_t requested_events)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120}
121
122uint32_t
Jim Ingham583bbb12016-03-07 21:50:25 +0000123Broadcaster::BroadcasterImpl::AddListener (lldb::ListenerSP listener_sp, uint32_t event_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000124{
Jim Ingham583bbb12016-03-07 21:50:25 +0000125 if (!listener_sp)
Johnny Chend161a852010-12-22 19:29:31 +0000126 return 0;
127
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000128 Mutex::Locker locker(m_listeners_mutex);
129 collection::iterator pos, end = m_listeners.end();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130
131 collection::iterator existing_pos = end;
132 // See if we already have this listener, and if so, update its mask
133 uint32_t taken_event_types = 0;
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000134 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000135 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000136 if (pos->first == listener_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000137 existing_pos = pos;
138 // For now don't descriminate on who gets what
139 // FIXME: Implement "unique listener for this bit" mask
140 // taken_event_types |= pos->second;
141 }
142
143 // Each event bit in a Broadcaster object can only be used
144 // by one listener
145 uint32_t available_event_types = ~taken_event_types & event_mask;
146
147 if (available_event_types)
148 {
149 // If we didn't find our listener, add it
150 if (existing_pos == end)
151 {
152 // Grant a new listener the available event bits
Jim Ingham583bbb12016-03-07 21:50:25 +0000153 m_listeners.push_back(std::make_pair(listener_sp, available_event_types));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154 }
155 else
156 {
157 // Grant the existing listener the available event bits
158 existing_pos->second |= available_event_types;
159 }
160
161 // Individual broadcasters decide whether they have outstanding data when a
162 // listener attaches, and insert it into the listener with this method.
163
Jim Ingham583bbb12016-03-07 21:50:25 +0000164 m_broadcaster.AddInitialEventsToListener (listener_sp, available_event_types);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000165 }
166
167 // Return the event bits that were granted to the listener
168 return available_event_types;
169}
170
171bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000172Broadcaster::BroadcasterImpl::EventTypeHasListeners (uint32_t event_type)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000174 Mutex::Locker locker (m_listeners_mutex);
Jim Ingham30f9b212010-10-11 23:53:14 +0000175
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000176 if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back())
Jim Ingham30f9b212010-10-11 23:53:14 +0000177 return true;
178
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000179 if (m_listeners.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180 return false;
181
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000182 collection::iterator pos, end = m_listeners.end();
183 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000184 {
185 if (pos->second & event_type)
186 return true;
187 }
188 return false;
189}
190
191bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000192Broadcaster::BroadcasterImpl::RemoveListener (lldb::ListenerSP listener_sp, uint32_t event_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000193{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000194 Mutex::Locker locker(m_listeners_mutex);
195 collection::iterator pos, end = m_listeners.end();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000196 // See if we already have this listener, and if so, update its mask
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000197 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000198 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000199 if (pos->first == listener_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 {
201 // Relinquish all event bits in "event_mask"
202 pos->second &= ~event_mask;
203 // If all bits have been relinquished then remove this listener
204 if (pos->second == 0)
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000205 m_listeners.erase (pos);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000206 return true;
207 }
208 }
209 return false;
210}
211
212void
Jim Ingham583bbb12016-03-07 21:50:25 +0000213Broadcaster::BroadcasterImpl::BroadcastEvent (EventSP &event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000214{
215 return PrivateBroadcastEvent (event_sp, false);
216}
217
218void
Jim Ingham583bbb12016-03-07 21:50:25 +0000219Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (EventSP &event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000220{
221 return PrivateBroadcastEvent (event_sp, true);
222}
223
224void
Jim Ingham583bbb12016-03-07 21:50:25 +0000225Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226{
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000227 // Can't add a nullptr event...
228 if (!event_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000229 return;
230
231 // Update the broadcaster on this event
Jim Ingham583bbb12016-03-07 21:50:25 +0000232 event_sp->SetBroadcaster (&m_broadcaster);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233
234 const uint32_t event_type = event_sp->GetType();
235
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000236 Mutex::Locker event_types_locker(m_listeners_mutex);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000237
Jim Ingham583bbb12016-03-07 21:50:25 +0000238 ListenerSP hijacking_listener_sp;
239
Greg Clayton11177952011-02-10 06:51:22 +0000240 if (!m_hijacking_listeners.empty())
241 {
242 assert (!m_hijacking_masks.empty());
Jim Ingham583bbb12016-03-07 21:50:25 +0000243 hijacking_listener_sp = m_hijacking_listeners.back();
Greg Clayton11177952011-02-10 06:51:22 +0000244 if ((event_type & m_hijacking_masks.back()) == 0)
Jim Ingham583bbb12016-03-07 21:50:25 +0000245 hijacking_listener_sp.reset();
Greg Clayton11177952011-02-10 06:51:22 +0000246 }
247
Greg Clayton5160ce52013-03-27 23:08:40 +0000248 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000249 if (log)
250 {
251 StreamString event_description;
252 event_sp->Dump (&event_description);
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000253 log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p",
Jim Ingham583bbb12016-03-07 21:50:25 +0000254 static_cast<void*>(this), GetBroadcasterName(),
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000255 event_description.GetData(), unique,
Jim Ingham583bbb12016-03-07 21:50:25 +0000256 static_cast<void*>(hijacking_listener_sp.get()));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257 }
258
Jim Ingham583bbb12016-03-07 21:50:25 +0000259 if (hijacking_listener_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000260 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000261 if (unique && hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type))
Jim Ingham30f9b212010-10-11 23:53:14 +0000262 return;
Jim Ingham583bbb12016-03-07 21:50:25 +0000263 hijacking_listener_sp->AddEvent (event_sp);
Jim Ingham30f9b212010-10-11 23:53:14 +0000264 }
265 else
266 {
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000267 collection::iterator pos, end = m_listeners.end();
Jim Ingham30f9b212010-10-11 23:53:14 +0000268
Jim Ingham30f9b212010-10-11 23:53:14 +0000269 // Iterate through all listener/mask pairs
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000270 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271 {
Jim Ingham30f9b212010-10-11 23:53:14 +0000272 // If the listener's mask matches any bits that we just set, then
273 // put the new event on its event queue.
274 if (event_type & pos->second)
275 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000276 if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type))
Jim Ingham30f9b212010-10-11 23:53:14 +0000277 continue;
278 pos->first->AddEvent (event_sp);
279 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000280 }
281 }
282}
283
284void
Jim Ingham583bbb12016-03-07 21:50:25 +0000285Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, EventData *event_data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000286{
287 EventSP event_sp (new Event (event_type, event_data));
288 PrivateBroadcastEvent (event_sp, false);
289}
290
291void
Jim Ingham583bbb12016-03-07 21:50:25 +0000292Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293{
294 EventSP event_sp (new Event (event_type, event_data));
295 PrivateBroadcastEvent (event_sp, true);
296}
297
Jim Ingham30f9b212010-10-11 23:53:14 +0000298bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000299Broadcaster::BroadcasterImpl::HijackBroadcaster (ListenerSP listener_sp, uint32_t event_mask)
Jim Ingham30f9b212010-10-11 23:53:14 +0000300{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000301 Mutex::Locker event_types_locker(m_listeners_mutex);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000302
Greg Clayton5160ce52013-03-27 23:08:40 +0000303 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Johnny Chen55d85f32012-03-29 20:02:33 +0000304 if (log)
Johnny Chen55d85f32012-03-29 20:02:33 +0000305 log->Printf ("%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)",
Jim Ingham583bbb12016-03-07 21:50:25 +0000306 static_cast<void*>(this), GetBroadcasterName(),
307 listener_sp->m_name.c_str(), static_cast<void*>(listener_sp.get()));
308 m_hijacking_listeners.push_back(listener_sp);
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000309 m_hijacking_masks.push_back(event_mask);
Jim Ingham30f9b212010-10-11 23:53:14 +0000310 return true;
311}
312
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000313bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000314Broadcaster::BroadcasterImpl::IsHijackedForEvent (uint32_t event_mask)
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000315{
316 Mutex::Locker event_types_locker(m_listeners_mutex);
317
318 if (!m_hijacking_listeners.empty())
319 return (event_mask & m_hijacking_masks.back()) != 0;
320 return false;
321}
322
Jim Ingham583bbb12016-03-07 21:50:25 +0000323const char *
324Broadcaster::BroadcasterImpl::GetHijackingListenerName()
325{
326 if (m_hijacking_listeners.size())
327 {
328 return m_hijacking_listeners.back()->GetName();
329 }
330 else
331 {
332 return nullptr;
333 }
334}
335
Jim Ingham30f9b212010-10-11 23:53:14 +0000336void
Jim Ingham583bbb12016-03-07 21:50:25 +0000337Broadcaster::BroadcasterImpl::RestoreBroadcaster ()
Jim Ingham30f9b212010-10-11 23:53:14 +0000338{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000339 Mutex::Locker event_types_locker(m_listeners_mutex);
Johnny Chen55d85f32012-03-29 20:02:33 +0000340
Greg Clayton44d93782014-01-27 23:43:24 +0000341 if (!m_hijacking_listeners.empty())
Ed Masteaacfe092014-02-04 18:51:11 +0000342 {
343 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
344 if (log)
345 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000346 ListenerSP listener_sp = m_hijacking_listeners.back();
Ed Masteaacfe092014-02-04 18:51:11 +0000347 log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)",
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000348 static_cast<void*>(this),
Jim Ingham583bbb12016-03-07 21:50:25 +0000349 GetBroadcasterName(),
350 listener_sp->m_name.c_str(), static_cast<void*>(listener_sp.get()));
Ed Masteaacfe092014-02-04 18:51:11 +0000351 }
Greg Clayton44d93782014-01-27 23:43:24 +0000352 m_hijacking_listeners.pop_back();
Ed Masteaacfe092014-02-04 18:51:11 +0000353 }
Greg Clayton44d93782014-01-27 23:43:24 +0000354 if (!m_hijacking_masks.empty())
355 m_hijacking_masks.pop_back();
Jim Ingham30f9b212010-10-11 23:53:14 +0000356}
357
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000358ConstString &
359Broadcaster::GetBroadcasterClass() const
360{
361 static ConstString class_name ("lldb.anonymous");
362 return class_name;
363}
364
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000365BroadcastEventSpec::BroadcastEventSpec(const BroadcastEventSpec &rhs) = default;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000366
367bool
368BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const
369{
370 if (GetBroadcasterClass() == rhs.GetBroadcasterClass())
371 {
372 return GetEventBits() < rhs.GetEventBits();
373 }
374 else
375 {
376 return GetBroadcasterClass() < rhs.GetBroadcasterClass();
377 }
378}
379
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000380BroadcastEventSpec &
381BroadcastEventSpec::operator=(const BroadcastEventSpec &rhs) = default;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000382
383BroadcasterManager::BroadcasterManager() :
384 m_manager_mutex(Mutex::eMutexTypeRecursive)
385{
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000386}
387
Jim Ingham583bbb12016-03-07 21:50:25 +0000388lldb::BroadcasterManagerSP
389BroadcasterManager::MakeBroadcasterManager()
390{
391 return BroadcasterManagerSP(new BroadcasterManager());
392}
393
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000394uint32_t
Jim Ingham583bbb12016-03-07 21:50:25 +0000395BroadcasterManager::RegisterListenerForEvents (ListenerSP listener_sp, BroadcastEventSpec event_spec)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000396{
397 Mutex::Locker locker(m_manager_mutex);
398
399 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
400 uint32_t available_bits = event_spec.GetEventBits();
401
402 while (iter != end_iter
403 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter)
404 {
405 available_bits &= ~((*iter).first.GetEventBits());
406 iter++;
407 }
408
409 if (available_bits != 0)
410 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000411 m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), listener_sp));
412 m_listeners.insert(listener_sp);
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000413 }
414
415 return available_bits;
416}
417
418bool
Jim Ingham583bbb12016-03-07 21:50:25 +0000419BroadcasterManager::UnregisterListenerForEvents (ListenerSP listener_sp, BroadcastEventSpec event_spec)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000420{
421 Mutex::Locker locker(m_manager_mutex);
422 bool removed_some = false;
423
Jim Ingham583bbb12016-03-07 21:50:25 +0000424 if (m_listeners.erase(listener_sp) == 0)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000425 return false;
426
Jim Ingham583bbb12016-03-07 21:50:25 +0000427 ListenerMatchesAndSharedBits predicate (event_spec, listener_sp);
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000428 std::vector<BroadcastEventSpec> to_be_readded;
429 uint32_t event_bits_to_remove = event_spec.GetEventBits();
430
431 // 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 +0000432 while (true)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000433 {
434 collection::iterator iter, end_iter = m_event_map.end();
435 iter = find_if (m_event_map.begin(), end_iter, predicate);
436 if (iter == end_iter)
437 {
438 break;
439 }
440 else
441 {
442 uint32_t iter_event_bits = (*iter).first.GetEventBits();
443 removed_some = true;
444
445 if (event_bits_to_remove != iter_event_bits)
446 {
447 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
448 to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits));
449 }
450 m_event_map.erase (iter);
451 }
452 }
453
454 // Okay now add back the bits that weren't completely removed:
455 for (size_t i = 0; i < to_be_readded.size(); i++)
456 {
Jim Ingham583bbb12016-03-07 21:50:25 +0000457 m_event_map.insert (event_listener_key (to_be_readded[i], listener_sp));
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000458 }
459
460 return removed_some;
461}
462
Jim Ingham583bbb12016-03-07 21:50:25 +0000463ListenerSP
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000464BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const
465{
466 Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex)));
467
468 collection::const_iterator iter, end_iter = m_event_map.end();
469 iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec));
470 if (iter != end_iter)
471 return (*iter).second;
472 else
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000473 return nullptr;
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000474}
475
476void
Jim Ingham583bbb12016-03-07 21:50:25 +0000477BroadcasterManager::RemoveListener(Listener *listener)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000478{
479 Mutex::Locker locker(m_manager_mutex);
Jim Ingham583bbb12016-03-07 21:50:25 +0000480 ListenerMatchesPointer predicate (listener);
481 listener_collection::iterator iter = m_listeners.begin(), end_iter = m_listeners.end();
482
483 std::find_if (iter, end_iter, predicate);
484 if (iter != end_iter)
485 m_listeners.erase(iter);
486
487 while (true)
488 {
489 collection::iterator iter, end_iter = m_event_map.end();
490 iter = find_if (m_event_map.begin(), end_iter, predicate);
491 if (iter == end_iter)
492 break;
493 else
494 m_event_map.erase(iter);
495 }
496}
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000497
Jim Ingham583bbb12016-03-07 21:50:25 +0000498void
499BroadcasterManager::RemoveListener (ListenerSP listener_sp)
500{
501 Mutex::Locker locker(m_manager_mutex);
502 ListenerMatches predicate (listener_sp);
503
504 if (m_listeners.erase (listener_sp) == 0)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000505 return;
506
Eugene Zelenko896ddd02016-03-02 01:09:03 +0000507 while (true)
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000508 {
509 collection::iterator iter, end_iter = m_event_map.end();
510 iter = find_if (m_event_map.begin(), end_iter, predicate);
511 if (iter == end_iter)
512 break;
513 else
514 m_event_map.erase(iter);
515 }
516}
517
518void
519BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster)
520{
521 Mutex::Locker locker(m_manager_mutex);
522
523 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
524
525 while (iter != end_iter
526 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter)
527 {
528 (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits());
529 iter++;
530 }
531}
532
533void
534BroadcasterManager::Clear ()
535{
536 Mutex::Locker locker(m_manager_mutex);
537 listener_collection::iterator end_iter = m_listeners.end();
538
539 for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++)
Jim Ingham583bbb12016-03-07 21:50:25 +0000540 (*iter)->BroadcasterManagerWillDestruct(this->shared_from_this());
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000541 m_listeners.clear();
542 m_event_map.clear();
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000543}