diff options
41 files changed, 763 insertions, 28 deletions
diff --git a/lldb/include/lldb/API/SBCommandInterpreter.h b/lldb/include/lldb/API/SBCommandInterpreter.h index 3ad4abe4e7f..258cfe97411 100644 --- a/lldb/include/lldb/API/SBCommandInterpreter.h +++ b/lldb/include/lldb/API/SBCommandInterpreter.h @@ -50,6 +50,9 @@ public: lldb::SBBroadcaster GetBroadcaster (); + + static const char * + GetBroadcasterClass (); bool HasCommands (); diff --git a/lldb/include/lldb/API/SBCommunication.h b/lldb/include/lldb/API/SBCommunication.h index f6d4c86ccfc..ecaaa3523c9 100644 --- a/lldb/include/lldb/API/SBCommunication.h +++ b/lldb/include/lldb/API/SBCommunication.h @@ -39,6 +39,8 @@ public: lldb::SBBroadcaster GetBroadcaster (); + + static const char *GetBroadcasterClass(); lldb::ConnectionStatus AdoptFileDesriptor (int fd, bool owns_fd); diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 679ef12ed95..34ef7fb1fc9 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -277,6 +277,7 @@ private: friend class SBProcess; friend class SBSourceManager; friend class SBTarget; + friend class SBListener; lldb::SBTarget FindTargetWithLLDBProcess (const lldb::ProcessSP &processSP); diff --git a/lldb/include/lldb/API/SBEvent.h b/lldb/include/lldb/API/SBEvent.h index 6a3faaa1307..a24e5562a93 100644 --- a/lldb/include/lldb/API/SBEvent.h +++ b/lldb/include/lldb/API/SBEvent.h @@ -47,6 +47,9 @@ public: lldb::SBBroadcaster GetBroadcaster () const; + const char * + GetBroadcasterClass () const; + bool BroadcasterMatchesPtr (const lldb::SBBroadcaster *broadcaster); diff --git a/lldb/include/lldb/API/SBListener.h b/lldb/include/lldb/API/SBListener.h index e43506e6ab6..c5a04734174 100644 --- a/lldb/include/lldb/API/SBListener.h +++ b/lldb/include/lldb/API/SBListener.h @@ -38,6 +38,16 @@ public: IsValid () const; uint32_t + StartListeningForEventClass (SBDebugger &debugger, + const char *broadcaster_class, + uint32_t event_mask); + + bool + StopListeningForEventClass (SBDebugger &debugger, + const char *broadcaster_class, + uint32_t event_mask); + + uint32_t StartListeningForEvents (const lldb::SBBroadcaster& broadcaster, uint32_t event_mask); diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h index 84e9192945b..5bff8774714 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -42,6 +42,9 @@ public: ~SBProcess(); + static const char * + GetBroadcasterClassName (); + void Clear (); @@ -178,6 +181,9 @@ public: lldb::SBBroadcaster GetBroadcaster () const; + static const char * + GetBroadcasterClass (); + bool GetDescription (lldb::SBStream &description); diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 8029c2b8c5b..d7f08956209 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -52,6 +52,9 @@ public: bool IsValid() const; + + static const char * + GetBroadcasterClassName (); lldb::SBProcess GetProcess (); diff --git a/lldb/include/lldb/Core/Broadcaster.h b/lldb/include/lldb/Core/Broadcaster.h index 0dff7e8b868..226f49d450e 100644 --- a/lldb/include/lldb/Core/Broadcaster.h +++ b/lldb/include/lldb/Core/Broadcaster.h @@ -20,11 +20,192 @@ // Project includes #include "lldb/lldb-private.h" //#include "lldb/Core/Flags.h" +#include "lldb/Core/ConstString.h" #include "lldb/Core/Listener.h" namespace lldb_private { //---------------------------------------------------------------------- +// lldb::BroadcastEventSpec +// +// This class is used to specify a kind of event to register for. The Debugger +// maintains a list of BroadcastEventSpec's and when it is made +//---------------------------------------------------------------------- +class BroadcastEventSpec +{ +public: + BroadcastEventSpec (const ConstString &broadcaster_class, uint32_t event_bits) : + m_broadcaster_class (broadcaster_class), + m_event_bits (event_bits) + { + } + + BroadcastEventSpec (const BroadcastEventSpec &rhs); + + ~BroadcastEventSpec() {} + + const ConstString &GetBroadcasterClass() const + { + return m_broadcaster_class; + } + + uint32_t GetEventBits () const + { + return m_event_bits; + } + + // Tell whether this BroadcastEventSpec is contained in in_spec. + // That is: + // (a) the two spec's share the same broadcaster class + // (b) the event bits of this spec are wholly contained in those of in_spec. + bool IsContainedIn (BroadcastEventSpec in_spec) const + { + if (m_broadcaster_class != in_spec.GetBroadcasterClass()) + return false; + uint32_t in_bits = in_spec.GetEventBits(); + if (in_bits == m_event_bits) + return true; + else + { + if ((m_event_bits & in_bits) != 0 + && (m_event_bits & ~in_bits) == 0) + return true; + } + return false; + } + + bool operator< (const BroadcastEventSpec &rhs) const; + const BroadcastEventSpec &operator= (const BroadcastEventSpec &rhs); + +private: + ConstString m_broadcaster_class; + uint32_t m_event_bits; +}; + +class BroadcasterManager +{ +public: + BroadcasterManager (); + + ~BroadcasterManager () {}; + + uint32_t + RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec); + + bool + UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec); + + Listener * + GetListenerForEventSpec (BroadcastEventSpec event_spec) const; + + void + SignUpListenersForBroadcaster (Broadcaster &broadcaster); + + void + RemoveListener (Listener &Listener); + +protected: + void Clear(); + +private: + typedef std::pair<BroadcastEventSpec, Listener *> event_listener_key; + typedef std::map<BroadcastEventSpec, Listener *> collection; + typedef std::set<Listener *> listener_collection; + collection m_event_map; + listener_collection m_listeners; + + Mutex m_manager_mutex; + + // A couple of comparator classes for find_if: + + class BroadcasterClassMatches + { + public: + BroadcasterClassMatches (const ConstString &broadcaster_class) : + m_broadcaster_class (broadcaster_class) + { + } + + ~BroadcasterClassMatches () {} + + bool operator() (const event_listener_key input) const + { + return (input.first.GetBroadcasterClass() == m_broadcaster_class); + } + + private: + ConstString m_broadcaster_class; + }; + + class BroadcastEventSpecMatches + { + public: + BroadcastEventSpecMatches (BroadcastEventSpec broadcaster_spec) : + m_broadcaster_spec (broadcaster_spec) + { + } + + ~BroadcastEventSpecMatches () {} + + bool operator() (const event_listener_key input) const + { + return (input.first.IsContainedIn (m_broadcaster_spec)); + } + + private: + BroadcastEventSpec m_broadcaster_spec; + }; + + class ListenerMatchesAndSharedBits + { + public: + ListenerMatchesAndSharedBits (BroadcastEventSpec broadcaster_spec, + const Listener &listener) : + m_broadcaster_spec (broadcaster_spec), + m_listener (&listener) + { + } + + ~ListenerMatchesAndSharedBits () {} + + bool operator() (const event_listener_key input) const + { + return (input.first.GetBroadcasterClass() == m_broadcaster_spec.GetBroadcasterClass() + && (input.first.GetEventBits() & m_broadcaster_spec.GetEventBits()) != 0 + && input.second == m_listener); + } + + private: + BroadcastEventSpec m_broadcaster_spec; + const Listener *m_listener; + }; + + class ListenerMatches + { + public: + ListenerMatches (const Listener &in_listener) : + m_listener (&in_listener) + { + } + + ~ListenerMatches() {} + + bool operator () (const event_listener_key input) const + { + if (input.second == m_listener) + return true; + else + return false; + } + + private: + const Listener *m_listener; + + }; + +}; + +//---------------------------------------------------------------------- /// @class Broadcaster Broadcaster.h "lldb/Core/Broadcaster.h" /// @brief An event broadcasting class. /// @@ -66,7 +247,7 @@ public: /// A NULL terminated C string that contains the name of the /// broadcaster object. //------------------------------------------------------------------ - Broadcaster (const char *name); + Broadcaster (BroadcasterManager *manager, const char *name); //------------------------------------------------------------------ /// Destructor. @@ -76,6 +257,9 @@ public: virtual ~Broadcaster(); + void + CheckInWithManager (); + //------------------------------------------------------------------ /// Broadcast an event which has no associated data. /// @@ -245,6 +429,10 @@ public: //------------------------------------------------------------------ void RestoreBroadcaster (); + + virtual ConstString &GetBroadcasterClass() const; + + BroadcasterManager *GetManager(); protected: @@ -266,6 +454,7 @@ protected: std::vector<Listener *> m_hijacking_listeners; // A simple mechanism to intercept events from a broadcaster std::vector<uint32_t> m_hijacking_masks; // At some point we may want to have a stack or Listener // collections, but for now this is just for private hijacking. + BroadcasterManager *m_manager; private: //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Core/Communication.h b/lldb/include/lldb/Core/Communication.h index 42a7900549c..98d4dfd011b 100644 --- a/lldb/include/lldb/Core/Communication.h +++ b/lldb/include/lldb/Core/Communication.h @@ -332,6 +332,13 @@ public: m_close_on_eof = b; } + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + private: //------------------------------------------------------------------ // For Communication only diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index a7dece86aea..8997d98bf3c 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -18,6 +18,7 @@ #include <stack> #include "lldb/lldb-public.h" +#include "lldb/Core/Broadcaster.h" #include "lldb/Core/Communication.h" #include "lldb/Core/FormatManager.h" #include "lldb/Core/InputReaderStack.h" @@ -253,7 +254,8 @@ private: class Debugger : public std::tr1::enable_shared_from_this<Debugger>, public UserID, - public DebuggerInstanceSettings + public DebuggerInstanceSettings, + public BroadcasterManager { friend class SourceManager; // For GetSourceFileCache. diff --git a/lldb/include/lldb/Core/Listener.h b/lldb/include/lldb/Core/Listener.h index 2173768209b..6070b1e260f 100644 --- a/lldb/include/lldb/Core/Listener.h +++ b/lldb/include/lldb/Core/Listener.h @@ -16,6 +16,7 @@ #include <map> #include <set> #include <string> +#include <vector> // Other libraries and framework includes @@ -32,6 +33,7 @@ public: typedef bool (*HandleBroadcastCallback) (lldb::EventSP &event_sp, void *baton); friend class Broadcaster; + friend class BroadcasterManager; //------------------------------------------------------------------ // Constructors and Destructors @@ -53,9 +55,17 @@ public: } uint32_t - StartListeningForEvents (Broadcaster* broadcaster, + StartListeningForEventSpec (BroadcasterManager &manager, + const BroadcastEventSpec &event_spec); + + bool + StopListeningForEventSpec (BroadcasterManager &manager, + const BroadcastEventSpec &event_spec); + + uint32_t + StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask); - + uint32_t StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask, @@ -128,6 +138,7 @@ protected: typedef std::multimap<Broadcaster*, BroadcasterInfo> broadcaster_collection; typedef std::list<lldb::EventSP> event_collection; + typedef std::vector<BroadcasterManager *> broadcaster_manager_collection; bool FindNextEventInternal (Broadcaster *broadcaster, // NULL for any broadcaster @@ -158,9 +169,14 @@ protected: event_collection m_events; Mutex m_events_mutex; // Protects m_broadcasters and m_events Predicate<bool> m_cond_wait; + broadcaster_manager_collection m_broadcaster_managers; void BroadcasterWillDestruct (Broadcaster *); + + void + BroadcasterManagerWillDestruct (BroadcasterManager *manager); + private: // broadcaster_collection::iterator diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 9e4e859bc97..7a569f12683 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -55,6 +55,15 @@ public: eCommandTypesAllThem = 0xFFFF // all commands }; + // These two functions fill out the Broadcaster interface: + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + void SourceInitFile (bool in_cwd, CommandReturnObject &result); @@ -437,7 +446,7 @@ public: { return "*** Some of your variables have more members than the debugger will show by default. To show all of them, you can either use the --show-all-children option to %s or raise the limit by changing the target.max-children-count setting.\n"; } - + protected: friend class Debugger; @@ -468,6 +477,7 @@ private: char m_repeat_char; bool m_batch_command_mode; ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated children and whether the user has been told + }; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index f4a4f8e3536..d3fa8457f0b 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1296,7 +1296,16 @@ public: eBroadcastInternalStateControlPause = (1<<1), eBroadcastInternalStateControlResume = (1<<2) }; - + + // These two functions fill out the Broadcaster interface: + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + //------------------------------------------------------------------ /// A notification structure that can be used by clients to listen /// for changes in a process's lifetime. diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 26e3df68e0c..712eb0e1b69 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -278,6 +278,52 @@ public: eBroadcastBitModulesUnloaded = (1 << 2) }; + // These two functions fill out the Broadcaster interface: + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + + // This event data class is for use by the TargetList to broadcast new target notifications. + class TargetEventData : public EventData + { + public: + + static const ConstString & + GetFlavorString (); + + virtual const ConstString & + GetFlavor () const; + + TargetEventData (const lldb::TargetSP &new_target_sp); + + lldb::TargetSP & + GetTarget() + { + return m_target_sp; + } + + virtual + ~TargetEventData(); + + virtual void + Dump (Stream *s) const; + + static const lldb::TargetSP + GetTargetFromEvent (const lldb::EventSP &event_sp); + + static const TargetEventData * + GetEventDataFromEvent (const Event *event_sp); + + private: + lldb::TargetSP m_target_sp; + + DISALLOW_COPY_AND_ASSIGN (TargetEventData); + }; + static void SettingsInitialize (); diff --git a/lldb/include/lldb/Target/TargetList.h b/lldb/include/lldb/Target/TargetList.h index 5940e9a5370..d617f9a77bd 100644 --- a/lldb/include/lldb/Target/TargetList.h +++ b/lldb/include/lldb/Target/TargetList.h @@ -34,7 +34,7 @@ private: /// /// @see static TargetList& lldb_private::Debugger::GetTargetList(). //------------------------------------------------------------------ - TargetList(); + TargetList(Debugger &debugger); public: @@ -47,7 +47,16 @@ public: }; - ~TargetList(); + // These two functions fill out the Broadcaster interface: + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + + virtual ~TargetList(); //------------------------------------------------------------------ /// Create a new Target. diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 7dd4842d8f3..3c2d2a1e26a 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -41,7 +41,9 @@ class BreakpointOptions; class BreakpointResolver; class BreakpointSite; class BreakpointSiteList; +class BroadcastEventSpec; class Broadcaster; +class BroadcasterManager; class CPPLanguageRuntime; class ClangASTContext; class ClangASTImporter; diff --git a/lldb/scripts/Python/interface/SBCommandInterpreter.i b/lldb/scripts/Python/interface/SBCommandInterpreter.i index 1f15a98e49a..62aaf8c48aa 100644 --- a/lldb/scripts/Python/interface/SBCommandInterpreter.i +++ b/lldb/scripts/Python/interface/SBCommandInterpreter.i @@ -87,6 +87,9 @@ public: lldb::SBBroadcaster GetBroadcaster (); + static const char * + GetBroadcasterClass (); + bool HasCommands (); diff --git a/lldb/scripts/Python/interface/SBCommunication.i b/lldb/scripts/Python/interface/SBCommunication.i index ca2bfa78944..99814d9f303 100644 --- a/lldb/scripts/Python/interface/SBCommunication.i +++ b/lldb/scripts/Python/interface/SBCommunication.i @@ -34,6 +34,8 @@ public: lldb::SBBroadcaster GetBroadcaster (); + static const char *GetBroadcasterClass(); + lldb::ConnectionStatus AdoptFileDesriptor (int fd, bool owns_fd); diff --git a/lldb/scripts/Python/interface/SBEvent.i b/lldb/scripts/Python/interface/SBEvent.i index 66963ea903c..b360e34b75f 100644 --- a/lldb/scripts/Python/interface/SBEvent.i +++ b/lldb/scripts/Python/interface/SBEvent.i @@ -134,6 +134,9 @@ public: lldb::SBBroadcaster GetBroadcaster () const; + const char * + GetBroadcasterClass () const; + bool BroadcasterMatchesRef (const lldb::SBBroadcaster &broadcaster); diff --git a/lldb/scripts/Python/interface/SBListener.i b/lldb/scripts/Python/interface/SBListener.i index ded91b9e3ae..9560b91bdb1 100644 --- a/lldb/scripts/Python/interface/SBListener.i +++ b/lldb/scripts/Python/interface/SBListener.i @@ -35,6 +35,16 @@ public: IsValid () const; uint32_t + StartListeningForEventClass (SBDebugger &debugger, + const char *broadcaster_class, + uint32_t event_mask); + + uint32_t + StopListeningForEventClass (SBDebugger &debugger, + const char *broadcaster_class, + uint32_t event_mask); + + uint32_t StartListeningForEvents (const lldb::SBBroadcaster& broadcaster, uint32_t event_mask); diff --git a/lldb/scripts/Python/interface/SBProcess.i b/lldb/scripts/Python/interface/SBProcess.i index 20d782ad5c4..37100557f9c 100644 --- a/lldb/scripts/Python/interface/SBProcess.i +++ b/lldb/scripts/Python/interface/SBProcess.i @@ -52,6 +52,9 @@ public: ~SBProcess(); + static const char * + GetBroadcasterClassName (); + void Clear (); diff --git a/lldb/scripts/Python/interface/SBTarget.i b/lldb/scripts/Python/interface/SBTarget.i index 58a546b54c7..a8e3395093c 100644 --- a/lldb/scripts/Python/interface/SBTarget.i +++ b/lldb/scripts/Python/interface/SBTarget.i @@ -72,6 +72,9 @@ public: //------------------------------------------------------------------ ~SBTarget(); + static const char * + GetBroadcasterClassName (); + bool IsValid() const; diff --git a/lldb/source/API/SBBroadcaster.cpp b/lldb/source/API/SBBroadcaster.cpp index a33f784e30a..9ede891868b 100644 --- a/lldb/source/API/SBBroadcaster.cpp +++ b/lldb/source/API/SBBroadcaster.cpp @@ -25,7 +25,7 @@ SBBroadcaster::SBBroadcaster () : } SBBroadcaster::SBBroadcaster (const char *name) : - m_opaque_sp (new Broadcaster (name)), + m_opaque_sp (new Broadcaster (NULL, name)), m_opaque_ptr (NULL) { m_opaque_ptr = m_opaque_sp.get(); diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index e6054789090..cbf2f914089 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -292,6 +292,12 @@ SBCommandInterpreter::GetBroadcaster () return broadcaster; } +const char * +SBCommandInterpreter::GetBroadcasterClass () +{ + return Communication::GetStaticBroadcasterClass().AsCString(); +} + const char * SBCommandInterpreter::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type) { diff --git a/lldb/source/API/SBCommunication.cpp b/lldb/source/API/SBCommunication.cpp index 6b5ddb37cd6..bf3a49e719e 100644 --- a/lldb/source/API/SBCommunication.cpp +++ b/lldb/source/API/SBCommunication.cpp @@ -255,6 +255,11 @@ SBCommunication::GetBroadcaster () return broadcaster; } +const char * +SBCommunication::GetBroadcasterClass () +{ + return Communication::GetStaticBroadcasterClass().AsCString(); +} // //void diff --git a/lldb/source/API/SBEvent.cpp b/lldb/source/API/SBEvent.cpp index f9d0e0cc3a8..5ba71b0aa30 100644 --- a/lldb/source/API/SBEvent.cpp +++ b/lldb/source/API/SBEvent.cpp @@ -109,6 +109,16 @@ SBEvent::GetBroadcaster () const return broadcaster; } +const char * +SBEvent::GetBroadcasterClass () const +{ + const Event *lldb_event = get(); + if (lldb_event) + return lldb_event->GetBroadcaster()->GetBroadcasterClass().AsCString(); + else + return "unknown class"; +} + bool SBEvent::BroadcasterMatchesPtr (const SBBroadcaster *broadcaster) { diff --git a/lldb/source/API/SBListener.cpp b/lldb/source/API/SBListener.cpp index f9816347d11..b1942be36fe 100644 --- a/lldb/source/API/SBListener.cpp +++ b/lldb/source/API/SBListener.cpp @@ -9,9 +9,11 @@ #include "lldb/API/SBListener.h" #include "lldb/API/SBBroadcaster.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBStream.h" #include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Listener.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" @@ -90,6 +92,40 @@ SBListener::Clear () m_opaque_ptr->Clear (); } + uint32_t + SBListener::StartListeningForEventClass (SBDebugger &debugger, + const char *broadcaster_class, + uint32_t event_mask) + { + if (m_opaque_ptr) + { + Debugger *lldb_debugger = debugger.get(); + if (!lldb_debugger) + return 0; + BroadcastEventSpec event_spec (ConstString (broadcaster_class), event_mask); + return m_opaque_ptr->StartListeningForEventSpec (*lldb_debugger, event_spec); + } + else + return 0; + } + + bool + SBListener::StopListeningForEventClass (SBDebugger &debugger, + const char *broadcaster_class, + uint32_t event_mask) + { + if (m_opaque_ptr) + { + Debugger *lldb_debugger = debugger.get(); + if (!lldb_debugger) + return false; + BroadcastEventSpec event_spec (ConstString (broadcaster_class), event_mask); + return m_opaque_ptr->StopListeningForEventSpec (*lldb_debugger, event_spec); + } + else + return false; + } + uint32_t SBListener::StartListeningForEvents (const SBBroadcaster& broadcaster, uint32_t event_mask) { diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index 5fc71966078..9e32f91c107 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -74,6 +74,12 @@ SBProcess::~SBProcess() { } +const char * +SBProcess::GetBroadcasterClassName () +{ + return Process::GetStaticBroadcasterClass().AsCString(); +} + lldb::ProcessSP SBProcess::GetSP() const { @@ -743,7 +749,7 @@ SBProcess::GetProcessFromEvent (const SBEvent &event) bool SBProcess::EventIsProcessEvent (const SBEvent &event) { - return Process::ProcessEventData::GetEventDataFromEvent(event.get()) != NULL; + return strcmp (event.GetBroadcasterClass(), SBProcess::GetBroadcasterClass()) == 0; } SBBroadcaster @@ -762,6 +768,12 @@ SBProcess::GetBroadcaster () const return broadcaster; } +const char * +SBProcess::GetBroadcasterClass () +{ + return Process::GetStaticBroadcasterClass().AsCString(); +} + size_t SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error) { diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 687c44e01f2..7fdfb347429 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -87,6 +87,12 @@ SBTarget::~SBTarget() { } +const char * +SBTarget::GetBroadcasterClassName () +{ + return Target::GetStaticBroadcasterClass().AsCString(); +} + bool SBTarget::IsValid () const { @@ -1235,7 +1241,6 @@ SBTarget::GetBroadcaster () const return broadcaster; } - bool SBTarget::GetDescription (SBStream &description, lldb::DescriptionLevel description_level) { diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index d9070a31ce5..ca839864046 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -30,7 +30,7 @@ using namespace lldb_private; //------------------------------------------------------------------------- // CommandObjectProcessLaunch //------------------------------------------------------------------------- -#pragma mark CommandObjectProjectLaunch +#pragma mark CommandObjectProcessLaunch class CommandObjectProcessLaunch : public CommandObject { public: 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); + +} + + diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 9d6ac257ee8..8b4dc81561b 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -59,13 +59,20 @@ using namespace lldb; using namespace lldb_private; +ConstString & +CommandInterpreter::GetStaticBroadcasterClass () +{ + static ConstString class_name ("lldb.commandInterpreter"); + return class_name; +} + CommandInterpreter::CommandInterpreter ( Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution ) : - Broadcaster ("lldb.command-interpreter"), + Broadcaster (&debugger, "lldb.command-interpreter"), m_debugger (debugger), m_synchronous_execution (synchronous_execution), m_skip_lldbinit_files (false), @@ -86,6 +93,8 @@ CommandInterpreter::CommandInterpreter SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); SetEventName (eBroadcastBitResetPrompt, "reset-prompt"); SetEventName (eBroadcastBitQuitCommandReceived, "quit"); + + CheckInWithManager (); } void diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 119ffcc717d..ab872f8e7d7 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -89,7 +89,7 @@ ProcessKDP::CanDebug(Target &target, bool plugin_specified_by_name) ProcessKDP::ProcessKDP(Target& target, Listener &listener) : Process (target, listener), m_comm("lldb.process.kdp-remote.communication"), - m_async_broadcaster ("lldb.process.kdp-remote.async-broadcaster"), + m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"), m_async_thread (LLDB_INVALID_HOST_THREAD) { // m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index afafaafaa06..8424d2a32be 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -146,7 +146,7 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : m_last_stop_packet (), m_last_stop_packet_mutex (Mutex::eMutexTypeNormal), m_register_info (), - m_async_broadcaster ("lldb.process.gdb-remote.async-broadcaster"), + m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"), m_async_thread (LLDB_INVALID_HOST_THREAD), m_continue_c_tids (), m_continue_C_tids (), diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 8083c9543bf..6f5589bb189 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -743,19 +743,25 @@ Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener return process_sp; } +ConstString & +Process::GetStaticBroadcasterClass () +{ + static ConstString class_name ("lldb.process"); + return class_name; +} //---------------------------------------------------------------------- // Process constructor //---------------------------------------------------------------------- Process::Process(Target &target, Listener &listener) : UserID (LLDB_INVALID_PROCESS_ID), - Broadcaster ("lldb.process"), + Broadcaster (&(target.GetDebugger()), "lldb.process"), ProcessInstanceSettings (GetSettingsController()), m_target (target), m_public_state (eStateUnloaded), m_private_state (eStateUnloaded), - m_private_state_broadcaster ("lldb.process.internal_state_broadcaster"), - m_private_state_control_broadcaster ("lldb.process.internal_state_control_broadcaster"), + m_private_state_broadcaster (NULL, "lldb.process.internal_state_broadcaster"), + m_private_state_control_broadcaster (NULL, "lldb.process.internal_state_control_broadcaster"), m_private_state_listener ("lldb.process.internal_state_listener"), m_private_state_control_wait(), m_private_state_thread (LLDB_INVALID_HOST_THREAD), @@ -783,6 +789,8 @@ Process::Process(Target &target, Listener &listener) : m_can_jit(eCanJITDontKnow) { UpdateInstanceName(); + + CheckInWithManager (); LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 6a6cb0eae7e..ef1eed3482b 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -41,11 +41,18 @@ using namespace lldb; using namespace lldb_private; +ConstString & +Target::GetStaticBroadcasterClass () +{ + static ConstString class_name ("lldb.target"); + return class_name; +} + //---------------------------------------------------------------------- // Target constructor //---------------------------------------------------------------------- Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp) : - Broadcaster ("lldb.target"), + Broadcaster (&debugger, "lldb.target"), ExecutionContextScope (), TargetInstanceSettings (GetSettingsController()), m_debugger (debugger), @@ -72,6 +79,8 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed"); SetEventName (eBroadcastBitModulesLoaded, "modules-loaded"); SetEventName (eBroadcastBitModulesUnloaded, "modules-unloaded"); + + CheckInWithManager(); LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) @@ -2773,3 +2782,58 @@ Target::SettingsController::instance_settings_table[] = { TSC_DISABLE_STDIO , eSetVarTypeBoolean, "false" , NULL, false, false, "Disable stdin/stdout for process (e.g. for a GUI application)" }, { NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL } }; + +const ConstString & +Target::TargetEventData::GetFlavorString () +{ + static ConstString g_flavor ("Target::TargetEventData"); + return g_flavor; +} + +const ConstString & +Target::TargetEventData::GetFlavor () const +{ + return TargetEventData::GetFlavorString (); +} + +Target::TargetEventData::TargetEventData (const lldb::TargetSP &new_target_sp) : + EventData(), + m_target_sp (new_target_sp) +{ +} + +Target::TargetEventData::~TargetEventData() +{ + +} + +void +Target::TargetEventData::Dump (Stream *s) const +{ + +} + +const TargetSP +Target::TargetEventData::GetTargetFromEvent (const lldb::EventSP &event_sp) +{ + TargetSP target_sp; + + const TargetEventData *data = GetEventDataFromEvent (event_sp.get()); + if (data) + target_sp = data->m_target_sp; + + return target_sp; +} + +const Target::TargetEventData * +Target::TargetEventData::GetEventDataFromEvent (const Event *event_ptr) +{ + if (event_ptr) + { + const EventData *event_data = event_ptr->GetData(); + if (event_data && event_data->GetFlavor() == TargetEventData::GetFlavorString()) + return static_cast <const TargetEventData *> (event_ptr->GetData()); + } + return NULL; +} + diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp index e412beb1da5..38240e12318 100644 --- a/lldb/source/Target/TargetList.cpp +++ b/lldb/source/Target/TargetList.cpp @@ -25,16 +25,23 @@ using namespace lldb; using namespace lldb_private; +ConstString & +TargetList::GetStaticBroadcasterClass () +{ + static ConstString class_name ("lldb.targetList"); + return class_name; +} //---------------------------------------------------------------------- // TargetList constructor //---------------------------------------------------------------------- -TargetList::TargetList() : - Broadcaster("TargetList"), +TargetList::TargetList(Debugger &debugger) : + Broadcaster(&debugger, "TargetList"), m_target_list(), m_target_list_mutex (Mutex::eMutexTypeRecursive), m_selected_target_idx (0) { + CheckInWithManager(); } //---------------------------------------------------------------------- @@ -176,9 +183,6 @@ TargetList::CreateTarget Mutex::Locker locker(m_target_list_mutex); m_selected_target_idx = m_target_list.size(); m_target_list.push_back(target_sp); - - // Now sign the Debugger up to listen to target events for this target: - debugger.GetListener().StartListeningForEvents(target_sp.get(), Target::eBroadcastBitBreakpointChanged); } return error; diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 5808f5f9c53..2a6f0628018 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -1233,6 +1233,9 @@ Driver::MainLoop () m_debugger.PushInputReader (m_editline_reader); SBListener listener(m_debugger.GetListener()); + listener.StartListeningForEventClass(m_debugger, + SBTarget::GetBroadcasterClassName(), + SBTarget::eBroadcastBitBreakpointChanged); if (listener.IsValid()) { |