blob: b311a8b3eeded5b8e9722d5ce0646b764aa7a690 [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),
26 m_broadcaster_listeners (),
27 m_broadcaster_listeners_mutex (Mutex::eMutexTypeRecursive)
28{
29 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
30 if (log)
31 log->Printf ("%p Broadcaster::Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
32
33}
34
35Broadcaster::~Broadcaster()
36{
37 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
38 if (log)
39 log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
40
41 // Scope for "listeners_locker"
42 {
43 Mutex::Locker listeners_locker(m_broadcaster_listeners_mutex);
44
45 // Make sure the listener forgets about this broadcaster. We do
46 // this in the broadcaster in case the broadcaster object initiates
47 // the removal.
48
49 collection::iterator pos, end = m_broadcaster_listeners.end();
50 for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
51 pos->first->BroadcasterWillDestruct (this);
52
53 m_broadcaster_listeners.clear();
54 }
55}
56
57const ConstString &
58Broadcaster::GetBroadcasterName ()
59{
60 return m_broadcaster_name;
61}
62
63void
64Broadcaster::AddInitialEventsToListener (Listener *listener, uint32_t requested_events)
65{
66
67}
68
69uint32_t
70Broadcaster::AddListener (Listener* listener, uint32_t event_mask)
71{
72 Mutex::Locker locker(m_broadcaster_listeners_mutex);
73 collection::iterator pos, end = m_broadcaster_listeners.end();
74
75 collection::iterator existing_pos = end;
76 // See if we already have this listener, and if so, update its mask
77 uint32_t taken_event_types = 0;
78 for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
79 {
80 if (pos->first == listener)
81 existing_pos = pos;
82 // For now don't descriminate on who gets what
83 // FIXME: Implement "unique listener for this bit" mask
84 // taken_event_types |= pos->second;
85 }
86
87 // Each event bit in a Broadcaster object can only be used
88 // by one listener
89 uint32_t available_event_types = ~taken_event_types & event_mask;
90
91 if (available_event_types)
92 {
93 // If we didn't find our listener, add it
94 if (existing_pos == end)
95 {
96 // Grant a new listener the available event bits
97 m_broadcaster_listeners.push_back(std::make_pair(listener, available_event_types));
98 }
99 else
100 {
101 // Grant the existing listener the available event bits
102 existing_pos->second |= available_event_types;
103 }
104
105 // Individual broadcasters decide whether they have outstanding data when a
106 // listener attaches, and insert it into the listener with this method.
107
108 AddInitialEventsToListener (listener, available_event_types);
109 }
110
111 // Return the event bits that were granted to the listener
112 return available_event_types;
113}
114
115bool
116Broadcaster::EventTypeHasListeners (uint32_t event_type)
117{
118 Mutex::Locker locker (m_broadcaster_listeners_mutex);
119 if (m_broadcaster_listeners.empty())
120 return false;
121
122 collection::iterator pos, end = m_broadcaster_listeners.end();
123 for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
124 {
125 if (pos->second & event_type)
126 return true;
127 }
128 return false;
129}
130
131bool
132Broadcaster::RemoveListener (Listener* listener, uint32_t event_mask)
133{
134 Mutex::Locker locker(m_broadcaster_listeners_mutex);
135 collection::iterator pos, end = m_broadcaster_listeners.end();
136 // See if we already have this listener, and if so, update its mask
137 for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
138 {
139 if (pos->first == listener)
140 {
141 // Relinquish all event bits in "event_mask"
142 pos->second &= ~event_mask;
143 // If all bits have been relinquished then remove this listener
144 if (pos->second == 0)
145 m_broadcaster_listeners.erase (pos);
146 return true;
147 }
148 }
149 return false;
150}
151
152void
153Broadcaster::BroadcastEvent (EventSP &event_sp)
154{
155 return PrivateBroadcastEvent (event_sp, false);
156}
157
158void
159Broadcaster::BroadcastEventIfUnique (EventSP &event_sp)
160{
161 return PrivateBroadcastEvent (event_sp, true);
162}
163
164void
165Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
166{
167 // Can't add a NULL event...
168 if (event_sp.get() == NULL)
169 return;
170
171 // Update the broadcaster on this event
172 event_sp->SetBroadcaster (this);
173
174 const uint32_t event_type = event_sp->GetType();
175
176 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
177 if (log)
178 {
179 StreamString event_description;
180 event_sp->Dump (&event_description);
181 log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i)",
182 this,
183 m_broadcaster_name.AsCString(""),
184 event_description.GetData(),
185 unique);
186 }
187
188 Mutex::Locker event_types_locker(m_broadcaster_listeners_mutex);
189 collection::iterator pos, end = m_broadcaster_listeners.end();
190
191
192 // Iterate through all listener/mask pairs
193 for (pos = m_broadcaster_listeners.begin(); pos != end; ++pos)
194 {
195 // If the listener's mask matches any bits that we just set, then
196 // put the new event on its event queue.
197 if (event_type & pos->second)
198 {
199 if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (this, event_type))
200 continue;
201 pos->first->AddEvent (event_sp);
202 }
203 }
204}
205
206void
207Broadcaster::BroadcastEvent (uint32_t event_type, EventData *event_data)
208{
209 EventSP event_sp (new Event (event_type, event_data));
210 PrivateBroadcastEvent (event_sp, false);
211}
212
213void
214Broadcaster::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
215{
216 EventSP event_sp (new Event (event_type, event_data));
217 PrivateBroadcastEvent (event_sp, true);
218}
219