diff options
Diffstat (limited to 'lldb/source/Core')
-rw-r--r-- | lldb/source/Core/Broadcaster.cpp | 184 | ||||
-rw-r--r-- | lldb/source/Core/Communication.cpp | 11 | ||||
-rw-r--r-- | lldb/source/Core/Debugger.cpp | 3 | ||||
-rw-r--r-- | lldb/source/Core/Listener.cpp | 41 |
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); + +} + + |