blob: dc37516c29c2493992cbd0f725ab5e78be1cc5af [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
306void
307Broadcaster::RestoreBroadcaster ()
308{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000309 Mutex::Locker event_types_locker(m_listeners_mutex);
Johnny Chen55d85f32012-03-29 20:02:33 +0000310
Greg Clayton44d93782014-01-27 23:43:24 +0000311 if (!m_hijacking_listeners.empty())
Ed Masteaacfe092014-02-04 18:51:11 +0000312 {
313 Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
314 if (log)
315 {
316 Listener *listener = m_hijacking_listeners.back();
317 log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)",
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000318 static_cast<void*>(this),
Ed Masteaacfe092014-02-04 18:51:11 +0000319 m_broadcaster_name.AsCString(""),
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000320 listener->m_name.c_str(), static_cast<void*>(listener));
Ed Masteaacfe092014-02-04 18:51:11 +0000321 }
Greg Clayton44d93782014-01-27 23:43:24 +0000322 m_hijacking_listeners.pop_back();
Ed Masteaacfe092014-02-04 18:51:11 +0000323 }
Greg Clayton44d93782014-01-27 23:43:24 +0000324 if (!m_hijacking_masks.empty())
325 m_hijacking_masks.pop_back();
Jim Ingham30f9b212010-10-11 23:53:14 +0000326}
327
Jim Ingham4bddaeb2012-02-16 06:50:00 +0000328ConstString &
329Broadcaster::GetBroadcasterClass() const
330{
331 static ConstString class_name ("lldb.anonymous");
332 return class_name;
333}
334
335BroadcastEventSpec::BroadcastEventSpec (const BroadcastEventSpec &rhs) :
336 m_broadcaster_class (rhs.m_broadcaster_class),
337 m_event_bits (rhs.m_event_bits)
338{
339}
340
341bool
342BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const
343{
344 if (GetBroadcasterClass() == rhs.GetBroadcasterClass())
345 {
346 return GetEventBits() < rhs.GetEventBits();
347 }
348 else
349 {
350 return GetBroadcasterClass() < rhs.GetBroadcasterClass();
351 }
352}
353
354const BroadcastEventSpec &
355BroadcastEventSpec::operator= (const BroadcastEventSpec &rhs)
356{
357 m_broadcaster_class = rhs.m_broadcaster_class;
358 m_event_bits = rhs.m_event_bits;
359 return *this;
360}
361
362BroadcasterManager::BroadcasterManager() :
363 m_manager_mutex(Mutex::eMutexTypeRecursive)
364{
365
366}
367
368uint32_t
369BroadcasterManager::RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
370{
371 Mutex::Locker locker(m_manager_mutex);
372
373 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
374 uint32_t available_bits = event_spec.GetEventBits();
375
376 while (iter != end_iter
377 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter)
378 {
379 available_bits &= ~((*iter).first.GetEventBits());
380 iter++;
381 }
382
383 if (available_bits != 0)
384 {
385 m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), &listener));
386 m_listeners.insert(&listener);
387 }
388
389 return available_bits;
390}
391
392bool
393BroadcasterManager::UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
394{
395 Mutex::Locker locker(m_manager_mutex);
396 bool removed_some = false;
397
398 if (m_listeners.erase(&listener) == 0)
399 return false;
400
401 ListenerMatchesAndSharedBits predicate (event_spec, listener);
402 std::vector<BroadcastEventSpec> to_be_readded;
403 uint32_t event_bits_to_remove = event_spec.GetEventBits();
404
405 // Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add:
406 while (1)
407 {
408 collection::iterator iter, end_iter = m_event_map.end();
409 iter = find_if (m_event_map.begin(), end_iter, predicate);
410 if (iter == end_iter)
411 {
412 break;
413 }
414 else
415 {
416 uint32_t iter_event_bits = (*iter).first.GetEventBits();
417 removed_some = true;
418
419 if (event_bits_to_remove != iter_event_bits)
420 {
421 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
422 to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits));
423 }
424 m_event_map.erase (iter);
425 }
426 }
427
428 // Okay now add back the bits that weren't completely removed:
429 for (size_t i = 0; i < to_be_readded.size(); i++)
430 {
431 m_event_map.insert (event_listener_key (to_be_readded[i], &listener));
432 }
433
434 return removed_some;
435}
436
437Listener *
438BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const
439{
440 Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex)));
441
442 collection::const_iterator iter, end_iter = m_event_map.end();
443 iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec));
444 if (iter != end_iter)
445 return (*iter).second;
446 else
447 return NULL;
448}
449
450void
451BroadcasterManager::RemoveListener (Listener &listener)
452{
453 Mutex::Locker locker(m_manager_mutex);
454 ListenerMatches predicate (listener);
455
456
457 if (m_listeners.erase (&listener) == 0)
458 return;
459
460 while (1)
461 {
462 collection::iterator iter, end_iter = m_event_map.end();
463 iter = find_if (m_event_map.begin(), end_iter, predicate);
464 if (iter == end_iter)
465 break;
466 else
467 m_event_map.erase(iter);
468 }
469}
470
471void
472BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster)
473{
474 Mutex::Locker locker(m_manager_mutex);
475
476 collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
477
478 while (iter != end_iter
479 && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter)
480 {
481 (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits());
482 iter++;
483 }
484}
485
486void
487BroadcasterManager::Clear ()
488{
489 Mutex::Locker locker(m_manager_mutex);
490 listener_collection::iterator end_iter = m_listeners.end();
491
492 for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++)
493 (*iter)->BroadcasterManagerWillDestruct(this);
494 m_listeners.clear();
495 m_event_map.clear();
496
497}