blob: c54b64069ea1f34be3241c1e6d42b5904d252f95 [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 Ingham30f9b212010-10-11 23:53:14 +000028 m_hijacking_listener(NULL),
Greg Claytoncfd1ace2010-10-31 03:01:06 +000029 m_hijacking_mask(UINT32_MAX)
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
43 // Scope for "listeners_locker"
44 {
Greg Claytoncfd1ace2010-10-31 03:01:06 +000045 Mutex::Locker listeners_locker(m_listeners_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046
47 // Make sure the listener forgets about this broadcaster. We do
48 // this in the broadcaster in case the broadcaster object initiates
49 // the removal.
50
Greg Claytoncfd1ace2010-10-31 03:01:06 +000051 collection::iterator pos, end = m_listeners.end();
52 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053 pos->first->BroadcasterWillDestruct (this);
54
Greg Claytoncfd1ace2010-10-31 03:01:06 +000055 m_listeners.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000056 }
57}
58
59const ConstString &
60Broadcaster::GetBroadcasterName ()
61{
62 return m_broadcaster_name;
63}
64
Greg Claytoncfd1ace2010-10-31 03:01:06 +000065bool
66Broadcaster::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const
67{
68 uint32_t num_names_added = 0;
69 if (event_mask && !m_event_names.empty())
70 {
71 event_names_map::const_iterator end = m_event_names.end();
72 for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1)
73 {
74 if (mask & 1)
75 {
76 event_names_map::const_iterator pos = m_event_names.find(bit);
77 if (pos != end)
78 {
79 if (num_names_added > 0)
80 s.PutCString(", ");
81
82 if (prefix_with_broadcaster_name)
83 {
84 s.PutCString (m_broadcaster_name.GetCString());
85 s.PutChar('.');
86 }
87 s.PutCString(pos->second.c_str());
88 ++num_names_added;
89 }
90 }
91 }
92 }
93 return num_names_added > 0;
94}
95
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096void
97Broadcaster::AddInitialEventsToListener (Listener *listener, uint32_t requested_events)
98{
99
100}
101
102uint32_t
103Broadcaster::AddListener (Listener* listener, uint32_t event_mask)
104{
Johnny Chend161a852010-12-22 19:29:31 +0000105 if (listener == NULL)
106 return 0;
107
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000108 Mutex::Locker locker(m_listeners_mutex);
109 collection::iterator pos, end = m_listeners.end();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110
111 collection::iterator existing_pos = end;
112 // See if we already have this listener, and if so, update its mask
113 uint32_t taken_event_types = 0;
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000114 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115 {
116 if (pos->first == listener)
117 existing_pos = pos;
118 // For now don't descriminate on who gets what
119 // FIXME: Implement "unique listener for this bit" mask
120 // taken_event_types |= pos->second;
121 }
122
123 // Each event bit in a Broadcaster object can only be used
124 // by one listener
125 uint32_t available_event_types = ~taken_event_types & event_mask;
126
127 if (available_event_types)
128 {
129 // If we didn't find our listener, add it
130 if (existing_pos == end)
131 {
132 // Grant a new listener the available event bits
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000133 m_listeners.push_back(std::make_pair(listener, available_event_types));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000134 }
135 else
136 {
137 // Grant the existing listener the available event bits
138 existing_pos->second |= available_event_types;
139 }
140
141 // Individual broadcasters decide whether they have outstanding data when a
142 // listener attaches, and insert it into the listener with this method.
143
144 AddInitialEventsToListener (listener, available_event_types);
145 }
146
147 // Return the event bits that were granted to the listener
148 return available_event_types;
149}
150
151bool
152Broadcaster::EventTypeHasListeners (uint32_t event_type)
153{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000154 Mutex::Locker locker (m_listeners_mutex);
Jim Ingham30f9b212010-10-11 23:53:14 +0000155
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000156 if (m_hijacking_listener != NULL && event_type & m_hijacking_mask)
Jim Ingham30f9b212010-10-11 23:53:14 +0000157 return true;
158
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000159 if (m_listeners.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160 return false;
161
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000162 collection::iterator pos, end = m_listeners.end();
163 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164 {
165 if (pos->second & event_type)
166 return true;
167 }
168 return false;
169}
170
171bool
172Broadcaster::RemoveListener (Listener* listener, uint32_t event_mask)
173{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000174 Mutex::Locker locker(m_listeners_mutex);
175 collection::iterator pos, end = m_listeners.end();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000176 // See if we already have this listener, and if so, update its mask
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000177 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178 {
179 if (pos->first == listener)
180 {
181 // Relinquish all event bits in "event_mask"
182 pos->second &= ~event_mask;
183 // If all bits have been relinquished then remove this listener
184 if (pos->second == 0)
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000185 m_listeners.erase (pos);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186 return true;
187 }
188 }
189 return false;
190}
191
192void
193Broadcaster::BroadcastEvent (EventSP &event_sp)
194{
195 return PrivateBroadcastEvent (event_sp, false);
196}
197
198void
199Broadcaster::BroadcastEventIfUnique (EventSP &event_sp)
200{
201 return PrivateBroadcastEvent (event_sp, true);
202}
203
204void
205Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
206{
207 // Can't add a NULL event...
208 if (event_sp.get() == NULL)
209 return;
210
211 // Update the broadcaster on this event
212 event_sp->SetBroadcaster (this);
213
214 const uint32_t event_type = event_sp->GetType();
215
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000216 Mutex::Locker event_types_locker(m_listeners_mutex);
217 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS | LIBLLDB_LOG_PROCESS));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218 if (log)
219 {
220 StreamString event_description;
221 event_sp->Dump (&event_description);
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000222 log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223 this,
224 m_broadcaster_name.AsCString(""),
225 event_description.GetData(),
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000226 unique,
227 m_hijacking_listener);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228 }
229
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000230 if (m_hijacking_listener != NULL && m_hijacking_mask & event_type)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231 {
Jim Ingham30f9b212010-10-11 23:53:14 +0000232 if (unique && m_hijacking_listener->PeekAtNextEventForBroadcasterWithType (this, event_type))
233 return;
234 m_hijacking_listener->AddEvent (event_sp);
235 }
236 else
237 {
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000238 collection::iterator pos, end = m_listeners.end();
Jim Ingham30f9b212010-10-11 23:53:14 +0000239
240
241 // Iterate through all listener/mask pairs
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000242 for (pos = m_listeners.begin(); pos != end; ++pos)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243 {
Jim Ingham30f9b212010-10-11 23:53:14 +0000244 // If the listener's mask matches any bits that we just set, then
245 // put the new event on its event queue.
246 if (event_type & pos->second)
247 {
248 if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (this, event_type))
249 continue;
250 pos->first->AddEvent (event_sp);
251 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000252 }
253 }
254}
255
256void
257Broadcaster::BroadcastEvent (uint32_t event_type, EventData *event_data)
258{
259 EventSP event_sp (new Event (event_type, event_data));
260 PrivateBroadcastEvent (event_sp, false);
261}
262
263void
264Broadcaster::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
265{
266 EventSP event_sp (new Event (event_type, event_data));
267 PrivateBroadcastEvent (event_sp, true);
268}
269
Jim Ingham30f9b212010-10-11 23:53:14 +0000270bool
271Broadcaster::HijackBroadcaster (Listener *listener, uint32_t event_mask)
272{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000273 Mutex::Locker event_types_locker(m_listeners_mutex);
Jim Ingham1e7a9ee2011-01-23 21:14:08 +0000274 assert (m_hijacking_listener == NULL);
275
Jim Ingham30f9b212010-10-11 23:53:14 +0000276 if (m_hijacking_listener != NULL)
277 return false;
278
279 m_hijacking_listener = listener;
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000280 m_hijacking_mask = event_mask;
Jim Ingham30f9b212010-10-11 23:53:14 +0000281 return true;
282}
283
284void
285Broadcaster::RestoreBroadcaster ()
286{
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000287 Mutex::Locker event_types_locker(m_listeners_mutex);
Jim Ingham30f9b212010-10-11 23:53:14 +0000288 m_hijacking_listener = NULL;
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000289 m_hijacking_mask = 0;
Jim Ingham30f9b212010-10-11 23:53:14 +0000290}
291