blob: 1d264a6c67505cee92b8d80629441276273365fe [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
24Broadcaster::Broadcaster (const char *name) :
25 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(),
29 m_hijacking_masks()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030{
Greg Clayton2d4edfb2010-11-06 01:53:30 +000031 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032 if (log)
33 log->Printf ("%p Broadcaster::Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
34
35}
36
37Broadcaster::~Broadcaster()
38{
Greg Clayton2d4edfb2010-11-06 01:53:30 +000039 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040 if (log)
41 log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
42
Greg Clayton1ed54f52011-10-01 00:45:15 +000043 Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044}
45
Greg Clayton1ed54f52011-10-01 00:45:15 +000046void
47Broadcaster::Clear()
48{
49 Mutex::Locker listeners_locker(m_listeners_mutex);
50
51 // Make sure the listener forgets about this broadcaster. We do
52 // this in the broadcaster in case the broadcaster object initiates
53 // the removal.
54
55 collection::iterator pos, end = m_listeners.end();
56 for (pos = m_listeners.begin(); pos != end; ++pos)
57 pos->first->BroadcasterWillDestruct (this);
58
59 m_listeners.clear();
60}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061const ConstString &
62Broadcaster::GetBroadcasterName ()
63{
64 return m_broadcaster_name;
65}
66
Greg Claytoncfd1ace2010-10-31 03:01:06 +000067bool
68Broadcaster::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const
69{
70 uint32_t num_names_added = 0;
71 if (event_mask && !m_event_names.empty())
72 {
73 event_names_map::const_iterator end = m_event_names.end();
74 for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1)
75 {
76 if (mask & 1)
77 {
78 event_names_map::const_iterator pos = m_event_names.find(bit);
79 if (pos != end)
80 {
81 if (num_names_added > 0)
82 s.PutCString(", ");
83
84 if (prefix_with_broadcaster_name)
85 {
86 s.PutCString (m_broadcaster_name.GetCString());
87 s.PutChar('.');
88 }
89 s.PutCString(pos->second.c_str());
90 ++num_names_added;
91 }
92 }
93 }
94 }
95 return num_names_added > 0;
96}
97
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098void
99Broadcaster::AddInitialEventsToListener (Listener *listener, uint32_t requested_events)
100{
101
102}
103
104uint32_t
105Broadcaster::AddListener (Listener* listener, uint32_t event_mask)
106{
Johnny Chend161a852010-12-22 19:29:31 +0000107 if (listener == NULL)
108 return 0;
109
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000110 Mutex::Locker locker(m_listeners_mutex);
111 collection::iterator pos, end = m_listeners.end();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112
113 collection::iterator existing_pos = end;
114 // See if we already have this listener, and if so, update its mask
115 uint32_t taken_event_types = 0;
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000116 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 {
118 if (pos->first == listener)
119 existing_pos = pos;
120 // For now don't descriminate on who gets what
121 // FIXME: Implement "unique listener for this bit" mask
122 // taken_event_types |= pos->second;
123 }
124
125 // Each event bit in a Broadcaster object can only be used
126 // by one listener
127 uint32_t available_event_types = ~taken_event_types & event_mask;
128
129 if (available_event_types)
130 {
131 // If we didn't find our listener, add it
132 if (existing_pos == end)
133 {
134 // Grant a new listener the available event bits
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000135 m_listeners.push_back(std::make_pair(listener, available_event_types));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136 }
137 else
138 {
139 // Grant the existing listener the available event bits
140 existing_pos->second |= available_event_types;
141 }
142
143 // Individual broadcasters decide whether they have outstanding data when a
144 // listener attaches, and insert it into the listener with this method.
145
146 AddInitialEventsToListener (listener, available_event_types);
147 }
148
149 // Return the event bits that were granted to the listener
150 return available_event_types;
151}
152
153bool
154Broadcaster::EventTypeHasListeners (uint32_t event_type)
155{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000156 Mutex::Locker locker (m_listeners_mutex);
Jim Ingham30f9b212010-10-11 23:53:14 +0000157
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000158 if (m_hijacking_listeners.size() > 0 && event_type & m_hijacking_masks.back())
Jim Ingham30f9b212010-10-11 23:53:14 +0000159 return true;
160
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000161 if (m_listeners.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162 return false;
163
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000164 collection::iterator pos, end = m_listeners.end();
165 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166 {
167 if (pos->second & event_type)
168 return true;
169 }
170 return false;
171}
172
173bool
174Broadcaster::RemoveListener (Listener* listener, uint32_t event_mask)
175{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000176 Mutex::Locker locker(m_listeners_mutex);
177 collection::iterator pos, end = m_listeners.end();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178 // See if we already have this listener, and if so, update its mask
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000179 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180 {
181 if (pos->first == listener)
182 {
183 // Relinquish all event bits in "event_mask"
184 pos->second &= ~event_mask;
185 // If all bits have been relinquished then remove this listener
186 if (pos->second == 0)
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000187 m_listeners.erase (pos);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188 return true;
189 }
190 }
191 return false;
192}
193
194void
195Broadcaster::BroadcastEvent (EventSP &event_sp)
196{
197 return PrivateBroadcastEvent (event_sp, false);
198}
199
200void
201Broadcaster::BroadcastEventIfUnique (EventSP &event_sp)
202{
203 return PrivateBroadcastEvent (event_sp, true);
204}
205
206void
207Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
208{
209 // Can't add a NULL event...
210 if (event_sp.get() == NULL)
211 return;
212
213 // Update the broadcaster on this event
214 event_sp->SetBroadcaster (this);
215
216 const uint32_t event_type = event_sp->GetType();
217
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000218 Mutex::Locker event_types_locker(m_listeners_mutex);
Greg Clayton11177952011-02-10 06:51:22 +0000219
220 Listener *hijacking_listener = NULL;
221 if (!m_hijacking_listeners.empty())
222 {
223 assert (!m_hijacking_masks.empty());
224 hijacking_listener = m_hijacking_listeners.back();
225 if ((event_type & m_hijacking_masks.back()) == 0)
226 hijacking_listener = NULL;
227 }
228
Jim Inghamdfac4cc2011-01-23 21:20:20 +0000229 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000230 if (log)
231 {
232 StreamString event_description;
233 event_sp->Dump (&event_description);
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000234 log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235 this,
236 m_broadcaster_name.AsCString(""),
237 event_description.GetData(),
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000238 unique,
Greg Clayton11177952011-02-10 06:51:22 +0000239 hijacking_listener);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240 }
241
Greg Clayton11177952011-02-10 06:51:22 +0000242 if (hijacking_listener)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243 {
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000244 if (unique && hijacking_listener->PeekAtNextEventForBroadcasterWithType (this, event_type))
Jim Ingham30f9b212010-10-11 23:53:14 +0000245 return;
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000246 hijacking_listener->AddEvent (event_sp);
Jim Ingham30f9b212010-10-11 23:53:14 +0000247 }
248 else
249 {
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000250 collection::iterator pos, end = m_listeners.end();
Jim Ingham30f9b212010-10-11 23:53:14 +0000251
252
253 // Iterate through all listener/mask pairs
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000254 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000255 {
Jim Ingham30f9b212010-10-11 23:53:14 +0000256 // If the listener's mask matches any bits that we just set, then
257 // put the new event on its event queue.
258 if (event_type & pos->second)
259 {
260 if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (this, event_type))
261 continue;
262 pos->first->AddEvent (event_sp);
263 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000264 }
265 }
266}
267
268void
269Broadcaster::BroadcastEvent (uint32_t event_type, EventData *event_data)
270{
271 EventSP event_sp (new Event (event_type, event_data));
272 PrivateBroadcastEvent (event_sp, false);
273}
274
275void
276Broadcaster::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
277{
278 EventSP event_sp (new Event (event_type, event_data));
279 PrivateBroadcastEvent (event_sp, true);
280}
281
Jim Ingham30f9b212010-10-11 23:53:14 +0000282bool
283Broadcaster::HijackBroadcaster (Listener *listener, uint32_t event_mask)
284{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000285 Mutex::Locker event_types_locker(m_listeners_mutex);
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000286
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000287 m_hijacking_listeners.push_back(listener);
288 m_hijacking_masks.push_back(event_mask);
Jim Ingham30f9b212010-10-11 23:53:14 +0000289 return true;
290}
291
292void
293Broadcaster::RestoreBroadcaster ()
294{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000295 Mutex::Locker event_types_locker(m_listeners_mutex);
Jim Inghamc4f4f7212011-02-08 05:16:50 +0000296 m_hijacking_listeners.pop_back();
297 m_hijacking_masks.pop_back();
Jim Ingham30f9b212010-10-11 23:53:14 +0000298}
299