summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core/Broadcaster.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core/Broadcaster.cpp')
-rw-r--r--lldb/source/Core/Broadcaster.cpp190
1 files changed, 118 insertions, 72 deletions
diff --git a/lldb/source/Core/Broadcaster.cpp b/lldb/source/Core/Broadcaster.cpp
index 3f125183d0b..ec91f8d8a7f 100644
--- a/lldb/source/Core/Broadcaster.cpp
+++ b/lldb/source/Core/Broadcaster.cpp
@@ -61,6 +61,33 @@ Broadcaster::CheckInWithManager ()
}
void
+Broadcaster::BroadcasterImpl::ListenerIterator (std::function <bool (const lldb::ListenerSP &listener_sp, uint32_t &event_mask)> const &callback)
+{
+ // Private iterator that should be used by everyone except BroadcasterImpl::RemoveListener().
+ // We have weak pointers to our listeners which means that at any point the listener can
+ // expire which means we will need to take it out of our list. To take care of this, we
+ // iterate and check that the weak pointer can be made into a valid shared pointer before
+ // we call the callback. If the weak pointer has expired, we remove it from our list.
+ collection::iterator pos = m_listeners.begin();
+ while (pos != m_listeners.end())
+ {
+ lldb::ListenerSP curr_listener_sp(pos->first.lock());
+ if (curr_listener_sp)
+ {
+ if (callback(curr_listener_sp, pos->second))
+ ++pos; // Keep iterating
+ else
+ return; // Done iterating
+ }
+ else
+ {
+ // The listener has been expired. Remove this entry.
+ pos = m_listeners.erase(pos);
+ }
+ }
+}
+
+void
Broadcaster::BroadcasterImpl::Clear()
{
Mutex::Locker listeners_locker(m_listeners_mutex);
@@ -68,10 +95,11 @@ Broadcaster::BroadcasterImpl::Clear()
// Make sure the listener forgets about this broadcaster. We do
// this in the broadcaster in case the broadcaster object initiates
// the removal.
-
- collection::iterator pos, end = m_listeners.end();
- for (pos = m_listeners.begin(); pos != end; ++pos)
- pos->first->BroadcasterWillDestruct (&m_broadcaster);
+
+ ListenerIterator([this](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
+ curr_listener_sp->BroadcasterWillDestruct (&m_broadcaster);
+ return true; // Keep iterating
+ });
m_listeners.clear();
}
@@ -114,57 +142,45 @@ Broadcaster::BroadcasterImpl::GetEventNames (Stream &s, uint32_t event_mask, boo
}
void
-Broadcaster::AddInitialEventsToListener (lldb::ListenerSP listener_sp, uint32_t requested_events)
+Broadcaster::AddInitialEventsToListener (const lldb::ListenerSP &listener_sp, uint32_t requested_events)
{
}
uint32_t
-Broadcaster::BroadcasterImpl::AddListener (lldb::ListenerSP listener_sp, uint32_t event_mask)
+Broadcaster::BroadcasterImpl::AddListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
{
if (!listener_sp)
return 0;
Mutex::Locker locker(m_listeners_mutex);
- collection::iterator pos, end = m_listeners.end();
- collection::iterator existing_pos = end;
// See if we already have this listener, and if so, update its mask
- uint32_t taken_event_types = 0;
- for (pos = m_listeners.begin(); pos != end; ++pos)
- {
- if (pos->first == listener_sp)
- existing_pos = pos;
- // For now don't descriminate on who gets what
- // FIXME: Implement "unique listener for this bit" mask
- // taken_event_types |= pos->second;
- }
- // Each event bit in a Broadcaster object can only be used
- // by one listener
- uint32_t available_event_types = ~taken_event_types & event_mask;
+ bool handled = false;
- if (available_event_types)
- {
- // If we didn't find our listener, add it
- if (existing_pos == end)
+ ListenerIterator([this, &listener_sp, &handled, event_mask](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
+ if (curr_listener_sp == listener_sp)
{
- // Grant a new listener the available event bits
- m_listeners.push_back(std::make_pair(listener_sp, available_event_types));
- }
- else
- {
- // Grant the existing listener the available event bits
- existing_pos->second |= available_event_types;
+ handled = true;
+ curr_event_mask |= event_mask;
+ m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask);
+ return false; // Stop iterating
}
+ return true; // Keep iterating
+ });
+
+ if (!handled)
+ {
+ // Grant a new listener the available event bits
+ m_listeners.push_back(std::make_pair(lldb::ListenerWP(listener_sp), event_mask));
// Individual broadcasters decide whether they have outstanding data when a
// listener attaches, and insert it into the listener with this method.
-
- m_broadcaster.AddInitialEventsToListener (listener_sp, available_event_types);
+ m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask);
}
// Return the event bits that were granted to the listener
- return available_event_types;
+ return event_mask;
}
bool
@@ -178,36 +194,63 @@ Broadcaster::BroadcasterImpl::EventTypeHasListeners (uint32_t event_type)
if (m_listeners.empty())
return false;
- collection::iterator pos, end = m_listeners.end();
- for (pos = m_listeners.begin(); pos != end; ++pos)
- {
- if (pos->second & event_type)
- return true;
- }
- return false;
+ bool result = false;
+ ListenerIterator([this, event_type, &result](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
+
+ if (curr_event_mask & event_type)
+ {
+ result = true;
+ return false; // Stop iterating
+ }
+ else
+ {
+ return true; // Keep iterating
+ }
+ });
+ return result;
}
bool
-Broadcaster::BroadcasterImpl::RemoveListener (lldb::ListenerSP listener_sp, uint32_t event_mask)
+Broadcaster::BroadcasterImpl::RemoveListener (lldb_private::Listener *listener, uint32_t event_mask)
{
- Mutex::Locker locker(m_listeners_mutex);
- collection::iterator pos, end = m_listeners.end();
- // See if we already have this listener, and if so, update its mask
- for (pos = m_listeners.begin(); pos != end; ++pos)
+ if (listener)
{
- if (pos->first == listener_sp)
+ Mutex::Locker locker(m_listeners_mutex);
+ collection::iterator pos = m_listeners.begin();
+ // See if we already have this listener, and if so, update its mask
+ while (pos != m_listeners.end())
{
- // Relinquish all event bits in "event_mask"
- pos->second &= ~event_mask;
- // If all bits have been relinquished then remove this listener
- if (pos->second == 0)
- m_listeners.erase (pos);
- return true;
+ lldb::ListenerSP curr_listener_sp(pos->first.lock());
+ if (curr_listener_sp)
+ {
+ if (curr_listener_sp.get() == listener)
+ {
+ // Relinquish all event bits in "event_mask"
+ pos->second &= ~event_mask;
+ // If all bits have been relinquished then remove this listener
+ if (pos->second == 0)
+ m_listeners.erase (pos);
+ return true;
+ }
+ ++pos;
+ }
+ else
+ {
+ // The listener has been destroyed since we couldn't turn the std::weak_ptr
+ // into a valid shared pointer, so we can remove it.
+ pos = m_listeners.erase (pos);
+ }
}
}
return false;
}
+bool
+Broadcaster::BroadcasterImpl::RemoveListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
+{
+ return RemoveListener (listener_sp.get(), event_mask);
+}
+
void
Broadcaster::BroadcasterImpl::BroadcastEvent (EventSP &event_sp)
{
@@ -232,7 +275,7 @@ Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool uni
const uint32_t event_type = event_sp->GetType();
- Mutex::Locker event_types_locker(m_listeners_mutex);
+ Mutex::Locker locker(m_listeners_mutex);
ListenerSP hijacking_listener_sp;
@@ -263,20 +306,16 @@ Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool uni
}
else
{
- collection::iterator pos, end = m_listeners.end();
- // Iterate through all listener/mask pairs
- for (pos = m_listeners.begin(); pos != end; ++pos)
- {
- // If the listener's mask matches any bits that we just set, then
- // put the new event on its event queue.
- if (event_type & pos->second)
+ ListenerIterator([this, unique, event_type, &event_sp](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
+
+ if (event_type & curr_event_mask)
{
- if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type))
- continue;
- pos->first->AddEvent (event_sp);
+ if (!unique || curr_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type) == nullptr)
+ curr_listener_sp->AddEvent (event_sp);
}
- }
+ return true; // Keep iterating
+ });
}
}
@@ -288,6 +327,13 @@ Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, EventData *ev
}
void
+Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, const lldb::EventDataSP &event_data_sp)
+{
+ EventSP event_sp (new Event (event_type, event_data_sp));
+ PrivateBroadcastEvent (event_sp, false);
+}
+
+void
Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
{
EventSP event_sp (new Event (event_type, event_data));
@@ -295,9 +341,9 @@ Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, Event
}
bool
-Broadcaster::BroadcasterImpl::HijackBroadcaster (ListenerSP listener_sp, uint32_t event_mask)
+Broadcaster::BroadcasterImpl::HijackBroadcaster (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
{
- Mutex::Locker event_types_locker(m_listeners_mutex);
+ Mutex::Locker locker(m_listeners_mutex);
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
if (log)
@@ -312,7 +358,7 @@ Broadcaster::BroadcasterImpl::HijackBroadcaster (ListenerSP listener_sp, uint32_
bool
Broadcaster::BroadcasterImpl::IsHijackedForEvent (uint32_t event_mask)
{
- Mutex::Locker event_types_locker(m_listeners_mutex);
+ Mutex::Locker locker(m_listeners_mutex);
if (!m_hijacking_listeners.empty())
return (event_mask & m_hijacking_masks.back()) != 0;
@@ -335,7 +381,7 @@ Broadcaster::BroadcasterImpl::GetHijackingListenerName()
void
Broadcaster::BroadcasterImpl::RestoreBroadcaster ()
{
- Mutex::Locker event_types_locker(m_listeners_mutex);
+ Mutex::Locker locker(m_listeners_mutex);
if (!m_hijacking_listeners.empty())
{
@@ -391,7 +437,7 @@ BroadcasterManager::MakeBroadcasterManager()
}
uint32_t
-BroadcasterManager::RegisterListenerForEvents (ListenerSP listener_sp, BroadcastEventSpec event_spec)
+BroadcasterManager::RegisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec)
{
Mutex::Locker locker(m_manager_mutex);
@@ -415,7 +461,7 @@ BroadcasterManager::RegisterListenerForEvents (ListenerSP listener_sp, Broadcast
}
bool
-BroadcasterManager::UnregisterListenerForEvents (ListenerSP listener_sp, BroadcastEventSpec event_spec)
+BroadcasterManager::UnregisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec)
{
Mutex::Locker locker(m_manager_mutex);
bool removed_some = false;
@@ -495,7 +541,7 @@ BroadcasterManager::RemoveListener(Listener *listener)
}
void
-BroadcasterManager::RemoveListener (ListenerSP listener_sp)
+BroadcasterManager::RemoveListener (const lldb::ListenerSP &listener_sp)
{
Mutex::Locker locker(m_manager_mutex);
ListenerMatches predicate (listener_sp);
OpenPOWER on IntegriCloud