summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core')
-rw-r--r--lldb/source/Core/Broadcaster.cpp184
-rw-r--r--lldb/source/Core/Communication.cpp11
-rw-r--r--lldb/source/Core/Debugger.cpp3
-rw-r--r--lldb/source/Core/Listener.cpp41
4 files changed, 235 insertions, 4 deletions
diff --git a/lldb/source/Core/Broadcaster.cpp b/lldb/source/Core/Broadcaster.cpp
index 1d264a6c675..4a4396f470b 100644
--- a/lldb/source/Core/Broadcaster.cpp
+++ b/lldb/source/Core/Broadcaster.cpp
@@ -21,12 +21,13 @@
using namespace lldb;
using namespace lldb_private;
-Broadcaster::Broadcaster (const char *name) :
+Broadcaster::Broadcaster (BroadcasterManager *manager, const char *name) :
m_broadcaster_name (name),
m_listeners (),
m_listeners_mutex (Mutex::eMutexTypeRecursive),
m_hijacking_listeners(),
- m_hijacking_masks()
+ m_hijacking_masks(),
+ m_manager (manager)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
@@ -44,6 +45,15 @@ Broadcaster::~Broadcaster()
}
void
+Broadcaster::CheckInWithManager ()
+{
+ if (m_manager != NULL)
+ {
+ m_manager->SignUpListenersForBroadcaster(*this);
+ }
+}
+
+void
Broadcaster::Clear()
{
Mutex::Locker listeners_locker(m_listeners_mutex);
@@ -297,3 +307,173 @@ Broadcaster::RestoreBroadcaster ()
m_hijacking_masks.pop_back();
}
+ConstString &
+Broadcaster::GetBroadcasterClass() const
+{
+ static ConstString class_name ("lldb.anonymous");
+ return class_name;
+}
+
+BroadcastEventSpec::BroadcastEventSpec (const BroadcastEventSpec &rhs) :
+ m_broadcaster_class (rhs.m_broadcaster_class),
+ m_event_bits (rhs.m_event_bits)
+{
+}
+
+bool
+BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const
+{
+ if (GetBroadcasterClass() == rhs.GetBroadcasterClass())
+ {
+ return GetEventBits() < rhs.GetEventBits();
+ }
+ else
+ {
+ return GetBroadcasterClass() < rhs.GetBroadcasterClass();
+ }
+}
+
+const BroadcastEventSpec &
+BroadcastEventSpec::operator= (const BroadcastEventSpec &rhs)
+{
+ m_broadcaster_class = rhs.m_broadcaster_class;
+ m_event_bits = rhs.m_event_bits;
+ return *this;
+}
+
+BroadcasterManager::BroadcasterManager() :
+ m_manager_mutex(Mutex::eMutexTypeRecursive)
+{
+
+}
+
+uint32_t
+BroadcasterManager::RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
+{
+ Mutex::Locker locker(m_manager_mutex);
+
+ collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
+ uint32_t available_bits = event_spec.GetEventBits();
+
+ while (iter != end_iter
+ && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter)
+ {
+ available_bits &= ~((*iter).first.GetEventBits());
+ iter++;
+ }
+
+ if (available_bits != 0)
+ {
+ m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), &listener));
+ m_listeners.insert(&listener);
+ }
+
+ return available_bits;
+}
+
+bool
+BroadcasterManager::UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
+{
+ Mutex::Locker locker(m_manager_mutex);
+ bool removed_some = false;
+
+ if (m_listeners.erase(&listener) == 0)
+ return false;
+
+ ListenerMatchesAndSharedBits predicate (event_spec, listener);
+ std::vector<BroadcastEventSpec> to_be_readded;
+ uint32_t event_bits_to_remove = event_spec.GetEventBits();
+
+ // Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add:
+ while (1)
+ {
+ collection::iterator iter, end_iter = m_event_map.end();
+ iter = find_if (m_event_map.begin(), end_iter, predicate);
+ if (iter == end_iter)
+ {
+ break;
+ }
+ else
+ {
+ uint32_t iter_event_bits = (*iter).first.GetEventBits();
+ removed_some = true;
+
+ if (event_bits_to_remove != iter_event_bits)
+ {
+ uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
+ to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits));
+ }
+ m_event_map.erase (iter);
+ }
+ }
+
+ // Okay now add back the bits that weren't completely removed:
+ for (size_t i = 0; i < to_be_readded.size(); i++)
+ {
+ m_event_map.insert (event_listener_key (to_be_readded[i], &listener));
+ }
+
+ return removed_some;
+}
+
+Listener *
+BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const
+{
+ Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex)));
+
+ collection::const_iterator iter, end_iter = m_event_map.end();
+ iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec));
+ if (iter != end_iter)
+ return (*iter).second;
+ else
+ return NULL;
+}
+
+void
+BroadcasterManager::RemoveListener (Listener &listener)
+{
+ Mutex::Locker locker(m_manager_mutex);
+ ListenerMatches predicate (listener);
+
+
+ if (m_listeners.erase (&listener) == 0)
+ return;
+
+ while (1)
+ {
+ collection::iterator iter, end_iter = m_event_map.end();
+ iter = find_if (m_event_map.begin(), end_iter, predicate);
+ if (iter == end_iter)
+ break;
+ else
+ m_event_map.erase(iter);
+ }
+}
+
+void
+BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster)
+{
+ Mutex::Locker locker(m_manager_mutex);
+
+ collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
+
+ while (iter != end_iter
+ && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter)
+ {
+ (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits());
+ iter++;
+ }
+}
+
+void
+BroadcasterManager::Clear ()
+{
+ Mutex::Locker locker(m_manager_mutex);
+ listener_collection::iterator end_iter = m_listeners.end();
+
+ for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++)
+ (*iter)->BroadcasterManagerWillDestruct(this);
+ m_listeners.clear();
+ m_event_map.clear();
+
+}
diff --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp
index 45850f3858b..35af6440df2 100644
--- a/lldb/source/Core/Communication.cpp
+++ b/lldb/source/Core/Communication.cpp
@@ -23,11 +23,18 @@
using namespace lldb;
using namespace lldb_private;
+ConstString &
+Communication::GetStaticBroadcasterClass ()
+{
+ static ConstString class_name ("lldb.communication");
+ return class_name;
+}
+
//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
Communication::Communication(const char *name) :
- Broadcaster (name),
+ Broadcaster (NULL, name),
m_connection_sp (),
m_read_thread (LLDB_INVALID_HOST_THREAD),
m_read_thread_enabled (false),
@@ -48,6 +55,8 @@ Communication::Communication(const char *name) :
SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit");
SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit");
SetEventName (eBroadcastBitPacketAvailable, "packet available");
+
+ CheckInWithManager();
}
//----------------------------------------------------------------------
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index ad6b86f044b..7f768e9ec41 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -333,7 +333,7 @@ Debugger::Debugger () :
m_input_file (),
m_output_file (),
m_error_file (),
- m_target_list (),
+ m_target_list (*this),
m_platform_list (),
m_listener ("lldb.Debugger"),
m_source_manager(*this),
@@ -374,6 +374,7 @@ Debugger::Clear()
target_sp->Destroy();
}
}
+ BroadcasterManager::Clear ();
DisconnectInput();
}
diff --git a/lldb/source/Core/Listener.cpp b/lldb/source/Core/Listener.cpp
index 7b0888aac92..060d5e6b47b 100644
--- a/lldb/source/Core/Listener.cpp
+++ b/lldb/source/Core/Listener.cpp
@@ -40,6 +40,13 @@ Listener::Listener(const char *name) :
Listener::~Listener()
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ Mutex::Locker locker (m_broadcasters_mutex);
+
+ size_t num_managers = m_broadcaster_managers.size();
+
+ for (int i = 0; i < num_managers; i++)
+ m_broadcaster_managers[i]->RemoveListener(*this);
+
if (log)
log->Printf ("%p Listener::~Listener('%s')", this, m_name.c_str());
Clear();
@@ -164,6 +171,16 @@ Listener::BroadcasterWillDestruct (Broadcaster *broadcaster)
}
void
+Listener::BroadcasterManagerWillDestruct (BroadcasterManager *manager)
+{
+ // Just need to remove this broadcast manager from the list of managers:
+ broadcaster_manager_collection::iterator iter, end_iter = m_broadcaster_managers.end();
+ iter = find(m_broadcaster_managers.begin(), end_iter, manager);
+ if (iter != end_iter)
+ m_broadcaster_managers.erase (iter);
+}
+
+void
Listener::AddEvent (EventSP &event_sp)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
@@ -483,3 +500,27 @@ Listener::HandleBroadcastEvent (EventSP &event_sp)
}
return num_handled;
}
+
+uint32_t
+Listener::StartListeningForEventSpec (BroadcasterManager &manager,
+ const BroadcastEventSpec &event_spec)
+{
+ Mutex::Locker locker(m_broadcasters_mutex);
+
+ uint32_t bits_acquired = manager.RegisterListenerForEvents(*this, event_spec);
+ if (bits_acquired)
+ m_broadcaster_managers.push_back(&manager);
+
+ return bits_acquired;
+}
+
+bool
+Listener::StopListeningForEventSpec (BroadcasterManager &manager,
+ const BroadcastEventSpec &event_spec)
+{
+ Mutex::Locker locker(m_broadcasters_mutex);
+ return manager.UnregisterListenerForEvents (*this, event_spec);
+
+}
+
+
OpenPOWER on IntegriCloud