blob: 1cbbde20e7f6aa6fe78b4a55ef304aab6c7e9455 [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"
18#include "lldb/Core/StreamString.h"
19#include "lldb/lldb-private-log.h"
20
21using namespace lldb;
22using namespace lldb_private;
23
Jim Ingham4bddaeb2012-02-16 06:50:00 +000024Broadcaster::Broadcaster (BroadcasterManager *manager, const char *name) :
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025 m_broadcaster_name (name),
Greg Claytoncfd1ace2010-10-31 03:01:06 +000026 m_listeners (),
27 m_listeners_mutex (Mutex::eMutexTypeRecursive),
Jim Inghamc4f4f7212011-02-08 05:16:50 +000028 m_hijacking_listeners(),
Jim Ingham4bddaeb2012-02-16 06:50:00 +000029 m_hijacking_masks(),
30 m_manager (manager)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031{
Greg Clayton5160ce52013-03-27 23:08:40 +000032 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +000034 log->Printf ("%p Broadcaster::Broadcaster(\"%s\")",
35 static_cast<void*>(this), m_broadcaster_name.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036}
37
38Broadcaster::~Broadcaster()
39{
Greg Clayton5160ce52013-03-27 23:08:40 +000040 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041 if (log)
Saleem Abdulrasool324a1032014-04-04 04:06:10 +000042 log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")",
43 static_cast<void*>(this), m_broadcaster_name.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044
Greg Clayton1ed54f52011-10-01 00:45:15 +000045 Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046}
47
Greg Clayton1ed54f52011-10-01 00:45:15 +000048void
Jim Ingham4bddaeb2012-02-16 06:50:00 +000049Broadcaster::CheckInWithManager ()
50{
51 if (m_manager != NULL)
52 {
53 m_manager->SignUpListenersForBroadcaster(*this);
54 }
55}
56
57void
Greg Clayton1ed54f52011-10-01 00:45:15 +000058Broadcaster::Clear()
59{
60 Mutex::Locker listeners_locker(m_listeners_mutex);
61
62 // Make sure the listener forgets about this broadcaster. We do
63 // this in the broadcaster in case the broadcaster object initiates
64 // the removal.
65
66 collection::iterator pos, end = m_listeners.end();
67 for (pos = m_listeners.begin(); pos != end; ++pos)
68 pos->first->BroadcasterWillDestruct (this);
69
70 m_listeners.clear();
71}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000072const ConstString &
73Broadcaster::GetBroadcasterName ()
74{
75 return m_broadcaster_name;
76}
77
Greg Claytoncfd1ace2010-10-31 03:01:06 +000078bool
79Broadcaster::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const
80{
81 uint32_t num_names_added = 0;
82 if (event_mask && !m_event_names.empty())
83 {
84 event_names_map::const_iterator end = m_event_names.end();
85 for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1)
86 {
87 if (mask & 1)
88 {
89 event_names_map::const_iterator pos = m_event_names.find(bit);
90 if (pos != end)
91 {
92 if (num_names_added > 0)
93 s.PutCString(", ");
94
95 if (prefix_with_broadcaster_name)
96 {
97 s.PutCString (m_broadcaster_name.GetCString());
98 s.PutChar('.');
99 }
100 s.PutCString(pos->second.c_str());
101 ++num_names_added;
102 }
103 }
104 }
105 }
106 return num_names_added > 0;
107}
108
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109void
110Broadcaster::AddInitialEventsToListener (Listener *listener, uint32_t requested_events)
111{
112
113}
114
115uint32_t
116Broadcaster::AddListener (Listener* listener, uint32_t event_mask)
117{
Johnny Chend161a852010-12-22 19:29:31 +0000118 if (listener == NULL)
119 return 0;
120
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000121 Mutex::Locker locker(m_listeners_mutex);
122 collection::iterator pos, end = m_listeners.end();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123
124 collection::iterator existing_pos = end;
125 // See if we already have this listener, and if so, update its mask
126 uint32_t taken_event_types = 0;
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000127 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128 {
129 if (pos->first == listener)
130 existing_pos = pos;
131 // For now don't descriminate on who gets what
132 // FIXME: Implement "unique listener for this bit" mask
133 // taken_event_types |= pos->second;
134 }
135
136 // Each event bit in a Broadcaster object can only be used
137 // by one listener
138 uint32_t available_event_types = ~taken_event_types & event_mask;
139
140 if (available_event_types)
141 {
142 // If we didn't find our listener, add it
143 if (existing_pos == end)
144 {
145 // Grant a new listener the available event bits
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000146 m_listeners.push_back(std::make_pair(listener, available_event_types));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147 }
148 else
149 {
150 // Grant the existing listener the available event bits
151 existing_pos->second |= available_event_types;
152 }
153
154 // Individual broadcasters decide whether they have outstanding data when a
155 // listener attaches, and insert it into the listener with this method.
156
157 AddInitialEventsToListener (listener, available_event_types);
158 }
159
160 // Return the event bits that were granted to the listener
161 return available_event_types;
162}
163
164bool
165Broadcaster::EventTypeHasListeners (uint32_t event_type)
166{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000167 Mutex::Locker locker (m_listeners_mutex);
Jim Ingham30f9b212010-10-11 23:53:14 +0000168
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000169 if (m_hijacking_listeners.size() > 0 && event_type & m_hijacking_masks.back())
Jim Ingham30f9b212010-10-11 23:53:14 +0000170 return true;
171
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000172 if (m_listeners.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 return false;
174
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000175 collection::iterator pos, end = m_listeners.end();
176 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000177 {
178 if (pos->second & event_type)
179 return true;
180 }
181 return false;
182}
183
184bool
185Broadcaster::RemoveListener (Listener* listener, uint32_t event_mask)
186{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000187 Mutex::Locker locker(m_listeners_mutex);
188 collection::iterator pos, end = m_listeners.end();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189 // See if we already have this listener, and if so, update its mask
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000190 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 {
192 if (pos->first == listener)
193 {
194 // Relinquish all event bits in "event_mask"
195 pos->second &= ~event_mask;
196 // If all bits have been relinquished then remove this listener
197 if (pos->second == 0)
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000198 m_listeners.erase (pos);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000199 return true;
200 }
201 }
202 return false;
203}
204
205void
206Broadcaster::BroadcastEvent (EventSP &event_sp)
207{
208 return PrivateBroadcastEvent (event_sp, false);
209}
210
211void
212Broadcaster::BroadcastEventIfUnique (EventSP &event_sp)
213{
214 return PrivateBroadcastEvent (event_sp, true);
215}
216
217void
218Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
219{
220 // Can't add a NULL event...
221 if (event_sp.get() == NULL)
222 return;
223
224 // Update the broadcaster on this event
225 event_sp->SetBroadcaster (this);
226
227 const uint32_t event_type = event_sp->GetType();
228
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000229 Mutex::Locker event_types_locker(m_listeners_mutex);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000230
Greg Clayton11177952011-02-10 06:51:22 +0000231 Listener *hijacking_listener = NULL;
232 if (!m_hijacking_listeners.empty())
233 {
234 assert (!m_hijacking_masks.empty());
235 hijacking_listener = m_hijacking_listeners.back();
236 if ((event_type & m_hijacking_masks.back()) == 0)
237 hijacking_listener = NULL;
238 }
239
Greg Clayton5160ce52013-03-27 23:08:40 +0000240 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000241 if (log)
242 {
243 StreamString event_description;
244 event_sp->Dump (&event_description);
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000245 log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p",
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000246 static_cast<void*>(this), m_broadcaster_name.AsCString(""),
247 event_description.GetData(), unique,
248 static_cast<void*>(hijacking_listener));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000249 }
250
Greg Clayton11177952011-02-10 06:51:22 +0000251 if (hijacking_listener)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000252 {
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000253 if (unique && hijacking_listener->PeekAtNextEventForBroadcasterWithType (this, event_type))
Jim Ingham30f9b212010-10-11 23:53:14 +0000254 return;
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000255 hijacking_listener->AddEvent (event_sp);
Jim Ingham30f9b212010-10-11 23:53:14 +0000256 }
257 else
258 {
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000259 collection::iterator pos, end = m_listeners.end();
Jim Ingham30f9b212010-10-11 23:53:14 +0000260
261
262 // Iterate through all listener/mask pairs
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000263 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000264 {
Jim Ingham30f9b212010-10-11 23:53:14 +0000265 // If the listener's mask matches any bits that we just set, then
266 // put the new event on its event queue.
267 if (event_type & pos->second)
268 {
269 if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (this, event_type))
270 continue;
271 pos->first->AddEvent (event_sp);
272 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000273 }
274 }
275}
276
277void
278Broadcaster::BroadcastEvent (uint32_t event_type, EventData *event_data)
279{
280 EventSP event_sp (new Event (event_type, event_data));
281 PrivateBroadcastEvent (event_sp, false);
282}
283
284void
285Broadcaster::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
286{
287 EventSP event_sp (new Event (event_type, event_data));
288 PrivateBroadcastEvent (event_sp, true);
289}
290
Jim Ingham30f9b212010-10-11 23:53:14 +0000291bool
292Broadcaster::HijackBroadcaster (Listener *listener, uint32_t event_mask)
293{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000294 Mutex::Locker event_types_locker(m_listeners_mutex);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000295
Greg Clayton5160ce52013-03-27 23:08:40 +0000296 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Johnny Chen55d85f32012-03-29 20:02:33 +0000297 if (log)
Johnny Chen55d85f32012-03-29 20:02:33 +0000298 log->Printf ("%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)",
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000299 static_cast<void*>(this), m_broadcaster_name.AsCString(""),
300 listener->m_name.c_str(), static_cast<void*>(listener));
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000301 m_hijacking_listeners.push_back(listener);
302 m_hijacking_masks.push_back(event_mask);
Jim Ingham30f9b212010-10-11 23:53:14 +0000303 return true;
304}
305
Oleksiy Vyalovf31a77f2015-02-04 19:42:32 +0000306bool
307Broadcaster::IsHijackedForEvent (uint32_t event_mask)
308{
309 Mutex::Locker event_types_locker(m_listeners_mutex);
310
311 if (!m_hijacking_listeners.empty())
312 return (event_mask & m_hijacking_masks.back()) != 0;
313 return false;
314}
315
Jim Ingham30f9b212010-10-11 23:53:14 +0000316void
317Broadcaster::RestoreBroadcaster ()
318{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000319 Mutex::Locker event_types_locker(m_listeners_mutex);
Johnny Chen55d85f32012-03-29 20:02:33 +0000320
Greg Clayton44d93782014-01-27 23:43:24 +0000321 if (!m_hijacking_listeners.empty())
Ed Masteaacfe092014-02-04 18:51:11 +0000322 {
323 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
324 if (log)
325 {
326 Listener *listener = m_hijacking_listeners.back();
327 log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)",
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000328 static_cast<void*>(this),
Ed Masteaacfe092014-02-04 18:51:11 +0000329 m_broadcaster_name.AsCString(""),
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000330 listener->m_name.c_str(), static_cast<void*>(listener));
Ed Masteaacfe092014-02-04 18:51:11 +0000331 }
Greg Clayton44d93782014-01-27 23:43:24 +0000332 m_hijacking_listeners.pop_back();
Ed Masteaacfe092014-02-04 18:51:11 +0000333 }
Greg Clayton44d93782014-01-27 23:43:24 +0000334 if (!m_hijacking_masks.empty())
335 m_hijacking_masks.pop_back();
Jim Ingham30f9b212010-10-11 23:53:14 +0000336}
337
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000338ConstString &
339Broadcaster::GetBroadcasterClass() const
340{
341 static ConstString class_name ("lldb.anonymous");
342 return class_name;
343}
344
345BroadcastEventSpec::BroadcastEventSpec (const BroadcastEventSpec &rhs) :
346 m_broadcaster_class (rhs.m_broadcaster_class),
347 m_event_bits (rhs.m_event_bits)
348{
349}
350
351bool
352BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const
353{
354 if (GetBroadcasterClass() == rhs.GetBroadcasterClass())
355 {
356 return GetEventBits() < rhs.GetEventBits();
357 }
358 else
359 {
360 return GetBroadcasterClass() < rhs.GetBroadcasterClass();
361 }
362}
363
364const BroadcastEventSpec &
365BroadcastEventSpec::operator= (const BroadcastEventSpec &rhs)
366{
367 m_broadcaster_class = rhs.m_broadcaster_class;
368 m_event_bits = rhs.m_event_bits;
369 return *this;
370}
371
372BroadcasterManager::BroadcasterManager() :
373 m_manager_mutex(Mutex::eMutexTypeRecursive)
374{
375
376}
377
378uint32_t
379BroadcasterManager::RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
380{
381 Mutex::Locker locker(m_manager_mutex);
382
383 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
384 uint32_t available_bits = event_spec.GetEventBits();
385
386 while (iter != end_iter
387 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter)
388 {
389 available_bits &= ~((*iter).first.GetEventBits());
390 iter++;
391 }
392
393 if (available_bits != 0)
394 {
395 m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), &listener));
396 m_listeners.insert(&listener);
397 }
398
399 return available_bits;
400}
401
402bool
403BroadcasterManager::UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
404{
405 Mutex::Locker locker(m_manager_mutex);
406 bool removed_some = false;
407
408 if (m_listeners.erase(&listener) == 0)
409 return false;
410
411 ListenerMatchesAndSharedBits predicate (event_spec, listener);
412 std::vector<BroadcastEventSpec> to_be_readded;
413 uint32_t event_bits_to_remove = event_spec.GetEventBits();
414
415 // Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add:
416 while (1)
417 {
418 collection::iterator iter, end_iter = m_event_map.end();
419 iter = find_if (m_event_map.begin(), end_iter, predicate);
420 if (iter == end_iter)
421 {
422 break;
423 }
424 else
425 {
426 uint32_t iter_event_bits = (*iter).first.GetEventBits();
427 removed_some = true;
428
429 if (event_bits_to_remove != iter_event_bits)
430 {
431 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
432 to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits));
433 }
434 m_event_map.erase (iter);
435 }
436 }
437
438 // Okay now add back the bits that weren't completely removed:
439 for (size_t i = 0; i < to_be_readded.size(); i++)
440 {
441 m_event_map.insert (event_listener_key (to_be_readded[i], &listener));
442 }
443
444 return removed_some;
445}
446
447Listener *
448BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const
449{
450 Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex)));
451
452 collection::const_iterator iter, end_iter = m_event_map.end();
453 iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec));
454 if (iter != end_iter)
455 return (*iter).second;
456 else
457 return NULL;
458}
459
460void
461BroadcasterManager::RemoveListener (Listener &listener)
462{
463 Mutex::Locker locker(m_manager_mutex);
464 ListenerMatches predicate (listener);
465
466
467 if (m_listeners.erase (&listener) == 0)
468 return;
469
470 while (1)
471 {
472 collection::iterator iter, end_iter = m_event_map.end();
473 iter = find_if (m_event_map.begin(), end_iter, predicate);
474 if (iter == end_iter)
475 break;
476 else
477 m_event_map.erase(iter);
478 }
479}
480
481void
482BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster)
483{
484 Mutex::Locker locker(m_manager_mutex);
485
486 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
487
488 while (iter != end_iter
489 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter)
490 {
491 (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits());
492 iter++;
493 }
494}
495
496void
497BroadcasterManager::Clear ()
498{
499 Mutex::Locker locker(m_manager_mutex);
500 listener_collection::iterator end_iter = m_listeners.end();
501
502 for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++)
503 (*iter)->BroadcasterManagerWillDestruct(this);
504 m_listeners.clear();
505 m_event_map.clear();
506
507}