Index: lldb/trunk/include/lldb/Breakpoint/Breakpoint.h =================================================================== --- lldb/trunk/include/lldb/Breakpoint/Breakpoint.h +++ lldb/trunk/include/lldb/Breakpoint/Breakpoint.h @@ -21,8 +21,8 @@ #include "lldb/Breakpoint/BreakpointName.h" #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Breakpoint/Stoppoint.h" -#include "lldb/Core/Event.h" #include "lldb/Core/SearchFilter.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/StringList.h" #include "lldb/Utility/StructuredData.h" Index: lldb/trunk/include/lldb/Breakpoint/BreakpointName.h =================================================================== --- lldb/trunk/include/lldb/Breakpoint/BreakpointName.h +++ lldb/trunk/include/lldb/Breakpoint/BreakpointName.h @@ -20,8 +20,8 @@ #include "lldb/Breakpoint/BreakpointLocationList.h" #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Breakpoint/Stoppoint.h" -#include "lldb/Core/Event.h" #include "lldb/Core/SearchFilter.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/Flags.h" #include "lldb/Utility/StringList.h" #include "lldb/Utility/StructuredData.h" Index: lldb/trunk/include/lldb/Core/Broadcaster.h =================================================================== --- lldb/trunk/include/lldb/Core/Broadcaster.h +++ lldb/trunk/include/lldb/Core/Broadcaster.h @@ -1,598 +0,0 @@ -//===-- Broadcaster.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Broadcaster_h_ -#define liblldb_Broadcaster_h_ - -#include "lldb/Utility/ConstString.h" -#include "lldb/lldb-defines.h" -#include "lldb/lldb-forward.h" - -#include "llvm/ADT/SmallVector.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace lldb_private { -class Broadcaster; -} -namespace lldb_private { -class EventData; -} -namespace lldb_private { -class Listener; -} -namespace lldb_private { -class Stream; -} - -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() = default; - - 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; - BroadcastEventSpec &operator=(const BroadcastEventSpec &rhs); - -private: - ConstString m_broadcaster_class; - uint32_t m_event_bits; -}; - -class BroadcasterManager - : public std::enable_shared_from_this { -public: - friend class Listener; - -protected: - BroadcasterManager(); - -public: - // Listeners hold onto weak pointers to their broadcaster managers. So they - // must be made into shared pointers, which you do with - // MakeBroadcasterManager. - - static lldb::BroadcasterManagerSP MakeBroadcasterManager(); - - ~BroadcasterManager() = default; - - uint32_t RegisterListenerForEvents(const lldb::ListenerSP &listener_sp, - BroadcastEventSpec event_spec); - - bool UnregisterListenerForEvents(const lldb::ListenerSP &listener_sp, - BroadcastEventSpec event_spec); - - lldb::ListenerSP GetListenerForEventSpec(BroadcastEventSpec event_spec) const; - - void SignUpListenersForBroadcaster(Broadcaster &broadcaster); - - void RemoveListener(const lldb::ListenerSP &listener_sp); - - void RemoveListener(Listener *listener); - - void Clear(); - -private: - typedef std::pair event_listener_key; - typedef std::map collection; - typedef std::set listener_collection; - collection m_event_map; - listener_collection m_listeners; - - mutable std::recursive_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() = default; - - 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() = default; - - bool operator()(const event_listener_key input) const { - return (input.first.IsContainedIn(m_broadcaster_spec)); - } - - private: - BroadcastEventSpec m_broadcaster_spec; - }; - - class ListenerMatchesAndSharedBits { - public: - explicit ListenerMatchesAndSharedBits(BroadcastEventSpec broadcaster_spec, - const lldb::ListenerSP listener_sp) - : m_broadcaster_spec(broadcaster_spec), m_listener_sp(listener_sp) {} - - ~ListenerMatchesAndSharedBits() = default; - - 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_sp); - } - - private: - BroadcastEventSpec m_broadcaster_spec; - const lldb::ListenerSP m_listener_sp; - }; - - class ListenerMatches { - public: - explicit ListenerMatches(const lldb::ListenerSP in_listener_sp) - : m_listener_sp(in_listener_sp) {} - - ~ListenerMatches() = default; - - bool operator()(const event_listener_key input) const { - if (input.second == m_listener_sp) - return true; - else - return false; - } - - private: - const lldb::ListenerSP m_listener_sp; - }; - - class ListenerMatchesPointer { - public: - ListenerMatchesPointer(const Listener *in_listener) - : m_listener(in_listener) {} - - ~ListenerMatchesPointer() = default; - - bool operator()(const event_listener_key input) const { - if (input.second.get() == m_listener) - return true; - else - return false; - } - - bool operator()(const lldb::ListenerSP input) const { - if (input.get() == m_listener) - return true; - else - return false; - } - - private: - const Listener *m_listener; - }; -}; - -//---------------------------------------------------------------------- -/// @class Broadcaster Broadcaster.h "lldb/Core/Broadcaster.h" An event -/// broadcasting class. -/// -/// The Broadcaster class is designed to be subclassed by objects that wish to -/// vend events in a multi-threaded environment. Broadcaster objects can each -/// vend 32 events. Each event is represented by a bit in a 32 bit value and -/// these bits can be set: -/// @see Broadcaster::SetEventBits(uint32_t) -/// or cleared: -/// @see Broadcaster::ResetEventBits(uint32_t) -/// When an event gets set the Broadcaster object will notify the Listener -/// object that is listening for the event (if there is one). -/// -/// Subclasses should provide broadcast bit definitions for any events they -/// vend, typically using an enumeration: -/// \code -/// class Foo : public Broadcaster -/// { -/// public: -/// //---------------------------------------------------------- -/// // Broadcaster event bits definitions. -/// //---------------------------------------------------------- -/// enum -/// { -/// eBroadcastBitOne = (1 << 0), -/// eBroadcastBitTwo = (1 << 1), -/// eBroadcastBitThree = (1 << 2), -/// ... -/// }; -/// \endcode -//---------------------------------------------------------------------- -class Broadcaster { - friend class Listener; - friend class Event; - -public: - //------------------------------------------------------------------ - /// Construct with a broadcaster with a name. - /// - /// @param[in] name - /// A NULL terminated C string that contains the name of the - /// broadcaster object. - //------------------------------------------------------------------ - Broadcaster(lldb::BroadcasterManagerSP manager_sp, const char *name); - - //------------------------------------------------------------------ - /// Destructor. - /// - /// The destructor is virtual since this class gets subclassed. - //------------------------------------------------------------------ - virtual ~Broadcaster(); - - void CheckInWithManager(); - - //------------------------------------------------------------------ - /// Broadcast an event which has no associated data. - /// - /// @param[in] event_type - /// The element from the enum defining this broadcaster's events - /// that is being broadcast. - /// - /// @param[in] event_data - /// User event data that will be owned by the lldb::Event that - /// is created internally. - /// - /// @param[in] unique - /// If true, then only add an event of this type if there isn't - /// one already in the queue. - /// - //------------------------------------------------------------------ - void BroadcastEvent(lldb::EventSP &event_sp) { - m_broadcaster_sp->BroadcastEvent(event_sp); - } - - void BroadcastEventIfUnique(lldb::EventSP &event_sp) { - m_broadcaster_sp->BroadcastEventIfUnique(event_sp); - } - - void BroadcastEvent(uint32_t event_type, - const lldb::EventDataSP &event_data_sp) { - m_broadcaster_sp->BroadcastEvent(event_type, event_data_sp); - } - - void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr) { - m_broadcaster_sp->BroadcastEvent(event_type, event_data); - } - - void BroadcastEventIfUnique(uint32_t event_type, - EventData *event_data = nullptr) { - m_broadcaster_sp->BroadcastEventIfUnique(event_type, event_data); - } - - void Clear() { m_broadcaster_sp->Clear(); } - - virtual void AddInitialEventsToListener(const lldb::ListenerSP &listener_sp, - uint32_t requested_events); - - //------------------------------------------------------------------ - /// Listen for any events specified by \a event_mask. - /// - /// Only one listener can listen to each event bit in a given Broadcaster. - /// Once a listener has acquired an event bit, no other broadcaster will - /// have access to it until it is relinquished by the first listener that - /// gets it. The actual event bits that get acquired by \a listener may be - /// different from what is requested in \a event_mask, and to track this the - /// actual event bits that are acquired get returned. - /// - /// @param[in] listener - /// The Listener object that wants to monitor the events that - /// get broadcast by this object. - /// - /// @param[in] event_mask - /// A bit mask that indicates which events the listener is - /// asking to monitor. - /// - /// @return - /// The actual event bits that were acquired by \a listener. - //------------------------------------------------------------------ - uint32_t AddListener(const lldb::ListenerSP &listener_sp, - uint32_t event_mask) { - return m_broadcaster_sp->AddListener(listener_sp, event_mask); - } - - //------------------------------------------------------------------ - /// Get the NULL terminated C string name of this Broadcaster object. - /// - /// @return - /// The NULL terminated C string name of this Broadcaster. - //------------------------------------------------------------------ - const ConstString &GetBroadcasterName() { return m_broadcaster_name; } - - //------------------------------------------------------------------ - /// Get the event name(s) for one or more event bits. - /// - /// @param[in] event_mask - /// A bit mask that indicates which events to get names for. - /// - /// @return - /// The NULL terminated C string name of this Broadcaster. - //------------------------------------------------------------------ - bool GetEventNames(Stream &s, const uint32_t event_mask, - bool prefix_with_broadcaster_name) const { - return m_broadcaster_sp->GetEventNames(s, event_mask, - prefix_with_broadcaster_name); - } - - //------------------------------------------------------------------ - /// Set the name for an event bit. - /// - /// @param[in] event_mask - /// A bit mask that indicates which events the listener is - /// asking to monitor. - /// - /// @return - /// The NULL terminated C string name of this Broadcaster. - //------------------------------------------------------------------ - void SetEventName(uint32_t event_mask, const char *name) { - m_broadcaster_sp->SetEventName(event_mask, name); - } - - const char *GetEventName(uint32_t event_mask) const { - return m_broadcaster_sp->GetEventName(event_mask); - } - - bool EventTypeHasListeners(uint32_t event_type) { - return m_broadcaster_sp->EventTypeHasListeners(event_type); - } - - //------------------------------------------------------------------ - /// Removes a Listener from this broadcasters list and frees the event bits - /// specified by \a event_mask that were previously acquired by \a listener - /// (assuming \a listener was listening to this object) for other listener - /// objects to use. - /// - /// @param[in] listener - /// A Listener object that previously called AddListener. - /// - /// @param[in] event_mask - /// The event bits \a listener wishes to relinquish. - /// - /// @return - /// \b True if the listener was listening to this broadcaster - /// and was removed, \b false otherwise. - /// - /// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t) - //------------------------------------------------------------------ - bool RemoveListener(const lldb::ListenerSP &listener_sp, - uint32_t event_mask = UINT32_MAX) { - return m_broadcaster_sp->RemoveListener(listener_sp, event_mask); - } - - //------------------------------------------------------------------ - /// Provides a simple mechanism to temporarily redirect events from - /// broadcaster. When you call this function passing in a listener and - /// event type mask, all events from the broadcaster matching the mask will - /// now go to the hijacking listener. Only one hijack can occur at a time. - /// If we need more than this we will have to implement a Listener stack. - /// - /// @param[in] listener - /// A Listener object. You do not need to call StartListeningForEvents - /// for this broadcaster (that would fail anyway since the event bits - /// would most likely be taken by the listener(s) you are usurping. - /// - /// @param[in] event_mask - /// The event bits \a listener wishes to hijack. - /// - /// @return - /// \b True if the event mask could be hijacked, \b false otherwise. - /// - /// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t) - //------------------------------------------------------------------ - bool HijackBroadcaster(const lldb::ListenerSP &listener_sp, - uint32_t event_mask = UINT32_MAX) { - return m_broadcaster_sp->HijackBroadcaster(listener_sp, event_mask); - } - - bool IsHijackedForEvent(uint32_t event_mask) { - return m_broadcaster_sp->IsHijackedForEvent(event_mask); - } - - //------------------------------------------------------------------ - /// Restore the state of the Broadcaster from a previous hijack attempt. - /// - //------------------------------------------------------------------ - void RestoreBroadcaster() { m_broadcaster_sp->RestoreBroadcaster(); } - - // This needs to be filled in if you are going to register the broadcaster - // with the broadcaster manager and do broadcaster class matching. - // FIXME: Probably should make a ManagedBroadcaster subclass with all the bits - // needed to work - // with the BroadcasterManager, so that it is clearer how to add one. - virtual ConstString &GetBroadcasterClass() const; - - lldb::BroadcasterManagerSP GetManager(); - -protected: - // BroadcasterImpl contains the actual Broadcaster implementation. The - // Broadcaster makes a BroadcasterImpl which lives as long as it does. The - // Listeners & the Events hold a weak pointer to the BroadcasterImpl, so that - // they can survive if a Broadcaster they were listening to is destroyed w/o - // their being able to unregister from it (which can happen if the - // Broadcasters & Listeners are being destroyed on separate threads - // simultaneously. The Broadcaster itself can't be shared out as a weak - // pointer, because some things that are broadcasters (e.g. the Target and - // the Process) are shared in their own right. - // - // For the most part, the Broadcaster functions dispatch to the - // BroadcasterImpl, and are documented in the public Broadcaster API above. - - class BroadcasterImpl { - friend class Listener; - friend class Broadcaster; - - public: - BroadcasterImpl(Broadcaster &broadcaster); - - ~BroadcasterImpl() = default; - - void BroadcastEvent(lldb::EventSP &event_sp); - - void BroadcastEventIfUnique(lldb::EventSP &event_sp); - - void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr); - - void BroadcastEvent(uint32_t event_type, - const lldb::EventDataSP &event_data_sp); - - void BroadcastEventIfUnique(uint32_t event_type, - EventData *event_data = nullptr); - - void Clear(); - - uint32_t AddListener(const lldb::ListenerSP &listener_sp, - uint32_t event_mask); - - const char *GetBroadcasterName() const { - return m_broadcaster.GetBroadcasterName().AsCString(); - } - - Broadcaster *GetBroadcaster(); - - bool GetEventNames(Stream &s, const uint32_t event_mask, - bool prefix_with_broadcaster_name) const; - - void SetEventName(uint32_t event_mask, const char *name) { - m_event_names[event_mask] = name; - } - - const char *GetEventName(uint32_t event_mask) const { - const auto pos = m_event_names.find(event_mask); - if (pos != m_event_names.end()) - return pos->second.c_str(); - return nullptr; - } - - bool EventTypeHasListeners(uint32_t event_type); - - bool RemoveListener(lldb_private::Listener *listener, - uint32_t event_mask = UINT32_MAX); - - bool RemoveListener(const lldb::ListenerSP &listener_sp, - uint32_t event_mask = UINT32_MAX); - - bool HijackBroadcaster(const lldb::ListenerSP &listener_sp, - uint32_t event_mask = UINT32_MAX); - - bool IsHijackedForEvent(uint32_t event_mask); - - void RestoreBroadcaster(); - - protected: - void PrivateBroadcastEvent(lldb::EventSP &event_sp, bool unique); - - const char *GetHijackingListenerName(); - - //------------------------------------------------------------------ - // - //------------------------------------------------------------------ - typedef llvm::SmallVector, 4> - collection; - typedef std::map event_names_map; - - llvm::SmallVector, 4> - GetListeners(); - - Broadcaster &m_broadcaster; ///< The broadcaster that this implements - event_names_map m_event_names; ///< Optionally define event names for - ///readability and logging for each event bit - collection m_listeners; ///< A list of Listener / event_mask pairs that are - ///listening to this broadcaster. - std::recursive_mutex - m_listeners_mutex; ///< A mutex that protects \a m_listeners. - std::vector m_hijacking_listeners; // A simple mechanism - // to intercept events - // from a broadcaster - std::vector 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. - - private: - //------------------------------------------------------------------ - // For Broadcaster only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN(BroadcasterImpl); - }; - - typedef std::shared_ptr BroadcasterImplSP; - typedef std::weak_ptr BroadcasterImplWP; - - BroadcasterImplSP GetBroadcasterImpl() { return m_broadcaster_sp; } - - const char *GetHijackingListenerName() { - return m_broadcaster_sp->GetHijackingListenerName(); - } - //------------------------------------------------------------------ - // Classes that inherit from Broadcaster can see and modify these - //------------------------------------------------------------------ - -private: - //------------------------------------------------------------------ - // For Broadcaster only - //------------------------------------------------------------------ - BroadcasterImplSP m_broadcaster_sp; - lldb::BroadcasterManagerSP m_manager_sp; - const ConstString - m_broadcaster_name; ///< The name of this broadcaster object. - - DISALLOW_COPY_AND_ASSIGN(Broadcaster); -}; - -} // namespace lldb_private - -#endif // liblldb_Broadcaster_h_ Index: lldb/trunk/include/lldb/Core/Communication.h =================================================================== --- lldb/trunk/include/lldb/Core/Communication.h +++ lldb/trunk/include/lldb/Core/Communication.h @@ -10,8 +10,8 @@ #ifndef liblldb_Communication_h_ #define liblldb_Communication_h_ -#include "lldb/Core/Broadcaster.h" #include "lldb/Host/HostThread.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Timeout.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" Index: lldb/trunk/include/lldb/Core/Debugger.h =================================================================== --- lldb/trunk/include/lldb/Core/Debugger.h +++ lldb/trunk/include/lldb/Core/Debugger.h @@ -15,7 +15,6 @@ #include #include -#include "lldb/Core/Broadcaster.h" #include "lldb/Core/FormatEntity.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/SourceManager.h" @@ -25,6 +24,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" #include "lldb/Target/TargetList.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Status.h" Index: lldb/trunk/include/lldb/Core/Event.h =================================================================== --- lldb/trunk/include/lldb/Core/Event.h +++ lldb/trunk/include/lldb/Core/Event.h @@ -1,274 +0,0 @@ -//===-- Event.h -------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Event_h_ -#define liblldb_Event_h_ - -#include "lldb/Core/Broadcaster.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Predicate.h" -#include "lldb/Utility/StructuredData.h" -#include "lldb/lldb-defines.h" -#include "lldb/lldb-forward.h" - -#include "llvm/ADT/StringRef.h" - -#include -#include -#include - -#include -#include - -namespace lldb_private { -class Event; -} -namespace lldb_private { -class Stream; -} - -namespace lldb_private { - -//---------------------------------------------------------------------- -// lldb::EventData -//---------------------------------------------------------------------- -class EventData { - friend class Event; - -public: - EventData(); - - virtual ~EventData(); - - virtual const ConstString &GetFlavor() const = 0; - - virtual void Dump(Stream *s) const; - -private: - virtual void DoOnRemoval(Event *event_ptr) {} - - DISALLOW_COPY_AND_ASSIGN(EventData); -}; - -//---------------------------------------------------------------------- -// lldb::EventDataBytes -//---------------------------------------------------------------------- -class EventDataBytes : public EventData { -public: - //------------------------------------------------------------------ - // Constructors - //------------------------------------------------------------------ - EventDataBytes(); - - EventDataBytes(const char *cstr); - - EventDataBytes(llvm::StringRef str); - - EventDataBytes(const void *src, size_t src_len); - - ~EventDataBytes() override; - - //------------------------------------------------------------------ - // Member functions - //------------------------------------------------------------------ - const ConstString &GetFlavor() const override; - - void Dump(Stream *s) const override; - - const void *GetBytes() const; - - size_t GetByteSize() const; - - void SetBytes(const void *src, size_t src_len); - - void SwapBytes(std::string &new_bytes); - - void SetBytesFromCString(const char *cstr); - - //------------------------------------------------------------------ - // Static functions - //------------------------------------------------------------------ - static const EventDataBytes *GetEventDataFromEvent(const Event *event_ptr); - - static const void *GetBytesFromEvent(const Event *event_ptr); - - static size_t GetByteSizeFromEvent(const Event *event_ptr); - - static const ConstString &GetFlavorString(); - -private: - std::string m_bytes; - - DISALLOW_COPY_AND_ASSIGN(EventDataBytes); -}; - -class EventDataReceipt : public EventData { -public: - EventDataReceipt() : EventData(), m_predicate(false) {} - - ~EventDataReceipt() override {} - - static const ConstString &GetFlavorString() { - static ConstString g_flavor("Process::ProcessEventData"); - return g_flavor; - } - - const ConstString &GetFlavor() const override { return GetFlavorString(); } - - bool WaitForEventReceived(const Timeout &timeout = llvm::None) { - return m_predicate.WaitForValueEqualTo(true, timeout); - } - -private: - Predicate m_predicate; - - void DoOnRemoval(Event *event_ptr) override { - m_predicate.SetValue(true, eBroadcastAlways); - } -}; - -//---------------------------------------------------------------------- -/// This class handles one or more StructuredData::Dictionary entries -/// that are raised for structured data events. -//---------------------------------------------------------------------- - -class EventDataStructuredData : public EventData { -public: - //------------------------------------------------------------------ - // Constructors - //------------------------------------------------------------------ - EventDataStructuredData(); - - EventDataStructuredData(const lldb::ProcessSP &process_sp, - const StructuredData::ObjectSP &object_sp, - const lldb::StructuredDataPluginSP &plugin_sp); - - ~EventDataStructuredData() override; - - //------------------------------------------------------------------ - // Member functions - //------------------------------------------------------------------ - const ConstString &GetFlavor() const override; - - void Dump(Stream *s) const override; - - const lldb::ProcessSP &GetProcess() const; - - const StructuredData::ObjectSP &GetObject() const; - - const lldb::StructuredDataPluginSP &GetStructuredDataPlugin() const; - - void SetProcess(const lldb::ProcessSP &process_sp); - - void SetObject(const StructuredData::ObjectSP &object_sp); - - void SetStructuredDataPlugin(const lldb::StructuredDataPluginSP &plugin_sp); - - //------------------------------------------------------------------ - // Static functions - //------------------------------------------------------------------ - static const EventDataStructuredData * - GetEventDataFromEvent(const Event *event_ptr); - - static lldb::ProcessSP GetProcessFromEvent(const Event *event_ptr); - - static StructuredData::ObjectSP GetObjectFromEvent(const Event *event_ptr); - - static lldb::StructuredDataPluginSP - GetPluginFromEvent(const Event *event_ptr); - - static const ConstString &GetFlavorString(); - -private: - lldb::ProcessSP m_process_sp; - StructuredData::ObjectSP m_object_sp; - lldb::StructuredDataPluginSP m_plugin_sp; - - DISALLOW_COPY_AND_ASSIGN(EventDataStructuredData); -}; - -//---------------------------------------------------------------------- -// lldb::Event -//---------------------------------------------------------------------- -class Event { - friend class Listener; - friend class EventData; - friend class Broadcaster::BroadcasterImpl; - -public: - Event(Broadcaster *broadcaster, uint32_t event_type, - EventData *data = nullptr); - - Event(Broadcaster *broadcaster, uint32_t event_type, - const lldb::EventDataSP &event_data_sp); - - Event(uint32_t event_type, EventData *data = nullptr); - - Event(uint32_t event_type, const lldb::EventDataSP &event_data_sp); - - ~Event(); - - void Dump(Stream *s) const; - - EventData *GetData() { return m_data_sp.get(); } - - const EventData *GetData() const { return m_data_sp.get(); } - - void SetData(EventData *new_data) { m_data_sp.reset(new_data); } - - uint32_t GetType() const { return m_type; } - - void SetType(uint32_t new_type) { m_type = new_type; } - - Broadcaster *GetBroadcaster() const { - Broadcaster::BroadcasterImplSP broadcaster_impl_sp = - m_broadcaster_wp.lock(); - if (broadcaster_impl_sp) - return broadcaster_impl_sp->GetBroadcaster(); - else - return nullptr; - } - - bool BroadcasterIs(Broadcaster *broadcaster) { - Broadcaster::BroadcasterImplSP broadcaster_impl_sp = - m_broadcaster_wp.lock(); - if (broadcaster_impl_sp) - return broadcaster_impl_sp->GetBroadcaster() == broadcaster; - else - return false; - } - - void Clear() { m_data_sp.reset(); } - -private: - // This is only called by Listener when it pops an event off the queue for - // the listener. It calls the Event Data's DoOnRemoval() method, which is - // virtual and can be overridden by the specific data classes. - - void DoOnRemoval(); - - // Called by Broadcaster::BroadcastEvent prior to letting all the listeners - // know about it update the contained broadcaster so that events can be - // popped off one queue and re-broadcast to others. - void SetBroadcaster(Broadcaster *broadcaster) { - m_broadcaster_wp = broadcaster->GetBroadcasterImpl(); - } - - Broadcaster::BroadcasterImplWP - m_broadcaster_wp; // The broadcaster that sent this event - uint32_t m_type; // The bit describing this event - lldb::EventDataSP m_data_sp; // User specific data for this event - - DISALLOW_COPY_AND_ASSIGN(Event); - Event(); // Disallow default constructor -}; - -} // namespace lldb_private - -#endif // liblldb_Event_h_ Index: lldb/trunk/include/lldb/Core/Listener.h =================================================================== --- lldb/trunk/include/lldb/Core/Listener.h +++ lldb/trunk/include/lldb/Core/Listener.h @@ -1,161 +0,0 @@ -//===-- Listener.h ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Select_h_ -#define liblldb_Select_h_ - -#include "lldb/Core/Broadcaster.h" -#include "lldb/Utility/Timeout.h" -#include "lldb/lldb-defines.h" -#include "lldb/lldb-forward.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace lldb_private { -class ConstString; -} -namespace lldb_private { -class Event; -} - -namespace lldb_private { - -class Listener : public std::enable_shared_from_this { -public: - typedef bool (*HandleBroadcastCallback)(lldb::EventSP &event_sp, void *baton); - - friend class Broadcaster; - friend class BroadcasterManager; - - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - // - // Listeners have to be constructed into shared pointers - at least if you - // want them to listen to Broadcasters, -protected: - Listener(const char *name); - -public: - static lldb::ListenerSP MakeListener(const char *name); - - ~Listener(); - - void AddEvent(lldb::EventSP &event); - - void Clear(); - - const char *GetName() { return m_name.c_str(); } - - uint32_t StartListeningForEventSpec(lldb::BroadcasterManagerSP manager_sp, - const BroadcastEventSpec &event_spec); - - bool StopListeningForEventSpec(lldb::BroadcasterManagerSP manager_sp, - const BroadcastEventSpec &event_spec); - - uint32_t StartListeningForEvents(Broadcaster *broadcaster, - uint32_t event_mask); - - uint32_t StartListeningForEvents(Broadcaster *broadcaster, - uint32_t event_mask, - HandleBroadcastCallback callback, - void *callback_user_data); - - bool StopListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask); - - Event *PeekAtNextEvent(); - - Event *PeekAtNextEventForBroadcaster(Broadcaster *broadcaster); - - Event *PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, - uint32_t event_type_mask); - - // Returns true if an event was received, false if we timed out. - bool GetEvent(lldb::EventSP &event_sp, const Timeout &timeout); - - bool GetEventForBroadcaster(Broadcaster *broadcaster, lldb::EventSP &event_sp, - const Timeout &timeout); - - bool GetEventForBroadcasterWithType(Broadcaster *broadcaster, - uint32_t event_type_mask, - lldb::EventSP &event_sp, - const Timeout &timeout); - - size_t HandleBroadcastEvent(lldb::EventSP &event_sp); - -private: - //------------------------------------------------------------------ - // Classes that inherit from Listener can see and modify these - //------------------------------------------------------------------ - struct BroadcasterInfo { - BroadcasterInfo(uint32_t mask, HandleBroadcastCallback cb = nullptr, - void *ud = nullptr) - : event_mask(mask), callback(cb), callback_user_data(ud) {} - - uint32_t event_mask; - HandleBroadcastCallback callback; - void *callback_user_data; - }; - - typedef std::multimap> - broadcaster_collection; - typedef std::list event_collection; - typedef std::vector - broadcaster_manager_collection; - - bool - FindNextEventInternal(std::unique_lock &lock, - Broadcaster *broadcaster, // nullptr for any broadcaster - const ConstString *sources, // nullptr for any event - uint32_t num_sources, uint32_t event_type_mask, - lldb::EventSP &event_sp, bool remove); - - bool GetEventInternal(const Timeout &timeout, - Broadcaster *broadcaster, // nullptr for any broadcaster - const ConstString *sources, // nullptr for any event - uint32_t num_sources, uint32_t event_type_mask, - lldb::EventSP &event_sp); - - std::string m_name; - broadcaster_collection m_broadcasters; - std::recursive_mutex m_broadcasters_mutex; // Protects m_broadcasters - event_collection m_events; - std::mutex m_events_mutex; // Protects m_broadcasters and m_events - std::condition_variable m_events_condition; - broadcaster_manager_collection m_broadcaster_managers; - - void BroadcasterWillDestruct(Broadcaster *); - - void BroadcasterManagerWillDestruct(lldb::BroadcasterManagerSP manager_sp); - - // broadcaster_collection::iterator - // FindBroadcasterWithMask (Broadcaster *broadcaster, - // uint32_t event_mask, - // bool exact); - - //------------------------------------------------------------------ - // For Listener only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN(Listener); -}; - -} // namespace lldb_private - -#endif // liblldb_Select_h_ Index: lldb/trunk/include/lldb/Core/StructuredDataImpl.h =================================================================== --- lldb/trunk/include/lldb/Core/StructuredDataImpl.h +++ lldb/trunk/include/lldb/Core/StructuredDataImpl.h @@ -10,8 +10,8 @@ #ifndef liblldb_StructuredDataImpl_h_ #define liblldb_StructuredDataImpl_h_ -#include "lldb/Core/Event.h" #include "lldb/Target/StructuredDataPlugin.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StructuredData.h" Index: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h =================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h +++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h @@ -10,21 +10,21 @@ #ifndef liblldb_CommandInterpreter_h_ #define liblldb_CommandInterpreter_h_ -#include -#include "lldb/Core/Broadcaster.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/Event.h" #include "lldb/Core/IOHandler.h" #include "lldb/Interpreter/CommandAlias.h" #include "lldb/Interpreter/CommandHistory.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Utility/Args.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/CompletionRequest.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StringList.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" +#include namespace lldb_private { Index: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h =================================================================== --- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h +++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h @@ -13,9 +13,9 @@ #include "lldb/lldb-private.h" #include "lldb/Breakpoint/BreakpointOptions.h" -#include "lldb/Core/Broadcaster.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/SearchFilter.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StructuredData.h" Index: lldb/trunk/include/lldb/Target/Process.h =================================================================== --- lldb/trunk/include/lldb/Target/Process.h +++ lldb/trunk/include/lldb/Target/Process.h @@ -23,10 +23,7 @@ #include #include "lldb/Breakpoint/BreakpointSiteList.h" -#include "lldb/Core/Broadcaster.h" #include "lldb/Core/Communication.h" -#include "lldb/Core/Event.h" -#include "lldb/Core/Listener.h" #include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/ThreadSafeValue.h" @@ -43,6 +40,9 @@ #include "lldb/Target/QueueList.h" #include "lldb/Target/ThreadList.h" #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Event.h" +#include "lldb/Utility/Listener.h" #include "lldb/Utility/NameMatches.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StructuredData.h" Index: lldb/trunk/include/lldb/Target/Target.h =================================================================== --- lldb/trunk/include/lldb/Target/Target.h +++ lldb/trunk/include/lldb/Target/Target.h @@ -20,7 +20,6 @@ #include "lldb/Breakpoint/BreakpointName.h" #include "lldb/Breakpoint/WatchpointList.h" #include "lldb/Core/Architecture.h" -#include "lldb/Core/Broadcaster.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/UserSettingsController.h" @@ -31,6 +30,7 @@ #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/SectionLoadHistory.h" #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Timeout.h" #include "lldb/lldb-public.h" Index: lldb/trunk/include/lldb/Target/TargetList.h =================================================================== --- lldb/trunk/include/lldb/Target/TargetList.h +++ lldb/trunk/include/lldb/Target/TargetList.h @@ -13,8 +13,8 @@ #include #include -#include "lldb/Core/Broadcaster.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/Broadcaster.h" namespace lldb_private { Index: lldb/trunk/include/lldb/Target/Thread.h =================================================================== --- lldb/trunk/include/lldb/Target/Thread.h +++ lldb/trunk/include/lldb/Target/Thread.h @@ -15,12 +15,12 @@ #include #include -#include "lldb/Core/Broadcaster.h" -#include "lldb/Core/Event.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/RegisterCheckpoint.h" #include "lldb/Target/StackFrameList.h" +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/StructuredData.h" #include "lldb/Utility/UserID.h" #include "lldb/lldb-private.h" Index: lldb/trunk/include/lldb/Utility/Broadcaster.h =================================================================== --- lldb/trunk/include/lldb/Utility/Broadcaster.h +++ lldb/trunk/include/lldb/Utility/Broadcaster.h @@ -0,0 +1,598 @@ +//===-- Broadcaster.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UTILITY_BROADCASTER_H +#define LLDB_UTILITY_BROADCASTER_H + +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" + +#include "llvm/ADT/SmallVector.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace lldb_private { +class Broadcaster; +} +namespace lldb_private { +class EventData; +} +namespace lldb_private { +class Listener; +} +namespace lldb_private { +class Stream; +} + +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() = default; + + 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; + BroadcastEventSpec &operator=(const BroadcastEventSpec &rhs); + +private: + ConstString m_broadcaster_class; + uint32_t m_event_bits; +}; + +class BroadcasterManager + : public std::enable_shared_from_this { +public: + friend class Listener; + +protected: + BroadcasterManager(); + +public: + // Listeners hold onto weak pointers to their broadcaster managers. So they + // must be made into shared pointers, which you do with + // MakeBroadcasterManager. + + static lldb::BroadcasterManagerSP MakeBroadcasterManager(); + + ~BroadcasterManager() = default; + + uint32_t RegisterListenerForEvents(const lldb::ListenerSP &listener_sp, + BroadcastEventSpec event_spec); + + bool UnregisterListenerForEvents(const lldb::ListenerSP &listener_sp, + BroadcastEventSpec event_spec); + + lldb::ListenerSP GetListenerForEventSpec(BroadcastEventSpec event_spec) const; + + void SignUpListenersForBroadcaster(Broadcaster &broadcaster); + + void RemoveListener(const lldb::ListenerSP &listener_sp); + + void RemoveListener(Listener *listener); + + void Clear(); + +private: + typedef std::pair event_listener_key; + typedef std::map collection; + typedef std::set listener_collection; + collection m_event_map; + listener_collection m_listeners; + + mutable std::recursive_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() = default; + + 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() = default; + + bool operator()(const event_listener_key input) const { + return (input.first.IsContainedIn(m_broadcaster_spec)); + } + + private: + BroadcastEventSpec m_broadcaster_spec; + }; + + class ListenerMatchesAndSharedBits { + public: + explicit ListenerMatchesAndSharedBits(BroadcastEventSpec broadcaster_spec, + const lldb::ListenerSP listener_sp) + : m_broadcaster_spec(broadcaster_spec), m_listener_sp(listener_sp) {} + + ~ListenerMatchesAndSharedBits() = default; + + 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_sp); + } + + private: + BroadcastEventSpec m_broadcaster_spec; + const lldb::ListenerSP m_listener_sp; + }; + + class ListenerMatches { + public: + explicit ListenerMatches(const lldb::ListenerSP in_listener_sp) + : m_listener_sp(in_listener_sp) {} + + ~ListenerMatches() = default; + + bool operator()(const event_listener_key input) const { + if (input.second == m_listener_sp) + return true; + else + return false; + } + + private: + const lldb::ListenerSP m_listener_sp; + }; + + class ListenerMatchesPointer { + public: + ListenerMatchesPointer(const Listener *in_listener) + : m_listener(in_listener) {} + + ~ListenerMatchesPointer() = default; + + bool operator()(const event_listener_key input) const { + if (input.second.get() == m_listener) + return true; + else + return false; + } + + bool operator()(const lldb::ListenerSP input) const { + if (input.get() == m_listener) + return true; + else + return false; + } + + private: + const Listener *m_listener; + }; +}; + +//---------------------------------------------------------------------- +/// @class Broadcaster Broadcaster.h "lldb/Utility/Broadcaster.h" An event +/// broadcasting class. +/// +/// The Broadcaster class is designed to be subclassed by objects that wish to +/// vend events in a multi-threaded environment. Broadcaster objects can each +/// vend 32 events. Each event is represented by a bit in a 32 bit value and +/// these bits can be set: +/// @see Broadcaster::SetEventBits(uint32_t) +/// or cleared: +/// @see Broadcaster::ResetEventBits(uint32_t) +/// When an event gets set the Broadcaster object will notify the Listener +/// object that is listening for the event (if there is one). +/// +/// Subclasses should provide broadcast bit definitions for any events they +/// vend, typically using an enumeration: +/// \code +/// class Foo : public Broadcaster +/// { +/// public: +/// //---------------------------------------------------------- +/// // Broadcaster event bits definitions. +/// //---------------------------------------------------------- +/// enum +/// { +/// eBroadcastBitOne = (1 << 0), +/// eBroadcastBitTwo = (1 << 1), +/// eBroadcastBitThree = (1 << 2), +/// ... +/// }; +/// \endcode +//---------------------------------------------------------------------- +class Broadcaster { + friend class Listener; + friend class Event; + +public: + //------------------------------------------------------------------ + /// Construct with a broadcaster with a name. + /// + /// @param[in] name + /// A NULL terminated C string that contains the name of the + /// broadcaster object. + //------------------------------------------------------------------ + Broadcaster(lldb::BroadcasterManagerSP manager_sp, const char *name); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class gets subclassed. + //------------------------------------------------------------------ + virtual ~Broadcaster(); + + void CheckInWithManager(); + + //------------------------------------------------------------------ + /// Broadcast an event which has no associated data. + /// + /// @param[in] event_type + /// The element from the enum defining this broadcaster's events + /// that is being broadcast. + /// + /// @param[in] event_data + /// User event data that will be owned by the lldb::Event that + /// is created internally. + /// + /// @param[in] unique + /// If true, then only add an event of this type if there isn't + /// one already in the queue. + /// + //------------------------------------------------------------------ + void BroadcastEvent(lldb::EventSP &event_sp) { + m_broadcaster_sp->BroadcastEvent(event_sp); + } + + void BroadcastEventIfUnique(lldb::EventSP &event_sp) { + m_broadcaster_sp->BroadcastEventIfUnique(event_sp); + } + + void BroadcastEvent(uint32_t event_type, + const lldb::EventDataSP &event_data_sp) { + m_broadcaster_sp->BroadcastEvent(event_type, event_data_sp); + } + + void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr) { + m_broadcaster_sp->BroadcastEvent(event_type, event_data); + } + + void BroadcastEventIfUnique(uint32_t event_type, + EventData *event_data = nullptr) { + m_broadcaster_sp->BroadcastEventIfUnique(event_type, event_data); + } + + void Clear() { m_broadcaster_sp->Clear(); } + + virtual void AddInitialEventsToListener(const lldb::ListenerSP &listener_sp, + uint32_t requested_events); + + //------------------------------------------------------------------ + /// Listen for any events specified by \a event_mask. + /// + /// Only one listener can listen to each event bit in a given Broadcaster. + /// Once a listener has acquired an event bit, no other broadcaster will + /// have access to it until it is relinquished by the first listener that + /// gets it. The actual event bits that get acquired by \a listener may be + /// different from what is requested in \a event_mask, and to track this the + /// actual event bits that are acquired get returned. + /// + /// @param[in] listener + /// The Listener object that wants to monitor the events that + /// get broadcast by this object. + /// + /// @param[in] event_mask + /// A bit mask that indicates which events the listener is + /// asking to monitor. + /// + /// @return + /// The actual event bits that were acquired by \a listener. + //------------------------------------------------------------------ + uint32_t AddListener(const lldb::ListenerSP &listener_sp, + uint32_t event_mask) { + return m_broadcaster_sp->AddListener(listener_sp, event_mask); + } + + //------------------------------------------------------------------ + /// Get the NULL terminated C string name of this Broadcaster object. + /// + /// @return + /// The NULL terminated C string name of this Broadcaster. + //------------------------------------------------------------------ + const ConstString &GetBroadcasterName() { return m_broadcaster_name; } + + //------------------------------------------------------------------ + /// Get the event name(s) for one or more event bits. + /// + /// @param[in] event_mask + /// A bit mask that indicates which events to get names for. + /// + /// @return + /// The NULL terminated C string name of this Broadcaster. + //------------------------------------------------------------------ + bool GetEventNames(Stream &s, const uint32_t event_mask, + bool prefix_with_broadcaster_name) const { + return m_broadcaster_sp->GetEventNames(s, event_mask, + prefix_with_broadcaster_name); + } + + //------------------------------------------------------------------ + /// Set the name for an event bit. + /// + /// @param[in] event_mask + /// A bit mask that indicates which events the listener is + /// asking to monitor. + /// + /// @return + /// The NULL terminated C string name of this Broadcaster. + //------------------------------------------------------------------ + void SetEventName(uint32_t event_mask, const char *name) { + m_broadcaster_sp->SetEventName(event_mask, name); + } + + const char *GetEventName(uint32_t event_mask) const { + return m_broadcaster_sp->GetEventName(event_mask); + } + + bool EventTypeHasListeners(uint32_t event_type) { + return m_broadcaster_sp->EventTypeHasListeners(event_type); + } + + //------------------------------------------------------------------ + /// Removes a Listener from this broadcasters list and frees the event bits + /// specified by \a event_mask that were previously acquired by \a listener + /// (assuming \a listener was listening to this object) for other listener + /// objects to use. + /// + /// @param[in] listener + /// A Listener object that previously called AddListener. + /// + /// @param[in] event_mask + /// The event bits \a listener wishes to relinquish. + /// + /// @return + /// \b True if the listener was listening to this broadcaster + /// and was removed, \b false otherwise. + /// + /// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t) + //------------------------------------------------------------------ + bool RemoveListener(const lldb::ListenerSP &listener_sp, + uint32_t event_mask = UINT32_MAX) { + return m_broadcaster_sp->RemoveListener(listener_sp, event_mask); + } + + //------------------------------------------------------------------ + /// Provides a simple mechanism to temporarily redirect events from + /// broadcaster. When you call this function passing in a listener and + /// event type mask, all events from the broadcaster matching the mask will + /// now go to the hijacking listener. Only one hijack can occur at a time. + /// If we need more than this we will have to implement a Listener stack. + /// + /// @param[in] listener + /// A Listener object. You do not need to call StartListeningForEvents + /// for this broadcaster (that would fail anyway since the event bits + /// would most likely be taken by the listener(s) you are usurping. + /// + /// @param[in] event_mask + /// The event bits \a listener wishes to hijack. + /// + /// @return + /// \b True if the event mask could be hijacked, \b false otherwise. + /// + /// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t) + //------------------------------------------------------------------ + bool HijackBroadcaster(const lldb::ListenerSP &listener_sp, + uint32_t event_mask = UINT32_MAX) { + return m_broadcaster_sp->HijackBroadcaster(listener_sp, event_mask); + } + + bool IsHijackedForEvent(uint32_t event_mask) { + return m_broadcaster_sp->IsHijackedForEvent(event_mask); + } + + //------------------------------------------------------------------ + /// Restore the state of the Broadcaster from a previous hijack attempt. + /// + //------------------------------------------------------------------ + void RestoreBroadcaster() { m_broadcaster_sp->RestoreBroadcaster(); } + + // This needs to be filled in if you are going to register the broadcaster + // with the broadcaster manager and do broadcaster class matching. + // FIXME: Probably should make a ManagedBroadcaster subclass with all the bits + // needed to work + // with the BroadcasterManager, so that it is clearer how to add one. + virtual ConstString &GetBroadcasterClass() const; + + lldb::BroadcasterManagerSP GetManager(); + +protected: + // BroadcasterImpl contains the actual Broadcaster implementation. The + // Broadcaster makes a BroadcasterImpl which lives as long as it does. The + // Listeners & the Events hold a weak pointer to the BroadcasterImpl, so that + // they can survive if a Broadcaster they were listening to is destroyed w/o + // their being able to unregister from it (which can happen if the + // Broadcasters & Listeners are being destroyed on separate threads + // simultaneously. The Broadcaster itself can't be shared out as a weak + // pointer, because some things that are broadcasters (e.g. the Target and + // the Process) are shared in their own right. + // + // For the most part, the Broadcaster functions dispatch to the + // BroadcasterImpl, and are documented in the public Broadcaster API above. + + class BroadcasterImpl { + friend class Listener; + friend class Broadcaster; + + public: + BroadcasterImpl(Broadcaster &broadcaster); + + ~BroadcasterImpl() = default; + + void BroadcastEvent(lldb::EventSP &event_sp); + + void BroadcastEventIfUnique(lldb::EventSP &event_sp); + + void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr); + + void BroadcastEvent(uint32_t event_type, + const lldb::EventDataSP &event_data_sp); + + void BroadcastEventIfUnique(uint32_t event_type, + EventData *event_data = nullptr); + + void Clear(); + + uint32_t AddListener(const lldb::ListenerSP &listener_sp, + uint32_t event_mask); + + const char *GetBroadcasterName() const { + return m_broadcaster.GetBroadcasterName().AsCString(); + } + + Broadcaster *GetBroadcaster(); + + bool GetEventNames(Stream &s, const uint32_t event_mask, + bool prefix_with_broadcaster_name) const; + + void SetEventName(uint32_t event_mask, const char *name) { + m_event_names[event_mask] = name; + } + + const char *GetEventName(uint32_t event_mask) const { + const auto pos = m_event_names.find(event_mask); + if (pos != m_event_names.end()) + return pos->second.c_str(); + return nullptr; + } + + bool EventTypeHasListeners(uint32_t event_type); + + bool RemoveListener(lldb_private::Listener *listener, + uint32_t event_mask = UINT32_MAX); + + bool RemoveListener(const lldb::ListenerSP &listener_sp, + uint32_t event_mask = UINT32_MAX); + + bool HijackBroadcaster(const lldb::ListenerSP &listener_sp, + uint32_t event_mask = UINT32_MAX); + + bool IsHijackedForEvent(uint32_t event_mask); + + void RestoreBroadcaster(); + + protected: + void PrivateBroadcastEvent(lldb::EventSP &event_sp, bool unique); + + const char *GetHijackingListenerName(); + + //------------------------------------------------------------------ + // + //------------------------------------------------------------------ + typedef llvm::SmallVector, 4> + collection; + typedef std::map event_names_map; + + llvm::SmallVector, 4> + GetListeners(); + + Broadcaster &m_broadcaster; ///< The broadcaster that this implements + event_names_map m_event_names; ///< Optionally define event names for + ///readability and logging for each event bit + collection m_listeners; ///< A list of Listener / event_mask pairs that are + ///listening to this broadcaster. + std::recursive_mutex + m_listeners_mutex; ///< A mutex that protects \a m_listeners. + std::vector m_hijacking_listeners; // A simple mechanism + // to intercept events + // from a broadcaster + std::vector 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. + + private: + //------------------------------------------------------------------ + // For Broadcaster only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(BroadcasterImpl); + }; + + typedef std::shared_ptr BroadcasterImplSP; + typedef std::weak_ptr BroadcasterImplWP; + + BroadcasterImplSP GetBroadcasterImpl() { return m_broadcaster_sp; } + + const char *GetHijackingListenerName() { + return m_broadcaster_sp->GetHijackingListenerName(); + } + //------------------------------------------------------------------ + // Classes that inherit from Broadcaster can see and modify these + //------------------------------------------------------------------ + +private: + //------------------------------------------------------------------ + // For Broadcaster only + //------------------------------------------------------------------ + BroadcasterImplSP m_broadcaster_sp; + lldb::BroadcasterManagerSP m_manager_sp; + const ConstString + m_broadcaster_name; ///< The name of this broadcaster object. + + DISALLOW_COPY_AND_ASSIGN(Broadcaster); +}; + +} // namespace lldb_private + +#endif // LLDB_UTILITY_BROADCASTER_H Index: lldb/trunk/include/lldb/Utility/Event.h =================================================================== --- lldb/trunk/include/lldb/Utility/Event.h +++ lldb/trunk/include/lldb/Utility/Event.h @@ -0,0 +1,274 @@ +//===-- Event.h -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UTILITY_EVENT_H +#define LLDB_UTILITY_EVENT_H + +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Predicate.h" +#include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" + +#include "llvm/ADT/StringRef.h" + +#include +#include +#include + +#include +#include + +namespace lldb_private { +class Event; +} +namespace lldb_private { +class Stream; +} + +namespace lldb_private { + +//---------------------------------------------------------------------- +// lldb::EventData +//---------------------------------------------------------------------- +class EventData { + friend class Event; + +public: + EventData(); + + virtual ~EventData(); + + virtual const ConstString &GetFlavor() const = 0; + + virtual void Dump(Stream *s) const; + +private: + virtual void DoOnRemoval(Event *event_ptr) {} + + DISALLOW_COPY_AND_ASSIGN(EventData); +}; + +//---------------------------------------------------------------------- +// lldb::EventDataBytes +//---------------------------------------------------------------------- +class EventDataBytes : public EventData { +public: + //------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------ + EventDataBytes(); + + EventDataBytes(const char *cstr); + + EventDataBytes(llvm::StringRef str); + + EventDataBytes(const void *src, size_t src_len); + + ~EventDataBytes() override; + + //------------------------------------------------------------------ + // Member functions + //------------------------------------------------------------------ + const ConstString &GetFlavor() const override; + + void Dump(Stream *s) const override; + + const void *GetBytes() const; + + size_t GetByteSize() const; + + void SetBytes(const void *src, size_t src_len); + + void SwapBytes(std::string &new_bytes); + + void SetBytesFromCString(const char *cstr); + + //------------------------------------------------------------------ + // Static functions + //------------------------------------------------------------------ + static const EventDataBytes *GetEventDataFromEvent(const Event *event_ptr); + + static const void *GetBytesFromEvent(const Event *event_ptr); + + static size_t GetByteSizeFromEvent(const Event *event_ptr); + + static const ConstString &GetFlavorString(); + +private: + std::string m_bytes; + + DISALLOW_COPY_AND_ASSIGN(EventDataBytes); +}; + +class EventDataReceipt : public EventData { +public: + EventDataReceipt() : EventData(), m_predicate(false) {} + + ~EventDataReceipt() override {} + + static const ConstString &GetFlavorString() { + static ConstString g_flavor("Process::ProcessEventData"); + return g_flavor; + } + + const ConstString &GetFlavor() const override { return GetFlavorString(); } + + bool WaitForEventReceived(const Timeout &timeout = llvm::None) { + return m_predicate.WaitForValueEqualTo(true, timeout); + } + +private: + Predicate m_predicate; + + void DoOnRemoval(Event *event_ptr) override { + m_predicate.SetValue(true, eBroadcastAlways); + } +}; + +//---------------------------------------------------------------------- +/// This class handles one or more StructuredData::Dictionary entries +/// that are raised for structured data events. +//---------------------------------------------------------------------- + +class EventDataStructuredData : public EventData { +public: + //------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------ + EventDataStructuredData(); + + EventDataStructuredData(const lldb::ProcessSP &process_sp, + const StructuredData::ObjectSP &object_sp, + const lldb::StructuredDataPluginSP &plugin_sp); + + ~EventDataStructuredData() override; + + //------------------------------------------------------------------ + // Member functions + //------------------------------------------------------------------ + const ConstString &GetFlavor() const override; + + void Dump(Stream *s) const override; + + const lldb::ProcessSP &GetProcess() const; + + const StructuredData::ObjectSP &GetObject() const; + + const lldb::StructuredDataPluginSP &GetStructuredDataPlugin() const; + + void SetProcess(const lldb::ProcessSP &process_sp); + + void SetObject(const StructuredData::ObjectSP &object_sp); + + void SetStructuredDataPlugin(const lldb::StructuredDataPluginSP &plugin_sp); + + //------------------------------------------------------------------ + // Static functions + //------------------------------------------------------------------ + static const EventDataStructuredData * + GetEventDataFromEvent(const Event *event_ptr); + + static lldb::ProcessSP GetProcessFromEvent(const Event *event_ptr); + + static StructuredData::ObjectSP GetObjectFromEvent(const Event *event_ptr); + + static lldb::StructuredDataPluginSP + GetPluginFromEvent(const Event *event_ptr); + + static const ConstString &GetFlavorString(); + +private: + lldb::ProcessSP m_process_sp; + StructuredData::ObjectSP m_object_sp; + lldb::StructuredDataPluginSP m_plugin_sp; + + DISALLOW_COPY_AND_ASSIGN(EventDataStructuredData); +}; + +//---------------------------------------------------------------------- +// lldb::Event +//---------------------------------------------------------------------- +class Event { + friend class Listener; + friend class EventData; + friend class Broadcaster::BroadcasterImpl; + +public: + Event(Broadcaster *broadcaster, uint32_t event_type, + EventData *data = nullptr); + + Event(Broadcaster *broadcaster, uint32_t event_type, + const lldb::EventDataSP &event_data_sp); + + Event(uint32_t event_type, EventData *data = nullptr); + + Event(uint32_t event_type, const lldb::EventDataSP &event_data_sp); + + ~Event(); + + void Dump(Stream *s) const; + + EventData *GetData() { return m_data_sp.get(); } + + const EventData *GetData() const { return m_data_sp.get(); } + + void SetData(EventData *new_data) { m_data_sp.reset(new_data); } + + uint32_t GetType() const { return m_type; } + + void SetType(uint32_t new_type) { m_type = new_type; } + + Broadcaster *GetBroadcaster() const { + Broadcaster::BroadcasterImplSP broadcaster_impl_sp = + m_broadcaster_wp.lock(); + if (broadcaster_impl_sp) + return broadcaster_impl_sp->GetBroadcaster(); + else + return nullptr; + } + + bool BroadcasterIs(Broadcaster *broadcaster) { + Broadcaster::BroadcasterImplSP broadcaster_impl_sp = + m_broadcaster_wp.lock(); + if (broadcaster_impl_sp) + return broadcaster_impl_sp->GetBroadcaster() == broadcaster; + else + return false; + } + + void Clear() { m_data_sp.reset(); } + +private: + // This is only called by Listener when it pops an event off the queue for + // the listener. It calls the Event Data's DoOnRemoval() method, which is + // virtual and can be overridden by the specific data classes. + + void DoOnRemoval(); + + // Called by Broadcaster::BroadcastEvent prior to letting all the listeners + // know about it update the contained broadcaster so that events can be + // popped off one queue and re-broadcast to others. + void SetBroadcaster(Broadcaster *broadcaster) { + m_broadcaster_wp = broadcaster->GetBroadcasterImpl(); + } + + Broadcaster::BroadcasterImplWP + m_broadcaster_wp; // The broadcaster that sent this event + uint32_t m_type; // The bit describing this event + lldb::EventDataSP m_data_sp; // User specific data for this event + + DISALLOW_COPY_AND_ASSIGN(Event); + Event(); // Disallow default constructor +}; + +} // namespace lldb_private + +#endif // LLDB_UTILITY_EVENT_H Index: lldb/trunk/include/lldb/Utility/Listener.h =================================================================== --- lldb/trunk/include/lldb/Utility/Listener.h +++ lldb/trunk/include/lldb/Utility/Listener.h @@ -0,0 +1,161 @@ +//===-- Listener.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UTILITY_LISTENER_H +#define LLDB_UTILITY_LISTENER_H + +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Timeout.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace lldb_private { +class ConstString; +} +namespace lldb_private { +class Event; +} + +namespace lldb_private { + +class Listener : public std::enable_shared_from_this { +public: + typedef bool (*HandleBroadcastCallback)(lldb::EventSP &event_sp, void *baton); + + friend class Broadcaster; + friend class BroadcasterManager; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + // + // Listeners have to be constructed into shared pointers - at least if you + // want them to listen to Broadcasters, +protected: + Listener(const char *name); + +public: + static lldb::ListenerSP MakeListener(const char *name); + + ~Listener(); + + void AddEvent(lldb::EventSP &event); + + void Clear(); + + const char *GetName() { return m_name.c_str(); } + + uint32_t StartListeningForEventSpec(lldb::BroadcasterManagerSP manager_sp, + const BroadcastEventSpec &event_spec); + + bool StopListeningForEventSpec(lldb::BroadcasterManagerSP manager_sp, + const BroadcastEventSpec &event_spec); + + uint32_t StartListeningForEvents(Broadcaster *broadcaster, + uint32_t event_mask); + + uint32_t StartListeningForEvents(Broadcaster *broadcaster, + uint32_t event_mask, + HandleBroadcastCallback callback, + void *callback_user_data); + + bool StopListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask); + + Event *PeekAtNextEvent(); + + Event *PeekAtNextEventForBroadcaster(Broadcaster *broadcaster); + + Event *PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, + uint32_t event_type_mask); + + // Returns true if an event was received, false if we timed out. + bool GetEvent(lldb::EventSP &event_sp, const Timeout &timeout); + + bool GetEventForBroadcaster(Broadcaster *broadcaster, lldb::EventSP &event_sp, + const Timeout &timeout); + + bool GetEventForBroadcasterWithType(Broadcaster *broadcaster, + uint32_t event_type_mask, + lldb::EventSP &event_sp, + const Timeout &timeout); + + size_t HandleBroadcastEvent(lldb::EventSP &event_sp); + +private: + //------------------------------------------------------------------ + // Classes that inherit from Listener can see and modify these + //------------------------------------------------------------------ + struct BroadcasterInfo { + BroadcasterInfo(uint32_t mask, HandleBroadcastCallback cb = nullptr, + void *ud = nullptr) + : event_mask(mask), callback(cb), callback_user_data(ud) {} + + uint32_t event_mask; + HandleBroadcastCallback callback; + void *callback_user_data; + }; + + typedef std::multimap> + broadcaster_collection; + typedef std::list event_collection; + typedef std::vector + broadcaster_manager_collection; + + bool + FindNextEventInternal(std::unique_lock &lock, + Broadcaster *broadcaster, // nullptr for any broadcaster + const ConstString *sources, // nullptr for any event + uint32_t num_sources, uint32_t event_type_mask, + lldb::EventSP &event_sp, bool remove); + + bool GetEventInternal(const Timeout &timeout, + Broadcaster *broadcaster, // nullptr for any broadcaster + const ConstString *sources, // nullptr for any event + uint32_t num_sources, uint32_t event_type_mask, + lldb::EventSP &event_sp); + + std::string m_name; + broadcaster_collection m_broadcasters; + std::recursive_mutex m_broadcasters_mutex; // Protects m_broadcasters + event_collection m_events; + std::mutex m_events_mutex; // Protects m_broadcasters and m_events + std::condition_variable m_events_condition; + broadcaster_manager_collection m_broadcaster_managers; + + void BroadcasterWillDestruct(Broadcaster *); + + void BroadcasterManagerWillDestruct(lldb::BroadcasterManagerSP manager_sp); + + // broadcaster_collection::iterator + // FindBroadcasterWithMask (Broadcaster *broadcaster, + // uint32_t event_mask, + // bool exact); + + //------------------------------------------------------------------ + // For Listener only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(Listener); +}; + +} // namespace lldb_private + +#endif // LLDB_UTILITY_LISTENER_H Index: lldb/trunk/source/API/SBBroadcaster.cpp =================================================================== --- lldb/trunk/source/API/SBBroadcaster.cpp +++ lldb/trunk/source/API/SBBroadcaster.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Broadcaster.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Log.h" #include "lldb/API/SBBroadcaster.h" Index: lldb/trunk/source/API/SBCommandInterpreter.cpp =================================================================== --- lldb/trunk/source/API/SBCommandInterpreter.cpp +++ lldb/trunk/source/API/SBCommandInterpreter.cpp @@ -9,11 +9,11 @@ #include "lldb/lldb-types.h" -#include "lldb/Core/Listener.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/Listener.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandInterpreter.h" Index: lldb/trunk/source/API/SBEvent.cpp =================================================================== --- lldb/trunk/source/API/SBEvent.cpp +++ lldb/trunk/source/API/SBEvent.cpp @@ -12,11 +12,11 @@ #include "lldb/API/SBStream.h" #include "lldb/Breakpoint/Breakpoint.h" -#include "lldb/Core/Event.h" #include "lldb/Core/StreamFile.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Target/Process.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/Stream.h" using namespace lldb; Index: lldb/trunk/source/API/SBListener.cpp =================================================================== --- lldb/trunk/source/API/SBListener.cpp +++ lldb/trunk/source/API/SBListener.cpp @@ -12,9 +12,9 @@ #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/Utility/Broadcaster.h" +#include "lldb/Utility/Listener.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" Index: lldb/trunk/source/API/SBStructuredData.cpp =================================================================== --- lldb/trunk/source/API/SBStructuredData.cpp +++ lldb/trunk/source/API/SBStructuredData.cpp @@ -11,9 +11,9 @@ #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" -#include "lldb/Core/Event.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Target/StructuredDataPlugin.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StructuredData.h" Index: lldb/trunk/source/Core/Broadcaster.cpp =================================================================== --- lldb/trunk/source/Core/Broadcaster.cpp +++ lldb/trunk/source/Core/Broadcaster.cpp @@ -1,479 +0,0 @@ -//===-- Broadcaster.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Core/Broadcaster.h" - -#include "lldb/Core/Event.h" -#include "lldb/Core/Listener.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Logging.h" -#include "lldb/Utility/Stream.h" -#include "lldb/Utility/StreamString.h" - -#include -#include -#include - -#include -#include - -using namespace lldb; -using namespace lldb_private; - -Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, const char *name) - : m_broadcaster_sp(std::make_shared(*this)), - m_manager_sp(manager_sp), m_broadcaster_name(name) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Broadcaster::Broadcaster(\"%s\")", - static_cast(this), GetBroadcasterName().AsCString()); -} - -Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster) - : m_broadcaster(broadcaster), m_listeners(), m_listeners_mutex(), - m_hijacking_listeners(), m_hijacking_masks() {} - -Broadcaster::~Broadcaster() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Broadcaster::~Broadcaster(\"%s\")", - static_cast(this), m_broadcaster_name.AsCString()); - - Clear(); -} - -void Broadcaster::CheckInWithManager() { - if (m_manager_sp) { - m_manager_sp->SignUpListenersForBroadcaster(*this); - } -} - -llvm::SmallVector, 4> -Broadcaster::BroadcasterImpl::GetListeners() { - llvm::SmallVector, 4> listeners; - listeners.reserve(m_listeners.size()); - - for (auto it = m_listeners.begin(); it != m_listeners.end();) { - lldb::ListenerSP curr_listener_sp(it->first.lock()); - if (curr_listener_sp && it->second) { - listeners.emplace_back(std::move(curr_listener_sp), it->second); - ++it; - } else - it = m_listeners.erase(it); - } - - return listeners; -} - -void Broadcaster::BroadcasterImpl::Clear() { - std::lock_guard guard(m_listeners_mutex); - - // Make sure the listener forgets about this broadcaster. We do this in the - // broadcaster in case the broadcaster object initiates the removal. - for (auto &pair : GetListeners()) - pair.first->BroadcasterWillDestruct(&m_broadcaster); - - m_listeners.clear(); -} - -Broadcaster *Broadcaster::BroadcasterImpl::GetBroadcaster() { - return &m_broadcaster; -} - -bool Broadcaster::BroadcasterImpl::GetEventNames( - Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const { - uint32_t num_names_added = 0; - if (event_mask && !m_event_names.empty()) { - event_names_map::const_iterator end = m_event_names.end(); - for (uint32_t bit = 1u, mask = event_mask; mask != 0 && bit != 0; - bit <<= 1, mask >>= 1) { - if (mask & 1) { - event_names_map::const_iterator pos = m_event_names.find(bit); - if (pos != end) { - if (num_names_added > 0) - s.PutCString(", "); - - if (prefix_with_broadcaster_name) { - s.PutCString(GetBroadcasterName()); - s.PutChar('.'); - } - s.PutCString(pos->second); - ++num_names_added; - } - } - } - } - return num_names_added > 0; -} - -void Broadcaster::AddInitialEventsToListener( - const lldb::ListenerSP &listener_sp, uint32_t requested_events) {} - -uint32_t -Broadcaster::BroadcasterImpl::AddListener(const lldb::ListenerSP &listener_sp, - uint32_t event_mask) { - if (!listener_sp) - return 0; - - std::lock_guard guard(m_listeners_mutex); - - // See if we already have this listener, and if so, update its mask - - bool handled = false; - - for (auto &pair : GetListeners()) { - if (pair.first == listener_sp) { - handled = true; - pair.second |= event_mask; - m_broadcaster.AddInitialEventsToListener(listener_sp, event_mask); - break; - } - } - - 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, event_mask); - } - - // Return the event bits that were granted to the listener - return event_mask; -} - -bool Broadcaster::BroadcasterImpl::EventTypeHasListeners(uint32_t event_type) { - std::lock_guard guard(m_listeners_mutex); - - if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back()) - return true; - - for (auto &pair : GetListeners()) { - if (pair.second & event_type) - return true; - } - return false; -} - -bool Broadcaster::BroadcasterImpl::RemoveListener( - lldb_private::Listener *listener, uint32_t event_mask) { - if (!listener) - return false; - - std::lock_guard guard(m_listeners_mutex); - for (auto &pair : GetListeners()) { - if (pair.first.get() == listener) { - pair.second &= ~event_mask; - return true; - } - } - 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) { - return PrivateBroadcastEvent(event_sp, false); -} - -void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique(EventSP &event_sp) { - return PrivateBroadcastEvent(event_sp, true); -} - -void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp, - bool unique) { - // Can't add a nullptr event... - if (!event_sp) - return; - - // Update the broadcaster on this event - event_sp->SetBroadcaster(&m_broadcaster); - - const uint32_t event_type = event_sp->GetType(); - - std::lock_guard guard(m_listeners_mutex); - - ListenerSP hijacking_listener_sp; - - if (!m_hijacking_listeners.empty()) { - assert(!m_hijacking_masks.empty()); - hijacking_listener_sp = m_hijacking_listeners.back(); - if ((event_type & m_hijacking_masks.back()) == 0) - hijacking_listener_sp.reset(); - } - - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log) { - StreamString event_description; - event_sp->Dump(&event_description); - log->Printf("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, " - "unique =%i) hijack = %p", - static_cast(this), GetBroadcasterName(), - event_description.GetData(), unique, - static_cast(hijacking_listener_sp.get())); - } - - if (hijacking_listener_sp) { - if (unique && - hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType( - &m_broadcaster, event_type)) - return; - hijacking_listener_sp->AddEvent(event_sp); - } else { - for (auto &pair : GetListeners()) { - if (!(pair.second & event_type)) - continue; - if (unique && - pair.first->PeekAtNextEventForBroadcasterWithType(&m_broadcaster, - event_type)) - continue; - - pair.first->AddEvent(event_sp); - } - } -} - -void Broadcaster::BroadcasterImpl::BroadcastEvent(uint32_t event_type, - EventData *event_data) { - auto event_sp = std::make_shared(event_type, event_data); - PrivateBroadcastEvent(event_sp, false); -} - -void Broadcaster::BroadcasterImpl::BroadcastEvent( - uint32_t event_type, const lldb::EventDataSP &event_data_sp) { - auto event_sp = std::make_shared(event_type, event_data_sp); - PrivateBroadcastEvent(event_sp, false); -} - -void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique( - uint32_t event_type, EventData *event_data) { - auto event_sp = std::make_shared(event_type, event_data); - PrivateBroadcastEvent(event_sp, true); -} - -bool Broadcaster::BroadcasterImpl::HijackBroadcaster( - const lldb::ListenerSP &listener_sp, uint32_t event_mask) { - std::lock_guard guard(m_listeners_mutex); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log) - log->Printf( - "%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)", - static_cast(this), GetBroadcasterName(), - listener_sp->m_name.c_str(), static_cast(listener_sp.get())); - m_hijacking_listeners.push_back(listener_sp); - m_hijacking_masks.push_back(event_mask); - return true; -} - -bool Broadcaster::BroadcasterImpl::IsHijackedForEvent(uint32_t event_mask) { - std::lock_guard guard(m_listeners_mutex); - - if (!m_hijacking_listeners.empty()) - return (event_mask & m_hijacking_masks.back()) != 0; - return false; -} - -const char *Broadcaster::BroadcasterImpl::GetHijackingListenerName() { - if (m_hijacking_listeners.size()) { - return m_hijacking_listeners.back()->GetName(); - } else { - return nullptr; - } -} - -void Broadcaster::BroadcasterImpl::RestoreBroadcaster() { - std::lock_guard guard(m_listeners_mutex); - - if (!m_hijacking_listeners.empty()) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log) { - ListenerSP listener_sp = m_hijacking_listeners.back(); - log->Printf("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop " - "listener(\"%s\")=%p)", - static_cast(this), GetBroadcasterName(), - listener_sp->m_name.c_str(), - static_cast(listener_sp.get())); - } - m_hijacking_listeners.pop_back(); - } - if (!m_hijacking_masks.empty()) - m_hijacking_masks.pop_back(); -} - -ConstString &Broadcaster::GetBroadcasterClass() const { - static ConstString class_name("lldb.anonymous"); - return class_name; -} - -BroadcastEventSpec::BroadcastEventSpec(const BroadcastEventSpec &rhs) = default; - -bool BroadcastEventSpec::operator<(const BroadcastEventSpec &rhs) const { - if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) { - return GetEventBits() < rhs.GetEventBits(); - } else { - return GetBroadcasterClass() < rhs.GetBroadcasterClass(); - } -} - -BroadcastEventSpec &BroadcastEventSpec:: -operator=(const BroadcastEventSpec &rhs) = default; - -BroadcasterManager::BroadcasterManager() : m_manager_mutex() {} - -lldb::BroadcasterManagerSP BroadcasterManager::MakeBroadcasterManager() { - return lldb::BroadcasterManagerSP(new BroadcasterManager()); -} - -uint32_t BroadcasterManager::RegisterListenerForEvents( - const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { - std::lock_guard guard(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_sp)); - m_listeners.insert(listener_sp); - } - - return available_bits; -} - -bool BroadcasterManager::UnregisterListenerForEvents( - const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { - std::lock_guard guard(m_manager_mutex); - bool removed_some = false; - - if (m_listeners.erase(listener_sp) == 0) - return false; - - ListenerMatchesAndSharedBits predicate(event_spec, listener_sp); - std::vector 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 (true) { - 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_sp)); - } - - return removed_some; -} - -ListenerSP BroadcasterManager::GetListenerForEventSpec( - BroadcastEventSpec event_spec) const { - std::lock_guard guard(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 nullptr; -} - -void BroadcasterManager::RemoveListener(Listener *listener) { - std::lock_guard guard(m_manager_mutex); - ListenerMatchesPointer predicate(listener); - listener_collection::iterator iter = m_listeners.begin(), - end_iter = m_listeners.end(); - - std::find_if(iter, end_iter, predicate); - if (iter != end_iter) - m_listeners.erase(iter); - - while (true) { - 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::RemoveListener(const lldb::ListenerSP &listener_sp) { - std::lock_guard guard(m_manager_mutex); - ListenerMatches predicate(listener_sp); - - if (m_listeners.erase(listener_sp) == 0) - return; - - while (true) { - 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) { - std::lock_guard guard(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() { - std::lock_guard guard(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->shared_from_this()); - m_listeners.clear(); - m_event_map.clear(); -} Index: lldb/trunk/source/Core/CMakeLists.txt =================================================================== --- lldb/trunk/source/Core/CMakeLists.txt +++ lldb/trunk/source/Core/CMakeLists.txt @@ -13,7 +13,6 @@ AddressResolver.cpp AddressResolverFileLine.cpp AddressResolverName.cpp - Broadcaster.cpp Communication.cpp Debugger.cpp Disassembler.cpp @@ -21,13 +20,11 @@ DumpRegisterValue.cpp DynamicLoader.cpp EmulateInstruction.cpp - Event.cpp FileLineResolver.cpp FileSpecList.cpp FormatEntity.cpp Highlighter.cpp IOHandler.cpp - Listener.cpp Mangled.cpp Module.cpp ModuleChild.cpp Index: lldb/trunk/source/Core/Communication.cpp =================================================================== --- lldb/trunk/source/Core/Communication.cpp +++ lldb/trunk/source/Core/Communication.cpp @@ -9,12 +9,12 @@ #include "lldb/Core/Communication.h" -#include "lldb/Core/Event.h" -#include "lldb/Core/Listener.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Utility/Connection.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Event.h" +#include "lldb/Utility/Listener.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Logging.h" #include "lldb/Utility/Status.h" Index: lldb/trunk/source/Core/Debugger.cpp =================================================================== --- lldb/trunk/source/Core/Debugger.cpp +++ lldb/trunk/source/Core/Debugger.cpp @@ -10,9 +10,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Breakpoint/Breakpoint.h" -#include "lldb/Core/Event.h" #include "lldb/Core/FormatEntity.h" -#include "lldb/Core/Listener.h" #include "lldb/Core/Mangled.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/PluginManager.h" @@ -43,6 +41,8 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadList.h" #include "lldb/Utility/AnsiTerminal.h" +#include "lldb/Utility/Event.h" +#include "lldb/Utility/Listener.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Reproducer.h" #include "lldb/Utility/State.h" Index: lldb/trunk/source/Core/Event.cpp =================================================================== --- lldb/trunk/source/Core/Event.cpp +++ lldb/trunk/source/Core/Event.cpp @@ -1,301 +0,0 @@ -//===-- Event.cpp -----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Core/Event.h" - -#include "lldb/Core/Broadcaster.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/Endian.h" -#include "lldb/Utility/Stream.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/lldb-enumerations.h" - -#include - -#include - -using namespace lldb; -using namespace lldb_private; - -#pragma mark - -#pragma mark Event - -//------------------------------------------------------------------ -// Event functions -//------------------------------------------------------------------ - -Event::Event(Broadcaster *broadcaster, uint32_t event_type, EventData *data) - : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type), - m_data_sp(data) {} - -Event::Event(Broadcaster *broadcaster, uint32_t event_type, - const EventDataSP &event_data_sp) - : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type), - m_data_sp(event_data_sp) {} - -Event::Event(uint32_t event_type, EventData *data) - : m_broadcaster_wp(), m_type(event_type), m_data_sp(data) {} - -Event::Event(uint32_t event_type, const EventDataSP &event_data_sp) - : m_broadcaster_wp(), m_type(event_type), m_data_sp(event_data_sp) {} - -Event::~Event() = default; - -void Event::Dump(Stream *s) const { - Broadcaster *broadcaster; - Broadcaster::BroadcasterImplSP broadcaster_impl_sp(m_broadcaster_wp.lock()); - if (broadcaster_impl_sp) - broadcaster = broadcaster_impl_sp->GetBroadcaster(); - else - broadcaster = nullptr; - - if (broadcaster) { - StreamString event_name; - if (broadcaster->GetEventNames(event_name, m_type, false)) - s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x (%s), data = ", - static_cast(this), - static_cast(broadcaster), - broadcaster->GetBroadcasterName().GetCString(), m_type, - event_name.GetData()); - else - s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x, data = ", - static_cast(this), - static_cast(broadcaster), - broadcaster->GetBroadcasterName().GetCString(), m_type); - } else - s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ", - static_cast(this), m_type); - - if (m_data_sp) { - s->PutChar('{'); - m_data_sp->Dump(s); - s->PutChar('}'); - } else - s->Printf(""); -} - -void Event::DoOnRemoval() { - if (m_data_sp) - m_data_sp->DoOnRemoval(this); -} - -#pragma mark - -#pragma mark EventData - -//------------------------------------------------------------------ -// EventData functions -//------------------------------------------------------------------ - -EventData::EventData() = default; - -EventData::~EventData() = default; - -void EventData::Dump(Stream *s) const { s->PutCString("Generic Event Data"); } - -#pragma mark - -#pragma mark EventDataBytes - -//------------------------------------------------------------------ -// EventDataBytes functions -//------------------------------------------------------------------ - -EventDataBytes::EventDataBytes() : m_bytes() {} - -EventDataBytes::EventDataBytes(const char *cstr) : m_bytes() { - SetBytesFromCString(cstr); -} - -EventDataBytes::EventDataBytes(llvm::StringRef str) : m_bytes() { - SetBytes(str.data(), str.size()); -} - -EventDataBytes::EventDataBytes(const void *src, size_t src_len) : m_bytes() { - SetBytes(src, src_len); -} - -EventDataBytes::~EventDataBytes() = default; - -const ConstString &EventDataBytes::GetFlavorString() { - static ConstString g_flavor("EventDataBytes"); - return g_flavor; -} - -const ConstString &EventDataBytes::GetFlavor() const { - return EventDataBytes::GetFlavorString(); -} - -void EventDataBytes::Dump(Stream *s) const { - size_t num_printable_chars = - std::count_if(m_bytes.begin(), m_bytes.end(), isprint); - if (num_printable_chars == m_bytes.size()) - s->Format("\"{0}\"", m_bytes); - else - s->Format("{0:$[ ]@[x-2]}", llvm::make_range( - reinterpret_cast(m_bytes.data()), - reinterpret_cast(m_bytes.data() + - m_bytes.size()))); -} - -const void *EventDataBytes::GetBytes() const { - return (m_bytes.empty() ? nullptr : m_bytes.data()); -} - -size_t EventDataBytes::GetByteSize() const { return m_bytes.size(); } - -void EventDataBytes::SetBytes(const void *src, size_t src_len) { - if (src != nullptr && src_len > 0) - m_bytes.assign((const char *)src, src_len); - else - m_bytes.clear(); -} - -void EventDataBytes::SetBytesFromCString(const char *cstr) { - if (cstr != nullptr && cstr[0]) - m_bytes.assign(cstr); - else - m_bytes.clear(); -} - -const void *EventDataBytes::GetBytesFromEvent(const Event *event_ptr) { - const EventDataBytes *e = GetEventDataFromEvent(event_ptr); - if (e != nullptr) - return e->GetBytes(); - return nullptr; -} - -size_t EventDataBytes::GetByteSizeFromEvent(const Event *event_ptr) { - const EventDataBytes *e = GetEventDataFromEvent(event_ptr); - if (e != nullptr) - return e->GetByteSize(); - return 0; -} - -const EventDataBytes * -EventDataBytes::GetEventDataFromEvent(const Event *event_ptr) { - if (event_ptr != nullptr) { - const EventData *event_data = event_ptr->GetData(); - if (event_data && - event_data->GetFlavor() == EventDataBytes::GetFlavorString()) - return static_cast(event_data); - } - return nullptr; -} - -void EventDataBytes::SwapBytes(std::string &new_bytes) { - m_bytes.swap(new_bytes); -} - -#pragma mark - -#pragma mark EventStructuredData - -//------------------------------------------------------------------ -// EventDataStructuredData definitions -//------------------------------------------------------------------ - -EventDataStructuredData::EventDataStructuredData() - : EventData(), m_process_sp(), m_object_sp(), m_plugin_sp() {} - -EventDataStructuredData::EventDataStructuredData( - const ProcessSP &process_sp, const StructuredData::ObjectSP &object_sp, - const lldb::StructuredDataPluginSP &plugin_sp) - : EventData(), m_process_sp(process_sp), m_object_sp(object_sp), - m_plugin_sp(plugin_sp) {} - -EventDataStructuredData::~EventDataStructuredData() {} - -//------------------------------------------------------------------ -// EventDataStructuredData member functions -//------------------------------------------------------------------ - -const ConstString &EventDataStructuredData::GetFlavor() const { - return EventDataStructuredData::GetFlavorString(); -} - -void EventDataStructuredData::Dump(Stream *s) const { - if (!s) - return; - - if (m_object_sp) - m_object_sp->Dump(*s); -} - -const ProcessSP &EventDataStructuredData::GetProcess() const { - return m_process_sp; -} - -const StructuredData::ObjectSP &EventDataStructuredData::GetObject() const { - return m_object_sp; -} - -const lldb::StructuredDataPluginSP & -EventDataStructuredData::GetStructuredDataPlugin() const { - return m_plugin_sp; -} - -void EventDataStructuredData::SetProcess(const ProcessSP &process_sp) { - m_process_sp = process_sp; -} - -void EventDataStructuredData::SetObject( - const StructuredData::ObjectSP &object_sp) { - m_object_sp = object_sp; -} - -void EventDataStructuredData::SetStructuredDataPlugin( - const lldb::StructuredDataPluginSP &plugin_sp) { - m_plugin_sp = plugin_sp; -} - -//------------------------------------------------------------------ -// EventDataStructuredData static functions -//------------------------------------------------------------------ - -const EventDataStructuredData * -EventDataStructuredData::GetEventDataFromEvent(const Event *event_ptr) { - if (event_ptr == nullptr) - return nullptr; - - const EventData *event_data = event_ptr->GetData(); - if (!event_data || - event_data->GetFlavor() != EventDataStructuredData::GetFlavorString()) - return nullptr; - - return static_cast(event_data); -} - -ProcessSP EventDataStructuredData::GetProcessFromEvent(const Event *event_ptr) { - auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); - if (event_data) - return event_data->GetProcess(); - else - return ProcessSP(); -} - -StructuredData::ObjectSP -EventDataStructuredData::GetObjectFromEvent(const Event *event_ptr) { - auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); - if (event_data) - return event_data->GetObject(); - else - return StructuredData::ObjectSP(); -} - -lldb::StructuredDataPluginSP -EventDataStructuredData::GetPluginFromEvent(const Event *event_ptr) { - auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); - if (event_data) - return event_data->GetStructuredDataPlugin(); - else - return StructuredDataPluginSP(); -} - -const ConstString &EventDataStructuredData::GetFlavorString() { - static ConstString s_flavor("EventDataStructuredData"); - return s_flavor; -} Index: lldb/trunk/source/Core/Listener.cpp =================================================================== --- lldb/trunk/source/Core/Listener.cpp +++ lldb/trunk/source/Core/Listener.cpp @@ -1,470 +0,0 @@ -//===-- Listener.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Core/Listener.h" - -#include "lldb/Core/Broadcaster.h" -#include "lldb/Core/Event.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Logging.h" - -#include "llvm/ADT/Optional.h" - -#include -#include -#include - -using namespace lldb; -using namespace lldb_private; - -namespace { -class BroadcasterManagerWPMatcher { -public: - BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp) - : m_manager_sp(manager_sp) {} - bool operator()(const BroadcasterManagerWP input_wp) const { - BroadcasterManagerSP input_sp = input_wp.lock(); - return (input_sp && input_sp == m_manager_sp); - } - - BroadcasterManagerSP m_manager_sp; -}; -} // anonymous namespace - -Listener::Listener(const char *name) - : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(), - m_events_mutex() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log != nullptr) - log->Printf("%p Listener::Listener('%s')", static_cast(this), - m_name.c_str()); -} - -Listener::~Listener() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - - Clear(); - - if (log) - log->Printf("%p Listener::%s('%s')", static_cast(this), - __FUNCTION__, m_name.c_str()); -} - -void Listener::Clear() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - std::lock_guard broadcasters_guard( - m_broadcasters_mutex); - broadcaster_collection::iterator pos, end = m_broadcasters.end(); - for (pos = m_broadcasters.begin(); pos != end; ++pos) { - Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock()); - if (broadcaster_sp) - broadcaster_sp->RemoveListener(this, pos->second.event_mask); - } - m_broadcasters.clear(); - - std::lock_guard events_guard(m_events_mutex); - m_events.clear(); - size_t num_managers = m_broadcaster_managers.size(); - - for (size_t i = 0; i < num_managers; i++) { - BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock()); - if (manager_sp) - manager_sp->RemoveListener(this); - } - - if (log) - log->Printf("%p Listener::%s('%s')", static_cast(this), - __FUNCTION__, m_name.c_str()); -} - -uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, - uint32_t event_mask) { - if (broadcaster) { - // Scope for "locker" - // Tell the broadcaster to add this object as a listener - { - std::lock_guard broadcasters_guard( - m_broadcasters_mutex); - Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); - m_broadcasters.insert( - std::make_pair(impl_wp, BroadcasterInfo(event_mask))); - } - - uint32_t acquired_mask = - broadcaster->AddListener(this->shared_from_this(), event_mask); - - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log != nullptr) - log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " - "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", - static_cast(this), static_cast(broadcaster), - event_mask, acquired_mask, m_name.c_str()); - - return acquired_mask; - } - return 0; -} - -uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, - uint32_t event_mask, - HandleBroadcastCallback callback, - void *callback_user_data) { - if (broadcaster) { - // Scope for "locker" - // Tell the broadcaster to add this object as a listener - { - std::lock_guard broadcasters_guard( - m_broadcasters_mutex); - Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); - m_broadcasters.insert(std::make_pair( - impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data))); - } - - uint32_t acquired_mask = - broadcaster->AddListener(this->shared_from_this(), event_mask); - - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log != nullptr) { - void **pointer = reinterpret_cast(&callback); - log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " - "mask = 0x%8.8x, callback = %p, user_data = %p) " - "acquired_mask = 0x%8.8x for %s", - static_cast(this), static_cast(broadcaster), - event_mask, *pointer, static_cast(callback_user_data), - acquired_mask, m_name.c_str()); - } - - return acquired_mask; - } - return 0; -} - -bool Listener::StopListeningForEvents(Broadcaster *broadcaster, - uint32_t event_mask) { - if (broadcaster) { - // Scope for "locker" - { - std::lock_guard broadcasters_guard( - m_broadcasters_mutex); - m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); - } - // Remove the broadcaster from our set of broadcasters - return broadcaster->RemoveListener(this->shared_from_this(), event_mask); - } - - return false; -} - -// Called when a Broadcaster is in its destructor. We need to remove all -// knowledge of this broadcaster and any events that it may have queued up -void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) { - // Scope for "broadcasters_locker" - { - std::lock_guard broadcasters_guard( - m_broadcasters_mutex); - m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); - } - - // Scope for "event_locker" - { - std::lock_guard events_guard(m_events_mutex); - // Remove all events for this broadcaster object. - event_collection::iterator pos = m_events.begin(); - while (pos != m_events.end()) { - if ((*pos)->GetBroadcaster() == broadcaster) - pos = m_events.erase(pos); - else - ++pos; - } - } -} - -void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { - // Just need to remove this broadcast manager from the list of managers: - broadcaster_manager_collection::iterator iter, - end_iter = m_broadcaster_managers.end(); - BroadcasterManagerWP manager_wp; - - BroadcasterManagerWPMatcher matcher(manager_sp); - iter = std::find_if( - m_broadcaster_managers.begin(), end_iter, matcher); - if (iter != end_iter) - m_broadcaster_managers.erase(iter); -} - -void Listener::AddEvent(EventSP &event_sp) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log != nullptr) - log->Printf("%p Listener('%s')::AddEvent (event_sp = {%p})", - static_cast(this), m_name.c_str(), - static_cast(event_sp.get())); - - std::lock_guard guard(m_events_mutex); - m_events.push_back(event_sp); - m_events_condition.notify_all(); -} - -class EventBroadcasterMatches { -public: - EventBroadcasterMatches(Broadcaster *broadcaster) - : m_broadcaster(broadcaster) {} - - bool operator()(const EventSP &event_sp) const { - return event_sp->BroadcasterIs(m_broadcaster); - } - -private: - Broadcaster *m_broadcaster; -}; - -class EventMatcher { -public: - EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names, - uint32_t num_broadcaster_names, uint32_t event_type_mask) - : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names), - m_num_broadcaster_names(num_broadcaster_names), - m_event_type_mask(event_type_mask) {} - - bool operator()(const EventSP &event_sp) const { - if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster)) - return false; - - if (m_broadcaster_names) { - bool found_source = false; - const ConstString &event_broadcaster_name = - event_sp->GetBroadcaster()->GetBroadcasterName(); - for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) { - if (m_broadcaster_names[i] == event_broadcaster_name) { - found_source = true; - break; - } - } - if (!found_source) - return false; - } - - if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType()) - return true; - return false; - } - -private: - Broadcaster *m_broadcaster; - const ConstString *m_broadcaster_names; - const uint32_t m_num_broadcaster_names; - const uint32_t m_event_type_mask; -}; - -bool Listener::FindNextEventInternal( - std::unique_lock &lock, - Broadcaster *broadcaster, // nullptr for any broadcaster - const ConstString *broadcaster_names, // nullptr for any event - uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp, - bool remove) { - // NOTE: callers of this function must lock m_events_mutex using a - // Mutex::Locker - // and pass the locker as the first argument. m_events_mutex is no longer - // recursive. - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); - - if (m_events.empty()) - return false; - - Listener::event_collection::iterator pos = m_events.end(); - - if (broadcaster == nullptr && broadcaster_names == nullptr && - event_type_mask == 0) { - pos = m_events.begin(); - } else { - pos = std::find_if(m_events.begin(), m_events.end(), - EventMatcher(broadcaster, broadcaster_names, - num_broadcaster_names, event_type_mask)); - } - - if (pos != m_events.end()) { - event_sp = *pos; - - if (log != nullptr) - log->Printf("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " - "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " - "remove=%i) event %p", - static_cast(this), GetName(), - static_cast(broadcaster), - static_cast(broadcaster_names), - num_broadcaster_names, event_type_mask, remove, - static_cast(event_sp.get())); - - if (remove) { - m_events.erase(pos); - // Unlock the event queue here. We've removed this event and are about - // to return it so it should be okay to get the next event off the queue - // here - and it might be useful to do that in the "DoOnRemoval". - lock.unlock(); - event_sp->DoOnRemoval(); - } - return true; - } - - event_sp.reset(); - return false; -} - -Event *Listener::PeekAtNextEvent() { - std::unique_lock guard(m_events_mutex); - EventSP event_sp; - if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false)) - return event_sp.get(); - return nullptr; -} - -Event *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) { - std::unique_lock guard(m_events_mutex); - EventSP event_sp; - if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false)) - return event_sp.get(); - return nullptr; -} - -Event * -Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, - uint32_t event_type_mask) { - std::unique_lock guard(m_events_mutex); - EventSP event_sp; - if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask, - event_sp, false)) - return event_sp.get(); - return nullptr; -} - -bool Listener::GetEventInternal( - const Timeout &timeout, - Broadcaster *broadcaster, // nullptr for any broadcaster - const ConstString *broadcaster_names, // nullptr for any event - uint32_t num_broadcaster_names, uint32_t event_type_mask, - EventSP &event_sp) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); - LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name); - - std::unique_lock lock(m_events_mutex); - - while (true) { - if (FindNextEventInternal(lock, broadcaster, broadcaster_names, - num_broadcaster_names, event_type_mask, event_sp, - true)) { - return true; - } else { - std::cv_status result = std::cv_status::no_timeout; - if (!timeout) - m_events_condition.wait(lock); - else - result = m_events_condition.wait_for(lock, *timeout); - - if (result == std::cv_status::timeout) { - log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); - if (log) - log->Printf("%p Listener::GetEventInternal() timed out for %s", - static_cast(this), m_name.c_str()); - return false; - } else if (result != std::cv_status::no_timeout) { - log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); - if (log) - log->Printf("%p Listener::GetEventInternal() unknown error for %s", - static_cast(this), m_name.c_str()); - return false; - } - } - } - - return false; -} - -bool Listener::GetEventForBroadcasterWithType( - Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp, - const Timeout &timeout) { - return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask, - event_sp); -} - -bool Listener::GetEventForBroadcaster(Broadcaster *broadcaster, - EventSP &event_sp, - const Timeout &timeout) { - return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp); -} - -bool Listener::GetEvent(EventSP &event_sp, const Timeout &timeout) { - return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp); -} - -size_t Listener::HandleBroadcastEvent(EventSP &event_sp) { - size_t num_handled = 0; - std::lock_guard guard(m_broadcasters_mutex); - Broadcaster *broadcaster = event_sp->GetBroadcaster(); - if (!broadcaster) - return 0; - broadcaster_collection::iterator pos; - broadcaster_collection::iterator end = m_broadcasters.end(); - Broadcaster::BroadcasterImplSP broadcaster_impl_sp( - broadcaster->GetBroadcasterImpl()); - for (pos = m_broadcasters.find(broadcaster_impl_sp); - pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) { - BroadcasterInfo info = pos->second; - if (event_sp->GetType() & info.event_mask) { - if (info.callback != nullptr) { - info.callback(event_sp, info.callback_user_data); - ++num_handled; - } - } - } - return num_handled; -} - -uint32_t -Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp, - const BroadcastEventSpec &event_spec) { - if (!manager_sp) - return 0; - - // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to - // avoid violating the lock hierarchy (manager before broadcasters). - std::lock_guard manager_guard( - manager_sp->m_manager_mutex); - std::lock_guard guard(m_broadcasters_mutex); - - uint32_t bits_acquired = manager_sp->RegisterListenerForEvents( - this->shared_from_this(), event_spec); - if (bits_acquired) { - broadcaster_manager_collection::iterator iter, - end_iter = m_broadcaster_managers.end(); - BroadcasterManagerWP manager_wp(manager_sp); - BroadcasterManagerWPMatcher matcher(manager_sp); - iter = std::find_if( - m_broadcaster_managers.begin(), end_iter, matcher); - if (iter == end_iter) - m_broadcaster_managers.push_back(manager_wp); - } - - return bits_acquired; -} - -bool Listener::StopListeningForEventSpec(BroadcasterManagerSP manager_sp, - const BroadcastEventSpec &event_spec) { - if (!manager_sp) - return false; - - std::lock_guard guard(m_broadcasters_mutex); - return manager_sp->UnregisterListenerForEvents(this->shared_from_this(), - event_spec); -} - -ListenerSP Listener::MakeListener(const char *name) { - return ListenerSP(new Listener(name)); -} Index: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h =================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h @@ -15,8 +15,8 @@ #include #include "lldb/Core/Communication.h" -#include "lldb/Core/Listener.h" #include "lldb/Core/StreamBuffer.h" +#include "lldb/Utility/Listener.h" #include "lldb/Utility/Predicate.h" #include "lldb/lldb-private.h" Index: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h =================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -14,12 +14,12 @@ #include #include -#include "lldb/Core/Broadcaster.h" #include "lldb/Core/ThreadSafeValue.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" Index: lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h +++ lldb/trunk/source/Plugins/Process/Utility/HistoryThread.h @@ -12,12 +12,12 @@ #include -#include "lldb/Core/Broadcaster.h" -#include "lldb/Core/Event.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/StackFrameList.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/UserID.h" #include "lldb/lldb-private.h" Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -19,12 +19,12 @@ #include #include "lldb/Core/Communication.h" -#include "lldb/Core/Listener.h" #include "lldb/Host/HostThread.h" #include "lldb/Utility/Args.h" +#include "lldb/Utility/Listener.h" #include "lldb/Utility/Predicate.h" -#include "lldb/lldb-public.h" #include "lldb/Utility/StringExtractorGDBRemote.h" +#include "lldb/lldb-public.h" namespace lldb_private { namespace process_gdb_remote { Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h @@ -15,8 +15,8 @@ #include "GDBRemoteCommunicationHistory.h" // Project includes -#include "lldb/Core/Broadcaster.h" #include "lldb/Host/HostThread.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/lldb-private-forward.h" #include "llvm/Support/Error.h" Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -19,9 +19,9 @@ #include // Project includes -#include "lldb/Core/Event.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringExtractorGDBRemote.h" Index: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -16,7 +16,6 @@ #include #include -#include "lldb/Core/Broadcaster.h" #include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/ThreadSafeValue.h" @@ -24,6 +23,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamGDBRemote.h" Index: lldb/trunk/source/Target/Process.cpp =================================================================== --- lldb/trunk/source/Target/Process.cpp +++ lldb/trunk/source/Target/Process.cpp @@ -17,7 +17,6 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/Event.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -62,6 +61,7 @@ #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanBase.h" #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/NameMatches.h" #include "lldb/Utility/SelectHelper.h" Index: lldb/trunk/source/Target/Target.cpp =================================================================== --- lldb/trunk/source/Target/Target.cpp +++ lldb/trunk/source/Target/Target.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include +#include "lldb/Target/Target.h" #include "Plugins/ExpressionParser/Clang/ClangASTSource.h" #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" @@ -20,12 +20,11 @@ #include "lldb/Breakpoint/BreakpointResolverScripted.h" #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/Event.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" #include "lldb/Core/SearchFilter.h" +#include "lldb/Core/Section.h" #include "lldb/Core/SourceManager.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" @@ -50,15 +49,16 @@ #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/SystemRuntime.h" -#include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" +#include using namespace lldb; using namespace lldb_private; Index: lldb/trunk/source/Target/TargetList.cpp =================================================================== --- lldb/trunk/source/Target/TargetList.cpp +++ lldb/trunk/source/Target/TargetList.cpp @@ -8,9 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/TargetList.h" -#include "lldb/Core/Broadcaster.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/Event.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Host.h" @@ -20,6 +18,8 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/State.h" #include "lldb/Utility/TildeExpressionResolver.h" #include "lldb/Utility/Timer.h" Index: lldb/trunk/source/Utility/Broadcaster.cpp =================================================================== --- lldb/trunk/source/Utility/Broadcaster.cpp +++ lldb/trunk/source/Utility/Broadcaster.cpp @@ -0,0 +1,479 @@ +//===-- Broadcaster.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/Broadcaster.h" + +#include "lldb/Utility/Event.h" +#include "lldb/Utility/Listener.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/StreamString.h" + +#include +#include +#include + +#include +#include + +using namespace lldb; +using namespace lldb_private; + +Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, const char *name) + : m_broadcaster_sp(std::make_shared(*this)), + m_manager_sp(manager_sp), m_broadcaster_name(name) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p Broadcaster::Broadcaster(\"%s\")", + static_cast(this), GetBroadcasterName().AsCString()); +} + +Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster) + : m_broadcaster(broadcaster), m_listeners(), m_listeners_mutex(), + m_hijacking_listeners(), m_hijacking_masks() {} + +Broadcaster::~Broadcaster() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p Broadcaster::~Broadcaster(\"%s\")", + static_cast(this), m_broadcaster_name.AsCString()); + + Clear(); +} + +void Broadcaster::CheckInWithManager() { + if (m_manager_sp) { + m_manager_sp->SignUpListenersForBroadcaster(*this); + } +} + +llvm::SmallVector, 4> +Broadcaster::BroadcasterImpl::GetListeners() { + llvm::SmallVector, 4> listeners; + listeners.reserve(m_listeners.size()); + + for (auto it = m_listeners.begin(); it != m_listeners.end();) { + lldb::ListenerSP curr_listener_sp(it->first.lock()); + if (curr_listener_sp && it->second) { + listeners.emplace_back(std::move(curr_listener_sp), it->second); + ++it; + } else + it = m_listeners.erase(it); + } + + return listeners; +} + +void Broadcaster::BroadcasterImpl::Clear() { + std::lock_guard guard(m_listeners_mutex); + + // Make sure the listener forgets about this broadcaster. We do this in the + // broadcaster in case the broadcaster object initiates the removal. + for (auto &pair : GetListeners()) + pair.first->BroadcasterWillDestruct(&m_broadcaster); + + m_listeners.clear(); +} + +Broadcaster *Broadcaster::BroadcasterImpl::GetBroadcaster() { + return &m_broadcaster; +} + +bool Broadcaster::BroadcasterImpl::GetEventNames( + Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const { + uint32_t num_names_added = 0; + if (event_mask && !m_event_names.empty()) { + event_names_map::const_iterator end = m_event_names.end(); + for (uint32_t bit = 1u, mask = event_mask; mask != 0 && bit != 0; + bit <<= 1, mask >>= 1) { + if (mask & 1) { + event_names_map::const_iterator pos = m_event_names.find(bit); + if (pos != end) { + if (num_names_added > 0) + s.PutCString(", "); + + if (prefix_with_broadcaster_name) { + s.PutCString(GetBroadcasterName()); + s.PutChar('.'); + } + s.PutCString(pos->second); + ++num_names_added; + } + } + } + } + return num_names_added > 0; +} + +void Broadcaster::AddInitialEventsToListener( + const lldb::ListenerSP &listener_sp, uint32_t requested_events) {} + +uint32_t +Broadcaster::BroadcasterImpl::AddListener(const lldb::ListenerSP &listener_sp, + uint32_t event_mask) { + if (!listener_sp) + return 0; + + std::lock_guard guard(m_listeners_mutex); + + // See if we already have this listener, and if so, update its mask + + bool handled = false; + + for (auto &pair : GetListeners()) { + if (pair.first == listener_sp) { + handled = true; + pair.second |= event_mask; + m_broadcaster.AddInitialEventsToListener(listener_sp, event_mask); + break; + } + } + + 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, event_mask); + } + + // Return the event bits that were granted to the listener + return event_mask; +} + +bool Broadcaster::BroadcasterImpl::EventTypeHasListeners(uint32_t event_type) { + std::lock_guard guard(m_listeners_mutex); + + if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back()) + return true; + + for (auto &pair : GetListeners()) { + if (pair.second & event_type) + return true; + } + return false; +} + +bool Broadcaster::BroadcasterImpl::RemoveListener( + lldb_private::Listener *listener, uint32_t event_mask) { + if (!listener) + return false; + + std::lock_guard guard(m_listeners_mutex); + for (auto &pair : GetListeners()) { + if (pair.first.get() == listener) { + pair.second &= ~event_mask; + return true; + } + } + 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) { + return PrivateBroadcastEvent(event_sp, false); +} + +void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique(EventSP &event_sp) { + return PrivateBroadcastEvent(event_sp, true); +} + +void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp, + bool unique) { + // Can't add a nullptr event... + if (!event_sp) + return; + + // Update the broadcaster on this event + event_sp->SetBroadcaster(&m_broadcaster); + + const uint32_t event_type = event_sp->GetType(); + + std::lock_guard guard(m_listeners_mutex); + + ListenerSP hijacking_listener_sp; + + if (!m_hijacking_listeners.empty()) { + assert(!m_hijacking_masks.empty()); + hijacking_listener_sp = m_hijacking_listeners.back(); + if ((event_type & m_hijacking_masks.back()) == 0) + hijacking_listener_sp.reset(); + } + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log) { + StreamString event_description; + event_sp->Dump(&event_description); + log->Printf("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, " + "unique =%i) hijack = %p", + static_cast(this), GetBroadcasterName(), + event_description.GetData(), unique, + static_cast(hijacking_listener_sp.get())); + } + + if (hijacking_listener_sp) { + if (unique && + hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType( + &m_broadcaster, event_type)) + return; + hijacking_listener_sp->AddEvent(event_sp); + } else { + for (auto &pair : GetListeners()) { + if (!(pair.second & event_type)) + continue; + if (unique && + pair.first->PeekAtNextEventForBroadcasterWithType(&m_broadcaster, + event_type)) + continue; + + pair.first->AddEvent(event_sp); + } + } +} + +void Broadcaster::BroadcasterImpl::BroadcastEvent(uint32_t event_type, + EventData *event_data) { + auto event_sp = std::make_shared(event_type, event_data); + PrivateBroadcastEvent(event_sp, false); +} + +void Broadcaster::BroadcasterImpl::BroadcastEvent( + uint32_t event_type, const lldb::EventDataSP &event_data_sp) { + auto event_sp = std::make_shared(event_type, event_data_sp); + PrivateBroadcastEvent(event_sp, false); +} + +void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique( + uint32_t event_type, EventData *event_data) { + auto event_sp = std::make_shared(event_type, event_data); + PrivateBroadcastEvent(event_sp, true); +} + +bool Broadcaster::BroadcasterImpl::HijackBroadcaster( + const lldb::ListenerSP &listener_sp, uint32_t event_mask) { + std::lock_guard guard(m_listeners_mutex); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log) + log->Printf( + "%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)", + static_cast(this), GetBroadcasterName(), + listener_sp->m_name.c_str(), static_cast(listener_sp.get())); + m_hijacking_listeners.push_back(listener_sp); + m_hijacking_masks.push_back(event_mask); + return true; +} + +bool Broadcaster::BroadcasterImpl::IsHijackedForEvent(uint32_t event_mask) { + std::lock_guard guard(m_listeners_mutex); + + if (!m_hijacking_listeners.empty()) + return (event_mask & m_hijacking_masks.back()) != 0; + return false; +} + +const char *Broadcaster::BroadcasterImpl::GetHijackingListenerName() { + if (m_hijacking_listeners.size()) { + return m_hijacking_listeners.back()->GetName(); + } else { + return nullptr; + } +} + +void Broadcaster::BroadcasterImpl::RestoreBroadcaster() { + std::lock_guard guard(m_listeners_mutex); + + if (!m_hijacking_listeners.empty()) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log) { + ListenerSP listener_sp = m_hijacking_listeners.back(); + log->Printf("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop " + "listener(\"%s\")=%p)", + static_cast(this), GetBroadcasterName(), + listener_sp->m_name.c_str(), + static_cast(listener_sp.get())); + } + m_hijacking_listeners.pop_back(); + } + if (!m_hijacking_masks.empty()) + m_hijacking_masks.pop_back(); +} + +ConstString &Broadcaster::GetBroadcasterClass() const { + static ConstString class_name("lldb.anonymous"); + return class_name; +} + +BroadcastEventSpec::BroadcastEventSpec(const BroadcastEventSpec &rhs) = default; + +bool BroadcastEventSpec::operator<(const BroadcastEventSpec &rhs) const { + if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) { + return GetEventBits() < rhs.GetEventBits(); + } else { + return GetBroadcasterClass() < rhs.GetBroadcasterClass(); + } +} + +BroadcastEventSpec &BroadcastEventSpec:: +operator=(const BroadcastEventSpec &rhs) = default; + +BroadcasterManager::BroadcasterManager() : m_manager_mutex() {} + +lldb::BroadcasterManagerSP BroadcasterManager::MakeBroadcasterManager() { + return lldb::BroadcasterManagerSP(new BroadcasterManager()); +} + +uint32_t BroadcasterManager::RegisterListenerForEvents( + const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { + std::lock_guard guard(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_sp)); + m_listeners.insert(listener_sp); + } + + return available_bits; +} + +bool BroadcasterManager::UnregisterListenerForEvents( + const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { + std::lock_guard guard(m_manager_mutex); + bool removed_some = false; + + if (m_listeners.erase(listener_sp) == 0) + return false; + + ListenerMatchesAndSharedBits predicate(event_spec, listener_sp); + std::vector 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 (true) { + 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_sp)); + } + + return removed_some; +} + +ListenerSP BroadcasterManager::GetListenerForEventSpec( + BroadcastEventSpec event_spec) const { + std::lock_guard guard(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 nullptr; +} + +void BroadcasterManager::RemoveListener(Listener *listener) { + std::lock_guard guard(m_manager_mutex); + ListenerMatchesPointer predicate(listener); + listener_collection::iterator iter = m_listeners.begin(), + end_iter = m_listeners.end(); + + std::find_if(iter, end_iter, predicate); + if (iter != end_iter) + m_listeners.erase(iter); + + while (true) { + 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::RemoveListener(const lldb::ListenerSP &listener_sp) { + std::lock_guard guard(m_manager_mutex); + ListenerMatches predicate(listener_sp); + + if (m_listeners.erase(listener_sp) == 0) + return; + + while (true) { + 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) { + std::lock_guard guard(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() { + std::lock_guard guard(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->shared_from_this()); + m_listeners.clear(); + m_event_map.clear(); +} Index: lldb/trunk/source/Utility/CMakeLists.txt =================================================================== --- lldb/trunk/source/Utility/CMakeLists.txt +++ lldb/trunk/source/Utility/CMakeLists.txt @@ -45,6 +45,7 @@ ArchSpec.cpp Args.cpp Baton.cpp + Broadcaster.cpp Connection.cpp ConstString.cpp CompletionRequest.cpp @@ -53,10 +54,12 @@ DataEncoder.cpp DataExtractor.cpp Environment.cpp + Event.cpp FileSpec.cpp IOObject.cpp JSON.cpp LLDBAssert.cpp + Listener.cpp Log.cpp Logging.cpp NameMatches.cpp Index: lldb/trunk/source/Utility/Event.cpp =================================================================== --- lldb/trunk/source/Utility/Event.cpp +++ lldb/trunk/source/Utility/Event.cpp @@ -0,0 +1,301 @@ +//===-- Event.cpp -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/Event.h" + +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/lldb-enumerations.h" + +#include + +#include + +using namespace lldb; +using namespace lldb_private; + +#pragma mark - +#pragma mark Event + +//------------------------------------------------------------------ +// Event functions +//------------------------------------------------------------------ + +Event::Event(Broadcaster *broadcaster, uint32_t event_type, EventData *data) + : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type), + m_data_sp(data) {} + +Event::Event(Broadcaster *broadcaster, uint32_t event_type, + const EventDataSP &event_data_sp) + : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type), + m_data_sp(event_data_sp) {} + +Event::Event(uint32_t event_type, EventData *data) + : m_broadcaster_wp(), m_type(event_type), m_data_sp(data) {} + +Event::Event(uint32_t event_type, const EventDataSP &event_data_sp) + : m_broadcaster_wp(), m_type(event_type), m_data_sp(event_data_sp) {} + +Event::~Event() = default; + +void Event::Dump(Stream *s) const { + Broadcaster *broadcaster; + Broadcaster::BroadcasterImplSP broadcaster_impl_sp(m_broadcaster_wp.lock()); + if (broadcaster_impl_sp) + broadcaster = broadcaster_impl_sp->GetBroadcaster(); + else + broadcaster = nullptr; + + if (broadcaster) { + StreamString event_name; + if (broadcaster->GetEventNames(event_name, m_type, false)) + s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x (%s), data = ", + static_cast(this), + static_cast(broadcaster), + broadcaster->GetBroadcasterName().GetCString(), m_type, + event_name.GetData()); + else + s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x, data = ", + static_cast(this), + static_cast(broadcaster), + broadcaster->GetBroadcasterName().GetCString(), m_type); + } else + s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ", + static_cast(this), m_type); + + if (m_data_sp) { + s->PutChar('{'); + m_data_sp->Dump(s); + s->PutChar('}'); + } else + s->Printf(""); +} + +void Event::DoOnRemoval() { + if (m_data_sp) + m_data_sp->DoOnRemoval(this); +} + +#pragma mark - +#pragma mark EventData + +//------------------------------------------------------------------ +// EventData functions +//------------------------------------------------------------------ + +EventData::EventData() = default; + +EventData::~EventData() = default; + +void EventData::Dump(Stream *s) const { s->PutCString("Generic Event Data"); } + +#pragma mark - +#pragma mark EventDataBytes + +//------------------------------------------------------------------ +// EventDataBytes functions +//------------------------------------------------------------------ + +EventDataBytes::EventDataBytes() : m_bytes() {} + +EventDataBytes::EventDataBytes(const char *cstr) : m_bytes() { + SetBytesFromCString(cstr); +} + +EventDataBytes::EventDataBytes(llvm::StringRef str) : m_bytes() { + SetBytes(str.data(), str.size()); +} + +EventDataBytes::EventDataBytes(const void *src, size_t src_len) : m_bytes() { + SetBytes(src, src_len); +} + +EventDataBytes::~EventDataBytes() = default; + +const ConstString &EventDataBytes::GetFlavorString() { + static ConstString g_flavor("EventDataBytes"); + return g_flavor; +} + +const ConstString &EventDataBytes::GetFlavor() const { + return EventDataBytes::GetFlavorString(); +} + +void EventDataBytes::Dump(Stream *s) const { + size_t num_printable_chars = + std::count_if(m_bytes.begin(), m_bytes.end(), isprint); + if (num_printable_chars == m_bytes.size()) + s->Format("\"{0}\"", m_bytes); + else + s->Format("{0:$[ ]@[x-2]}", llvm::make_range( + reinterpret_cast(m_bytes.data()), + reinterpret_cast(m_bytes.data() + + m_bytes.size()))); +} + +const void *EventDataBytes::GetBytes() const { + return (m_bytes.empty() ? nullptr : m_bytes.data()); +} + +size_t EventDataBytes::GetByteSize() const { return m_bytes.size(); } + +void EventDataBytes::SetBytes(const void *src, size_t src_len) { + if (src != nullptr && src_len > 0) + m_bytes.assign((const char *)src, src_len); + else + m_bytes.clear(); +} + +void EventDataBytes::SetBytesFromCString(const char *cstr) { + if (cstr != nullptr && cstr[0]) + m_bytes.assign(cstr); + else + m_bytes.clear(); +} + +const void *EventDataBytes::GetBytesFromEvent(const Event *event_ptr) { + const EventDataBytes *e = GetEventDataFromEvent(event_ptr); + if (e != nullptr) + return e->GetBytes(); + return nullptr; +} + +size_t EventDataBytes::GetByteSizeFromEvent(const Event *event_ptr) { + const EventDataBytes *e = GetEventDataFromEvent(event_ptr); + if (e != nullptr) + return e->GetByteSize(); + return 0; +} + +const EventDataBytes * +EventDataBytes::GetEventDataFromEvent(const Event *event_ptr) { + if (event_ptr != nullptr) { + const EventData *event_data = event_ptr->GetData(); + if (event_data && + event_data->GetFlavor() == EventDataBytes::GetFlavorString()) + return static_cast(event_data); + } + return nullptr; +} + +void EventDataBytes::SwapBytes(std::string &new_bytes) { + m_bytes.swap(new_bytes); +} + +#pragma mark - +#pragma mark EventStructuredData + +//------------------------------------------------------------------ +// EventDataStructuredData definitions +//------------------------------------------------------------------ + +EventDataStructuredData::EventDataStructuredData() + : EventData(), m_process_sp(), m_object_sp(), m_plugin_sp() {} + +EventDataStructuredData::EventDataStructuredData( + const ProcessSP &process_sp, const StructuredData::ObjectSP &object_sp, + const lldb::StructuredDataPluginSP &plugin_sp) + : EventData(), m_process_sp(process_sp), m_object_sp(object_sp), + m_plugin_sp(plugin_sp) {} + +EventDataStructuredData::~EventDataStructuredData() {} + +//------------------------------------------------------------------ +// EventDataStructuredData member functions +//------------------------------------------------------------------ + +const ConstString &EventDataStructuredData::GetFlavor() const { + return EventDataStructuredData::GetFlavorString(); +} + +void EventDataStructuredData::Dump(Stream *s) const { + if (!s) + return; + + if (m_object_sp) + m_object_sp->Dump(*s); +} + +const ProcessSP &EventDataStructuredData::GetProcess() const { + return m_process_sp; +} + +const StructuredData::ObjectSP &EventDataStructuredData::GetObject() const { + return m_object_sp; +} + +const lldb::StructuredDataPluginSP & +EventDataStructuredData::GetStructuredDataPlugin() const { + return m_plugin_sp; +} + +void EventDataStructuredData::SetProcess(const ProcessSP &process_sp) { + m_process_sp = process_sp; +} + +void EventDataStructuredData::SetObject( + const StructuredData::ObjectSP &object_sp) { + m_object_sp = object_sp; +} + +void EventDataStructuredData::SetStructuredDataPlugin( + const lldb::StructuredDataPluginSP &plugin_sp) { + m_plugin_sp = plugin_sp; +} + +//------------------------------------------------------------------ +// EventDataStructuredData static functions +//------------------------------------------------------------------ + +const EventDataStructuredData * +EventDataStructuredData::GetEventDataFromEvent(const Event *event_ptr) { + if (event_ptr == nullptr) + return nullptr; + + const EventData *event_data = event_ptr->GetData(); + if (!event_data || + event_data->GetFlavor() != EventDataStructuredData::GetFlavorString()) + return nullptr; + + return static_cast(event_data); +} + +ProcessSP EventDataStructuredData::GetProcessFromEvent(const Event *event_ptr) { + auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); + if (event_data) + return event_data->GetProcess(); + else + return ProcessSP(); +} + +StructuredData::ObjectSP +EventDataStructuredData::GetObjectFromEvent(const Event *event_ptr) { + auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); + if (event_data) + return event_data->GetObject(); + else + return StructuredData::ObjectSP(); +} + +lldb::StructuredDataPluginSP +EventDataStructuredData::GetPluginFromEvent(const Event *event_ptr) { + auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); + if (event_data) + return event_data->GetStructuredDataPlugin(); + else + return StructuredDataPluginSP(); +} + +const ConstString &EventDataStructuredData::GetFlavorString() { + static ConstString s_flavor("EventDataStructuredData"); + return s_flavor; +} Index: lldb/trunk/source/Utility/Listener.cpp =================================================================== --- lldb/trunk/source/Utility/Listener.cpp +++ lldb/trunk/source/Utility/Listener.cpp @@ -0,0 +1,470 @@ +//===-- Listener.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/Listener.h" + +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Event.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" + +#include "llvm/ADT/Optional.h" + +#include +#include +#include + +using namespace lldb; +using namespace lldb_private; + +namespace { +class BroadcasterManagerWPMatcher { +public: + BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp) + : m_manager_sp(manager_sp) {} + bool operator()(const BroadcasterManagerWP input_wp) const { + BroadcasterManagerSP input_sp = input_wp.lock(); + return (input_sp && input_sp == m_manager_sp); + } + + BroadcasterManagerSP m_manager_sp; +}; +} // anonymous namespace + +Listener::Listener(const char *name) + : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(), + m_events_mutex() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log != nullptr) + log->Printf("%p Listener::Listener('%s')", static_cast(this), + m_name.c_str()); +} + +Listener::~Listener() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + + Clear(); + + if (log) + log->Printf("%p Listener::%s('%s')", static_cast(this), + __FUNCTION__, m_name.c_str()); +} + +void Listener::Clear() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + std::lock_guard broadcasters_guard( + m_broadcasters_mutex); + broadcaster_collection::iterator pos, end = m_broadcasters.end(); + for (pos = m_broadcasters.begin(); pos != end; ++pos) { + Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock()); + if (broadcaster_sp) + broadcaster_sp->RemoveListener(this, pos->second.event_mask); + } + m_broadcasters.clear(); + + std::lock_guard events_guard(m_events_mutex); + m_events.clear(); + size_t num_managers = m_broadcaster_managers.size(); + + for (size_t i = 0; i < num_managers; i++) { + BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock()); + if (manager_sp) + manager_sp->RemoveListener(this); + } + + if (log) + log->Printf("%p Listener::%s('%s')", static_cast(this), + __FUNCTION__, m_name.c_str()); +} + +uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, + uint32_t event_mask) { + if (broadcaster) { + // Scope for "locker" + // Tell the broadcaster to add this object as a listener + { + std::lock_guard broadcasters_guard( + m_broadcasters_mutex); + Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); + m_broadcasters.insert( + std::make_pair(impl_wp, BroadcasterInfo(event_mask))); + } + + uint32_t acquired_mask = + broadcaster->AddListener(this->shared_from_this(), event_mask); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log != nullptr) + log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " + "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", + static_cast(this), static_cast(broadcaster), + event_mask, acquired_mask, m_name.c_str()); + + return acquired_mask; + } + return 0; +} + +uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, + uint32_t event_mask, + HandleBroadcastCallback callback, + void *callback_user_data) { + if (broadcaster) { + // Scope for "locker" + // Tell the broadcaster to add this object as a listener + { + std::lock_guard broadcasters_guard( + m_broadcasters_mutex); + Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); + m_broadcasters.insert(std::make_pair( + impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data))); + } + + uint32_t acquired_mask = + broadcaster->AddListener(this->shared_from_this(), event_mask); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log != nullptr) { + void **pointer = reinterpret_cast(&callback); + log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " + "mask = 0x%8.8x, callback = %p, user_data = %p) " + "acquired_mask = 0x%8.8x for %s", + static_cast(this), static_cast(broadcaster), + event_mask, *pointer, static_cast(callback_user_data), + acquired_mask, m_name.c_str()); + } + + return acquired_mask; + } + return 0; +} + +bool Listener::StopListeningForEvents(Broadcaster *broadcaster, + uint32_t event_mask) { + if (broadcaster) { + // Scope for "locker" + { + std::lock_guard broadcasters_guard( + m_broadcasters_mutex); + m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); + } + // Remove the broadcaster from our set of broadcasters + return broadcaster->RemoveListener(this->shared_from_this(), event_mask); + } + + return false; +} + +// Called when a Broadcaster is in its destructor. We need to remove all +// knowledge of this broadcaster and any events that it may have queued up +void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) { + // Scope for "broadcasters_locker" + { + std::lock_guard broadcasters_guard( + m_broadcasters_mutex); + m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); + } + + // Scope for "event_locker" + { + std::lock_guard events_guard(m_events_mutex); + // Remove all events for this broadcaster object. + event_collection::iterator pos = m_events.begin(); + while (pos != m_events.end()) { + if ((*pos)->GetBroadcaster() == broadcaster) + pos = m_events.erase(pos); + else + ++pos; + } + } +} + +void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { + // Just need to remove this broadcast manager from the list of managers: + broadcaster_manager_collection::iterator iter, + end_iter = m_broadcaster_managers.end(); + BroadcasterManagerWP manager_wp; + + BroadcasterManagerWPMatcher matcher(manager_sp); + iter = std::find_if( + m_broadcaster_managers.begin(), end_iter, matcher); + if (iter != end_iter) + m_broadcaster_managers.erase(iter); +} + +void Listener::AddEvent(EventSP &event_sp) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log != nullptr) + log->Printf("%p Listener('%s')::AddEvent (event_sp = {%p})", + static_cast(this), m_name.c_str(), + static_cast(event_sp.get())); + + std::lock_guard guard(m_events_mutex); + m_events.push_back(event_sp); + m_events_condition.notify_all(); +} + +class EventBroadcasterMatches { +public: + EventBroadcasterMatches(Broadcaster *broadcaster) + : m_broadcaster(broadcaster) {} + + bool operator()(const EventSP &event_sp) const { + return event_sp->BroadcasterIs(m_broadcaster); + } + +private: + Broadcaster *m_broadcaster; +}; + +class EventMatcher { +public: + EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names, + uint32_t num_broadcaster_names, uint32_t event_type_mask) + : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names), + m_num_broadcaster_names(num_broadcaster_names), + m_event_type_mask(event_type_mask) {} + + bool operator()(const EventSP &event_sp) const { + if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster)) + return false; + + if (m_broadcaster_names) { + bool found_source = false; + const ConstString &event_broadcaster_name = + event_sp->GetBroadcaster()->GetBroadcasterName(); + for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) { + if (m_broadcaster_names[i] == event_broadcaster_name) { + found_source = true; + break; + } + } + if (!found_source) + return false; + } + + if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType()) + return true; + return false; + } + +private: + Broadcaster *m_broadcaster; + const ConstString *m_broadcaster_names; + const uint32_t m_num_broadcaster_names; + const uint32_t m_event_type_mask; +}; + +bool Listener::FindNextEventInternal( + std::unique_lock &lock, + Broadcaster *broadcaster, // nullptr for any broadcaster + const ConstString *broadcaster_names, // nullptr for any event + uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp, + bool remove) { + // NOTE: callers of this function must lock m_events_mutex using a + // Mutex::Locker + // and pass the locker as the first argument. m_events_mutex is no longer + // recursive. + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + + if (m_events.empty()) + return false; + + Listener::event_collection::iterator pos = m_events.end(); + + if (broadcaster == nullptr && broadcaster_names == nullptr && + event_type_mask == 0) { + pos = m_events.begin(); + } else { + pos = std::find_if(m_events.begin(), m_events.end(), + EventMatcher(broadcaster, broadcaster_names, + num_broadcaster_names, event_type_mask)); + } + + if (pos != m_events.end()) { + event_sp = *pos; + + if (log != nullptr) + log->Printf("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " + "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " + "remove=%i) event %p", + static_cast(this), GetName(), + static_cast(broadcaster), + static_cast(broadcaster_names), + num_broadcaster_names, event_type_mask, remove, + static_cast(event_sp.get())); + + if (remove) { + m_events.erase(pos); + // Unlock the event queue here. We've removed this event and are about + // to return it so it should be okay to get the next event off the queue + // here - and it might be useful to do that in the "DoOnRemoval". + lock.unlock(); + event_sp->DoOnRemoval(); + } + return true; + } + + event_sp.reset(); + return false; +} + +Event *Listener::PeekAtNextEvent() { + std::unique_lock guard(m_events_mutex); + EventSP event_sp; + if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false)) + return event_sp.get(); + return nullptr; +} + +Event *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) { + std::unique_lock guard(m_events_mutex); + EventSP event_sp; + if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false)) + return event_sp.get(); + return nullptr; +} + +Event * +Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, + uint32_t event_type_mask) { + std::unique_lock guard(m_events_mutex); + EventSP event_sp; + if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask, + event_sp, false)) + return event_sp.get(); + return nullptr; +} + +bool Listener::GetEventInternal( + const Timeout &timeout, + Broadcaster *broadcaster, // nullptr for any broadcaster + const ConstString *broadcaster_names, // nullptr for any event + uint32_t num_broadcaster_names, uint32_t event_type_mask, + EventSP &event_sp) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name); + + std::unique_lock lock(m_events_mutex); + + while (true) { + if (FindNextEventInternal(lock, broadcaster, broadcaster_names, + num_broadcaster_names, event_type_mask, event_sp, + true)) { + return true; + } else { + std::cv_status result = std::cv_status::no_timeout; + if (!timeout) + m_events_condition.wait(lock); + else + result = m_events_condition.wait_for(lock, *timeout); + + if (result == std::cv_status::timeout) { + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); + if (log) + log->Printf("%p Listener::GetEventInternal() timed out for %s", + static_cast(this), m_name.c_str()); + return false; + } else if (result != std::cv_status::no_timeout) { + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); + if (log) + log->Printf("%p Listener::GetEventInternal() unknown error for %s", + static_cast(this), m_name.c_str()); + return false; + } + } + } + + return false; +} + +bool Listener::GetEventForBroadcasterWithType( + Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp, + const Timeout &timeout) { + return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask, + event_sp); +} + +bool Listener::GetEventForBroadcaster(Broadcaster *broadcaster, + EventSP &event_sp, + const Timeout &timeout) { + return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp); +} + +bool Listener::GetEvent(EventSP &event_sp, const Timeout &timeout) { + return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp); +} + +size_t Listener::HandleBroadcastEvent(EventSP &event_sp) { + size_t num_handled = 0; + std::lock_guard guard(m_broadcasters_mutex); + Broadcaster *broadcaster = event_sp->GetBroadcaster(); + if (!broadcaster) + return 0; + broadcaster_collection::iterator pos; + broadcaster_collection::iterator end = m_broadcasters.end(); + Broadcaster::BroadcasterImplSP broadcaster_impl_sp( + broadcaster->GetBroadcasterImpl()); + for (pos = m_broadcasters.find(broadcaster_impl_sp); + pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) { + BroadcasterInfo info = pos->second; + if (event_sp->GetType() & info.event_mask) { + if (info.callback != nullptr) { + info.callback(event_sp, info.callback_user_data); + ++num_handled; + } + } + } + return num_handled; +} + +uint32_t +Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp, + const BroadcastEventSpec &event_spec) { + if (!manager_sp) + return 0; + + // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to + // avoid violating the lock hierarchy (manager before broadcasters). + std::lock_guard manager_guard( + manager_sp->m_manager_mutex); + std::lock_guard guard(m_broadcasters_mutex); + + uint32_t bits_acquired = manager_sp->RegisterListenerForEvents( + this->shared_from_this(), event_spec); + if (bits_acquired) { + broadcaster_manager_collection::iterator iter, + end_iter = m_broadcaster_managers.end(); + BroadcasterManagerWP manager_wp(manager_sp); + BroadcasterManagerWPMatcher matcher(manager_sp); + iter = std::find_if( + m_broadcaster_managers.begin(), end_iter, matcher); + if (iter == end_iter) + m_broadcaster_managers.push_back(manager_wp); + } + + return bits_acquired; +} + +bool Listener::StopListeningForEventSpec(BroadcasterManagerSP manager_sp, + const BroadcastEventSpec &event_spec) { + if (!manager_sp) + return false; + + std::lock_guard guard(m_broadcasters_mutex); + return manager_sp->UnregisterListenerForEvents(this->shared_from_this(), + event_spec); +} + +ListenerSP Listener::MakeListener(const char *name) { + return ListenerSP(new Listener(name)); +} Index: lldb/trunk/unittests/Core/BroadcasterTest.cpp =================================================================== --- lldb/trunk/unittests/Core/BroadcasterTest.cpp +++ lldb/trunk/unittests/Core/BroadcasterTest.cpp @@ -1,75 +0,0 @@ -//===-- BroadcasterTest.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "gtest/gtest.h" - -#include "lldb/Core/Broadcaster.h" -#include "lldb/Core/Event.h" -#include "lldb/Core/Listener.h" -#include "lldb/Utility/Predicate.h" - -#include - -using namespace lldb; -using namespace lldb_private; - -TEST(BroadcasterTest, BroadcastEvent) { - EventSP event_sp; - Broadcaster broadcaster(nullptr, "test-broadcaster"); - std::chrono::seconds timeout(0); - - // Create a listener, sign it up, make sure it receives an event. - ListenerSP listener1_sp = Listener::MakeListener("test-listener1"); - const uint32_t event_mask1 = 1; - EXPECT_EQ(event_mask1, - listener1_sp->StartListeningForEvents(&broadcaster, event_mask1)); - broadcaster.BroadcastEvent(event_mask1, nullptr); - EXPECT_TRUE(listener1_sp->GetEvent(event_sp, timeout)); - EXPECT_EQ(event_mask1, event_sp->GetType()); - - { - // Add one more listener, make sure it works as well. - ListenerSP listener2_sp = Listener::MakeListener("test-listener2"); - const uint32_t event_mask2 = 1; - EXPECT_EQ(event_mask2, listener2_sp->StartListeningForEvents( - &broadcaster, event_mask1 | event_mask2)); - broadcaster.BroadcastEvent(event_mask2, nullptr); - EXPECT_TRUE(listener2_sp->GetEvent(event_sp, timeout)); - EXPECT_EQ(event_mask2, event_sp->GetType()); - - // Both listeners should get this event. - broadcaster.BroadcastEvent(event_mask1, nullptr); - EXPECT_TRUE(listener1_sp->GetEvent(event_sp, timeout)); - EXPECT_EQ(event_mask1, event_sp->GetType()); - EXPECT_TRUE(listener2_sp->GetEvent(event_sp, timeout)); - EXPECT_EQ(event_mask2, event_sp->GetType()); - } - - // Now again only one listener should be active. - broadcaster.BroadcastEvent(event_mask1, nullptr); - EXPECT_TRUE(listener1_sp->GetEvent(event_sp, timeout)); - EXPECT_EQ(event_mask1, event_sp->GetType()); -} - -TEST(BroadcasterTest, EventTypeHasListeners) { - EventSP event_sp; - Broadcaster broadcaster(nullptr, "test-broadcaster"); - - const uint32_t event_mask = 1; - EXPECT_FALSE(broadcaster.EventTypeHasListeners(event_mask)); - - { - ListenerSP listener_sp = Listener::MakeListener("test-listener"); - EXPECT_EQ(event_mask, - listener_sp->StartListeningForEvents(&broadcaster, event_mask)); - EXPECT_TRUE(broadcaster.EventTypeHasListeners(event_mask)); - } - - EXPECT_FALSE(broadcaster.EventTypeHasListeners(event_mask)); -} Index: lldb/trunk/unittests/Core/CMakeLists.txt =================================================================== --- lldb/trunk/unittests/Core/CMakeLists.txt +++ lldb/trunk/unittests/Core/CMakeLists.txt @@ -1,7 +1,4 @@ add_lldb_unittest(LLDBCoreTests - BroadcasterTest.cpp - EventTest.cpp - ListenerTest.cpp MangledTest.cpp RangeTest.cpp RichManglingContextTest.cpp Index: lldb/trunk/unittests/Core/EventTest.cpp =================================================================== --- lldb/trunk/unittests/Core/EventTest.cpp +++ lldb/trunk/unittests/Core/EventTest.cpp @@ -1,25 +0,0 @@ -//===-- EventTest.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Core/Event.h" -#include "lldb/Utility/StreamString.h" -#include "gtest/gtest.h" - -using namespace lldb_private; - -static std::string to_string(const EventDataBytes &E) { - StreamString S; - E.Dump(&S); - return S.GetString(); -} - -TEST(EventTest, DumpEventDataBytes) { - EXPECT_EQ(R"("foo")", to_string(EventDataBytes("foo"))); - EXPECT_EQ("01 02 03", to_string(EventDataBytes("\x01\x02\x03"))); -} Index: lldb/trunk/unittests/Core/ListenerTest.cpp =================================================================== --- lldb/trunk/unittests/Core/ListenerTest.cpp +++ lldb/trunk/unittests/Core/ListenerTest.cpp @@ -1,114 +0,0 @@ -//===-- ListenerTest.cpp ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "gtest/gtest.h" - -#include "lldb/Core/Broadcaster.h" -#include "lldb/Core/Listener.h" -#include -#include - -using namespace lldb; -using namespace lldb_private; - -TEST(ListenerTest, GetEventImmediate) { - EventSP event_sp; - Broadcaster broadcaster(nullptr, "test-broadcaster"); - - // Create a listener, sign it up, make sure it receives an event. - ListenerSP listener_sp = Listener::MakeListener("test-listener"); - const uint32_t event_mask = 1; - ASSERT_EQ(event_mask, - listener_sp->StartListeningForEvents(&broadcaster, event_mask)); - - const std::chrono::seconds timeout(0); - // Without any events sent, these should return false. - EXPECT_FALSE(listener_sp->GetEvent(event_sp, timeout)); - EXPECT_FALSE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout)); - EXPECT_FALSE( - listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout)); - EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType( - &broadcaster, event_mask, event_sp, timeout)); - - // Now send events and make sure they get it. - broadcaster.BroadcastEvent(event_mask, nullptr); - EXPECT_TRUE(listener_sp->GetEvent(event_sp, timeout)); - - broadcaster.BroadcastEvent(event_mask, nullptr); - EXPECT_TRUE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout)); - - broadcaster.BroadcastEvent(event_mask, nullptr); - EXPECT_TRUE( - listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout)); - - broadcaster.BroadcastEvent(event_mask, nullptr); - EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType( - &broadcaster, event_mask * 2, event_sp, timeout)); - EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType( - &broadcaster, event_mask, event_sp, timeout)); -} - -TEST(ListenerTest, GetEventWait) { - EventSP event_sp; - Broadcaster broadcaster(nullptr, "test-broadcaster"); - - // Create a listener, sign it up, make sure it receives an event. - ListenerSP listener_sp = Listener::MakeListener("test-listener"); - const uint32_t event_mask = 1; - ASSERT_EQ(event_mask, - listener_sp->StartListeningForEvents(&broadcaster, event_mask)); - - // Without any events sent, these should make a short wait and return false. - std::chrono::microseconds timeout(10); - EXPECT_FALSE(listener_sp->GetEvent(event_sp, timeout)); - EXPECT_FALSE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout)); - EXPECT_FALSE( - listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout)); - EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType( - &broadcaster, event_mask, event_sp, timeout)); - - // Now send events and make sure they get it. - broadcaster.BroadcastEvent(event_mask, nullptr); - EXPECT_TRUE(listener_sp->GetEvent(event_sp, timeout)); - - broadcaster.BroadcastEvent(event_mask, nullptr); - EXPECT_TRUE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout)); - - broadcaster.BroadcastEvent(event_mask, nullptr); - EXPECT_TRUE( - listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout)); - - broadcaster.BroadcastEvent(event_mask, nullptr); - EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType( - &broadcaster, event_mask * 2, event_sp, timeout)); - EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType( - &broadcaster, event_mask, event_sp, timeout)); - - auto delayed_broadcast = [&] { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - broadcaster.BroadcastEvent(event_mask, nullptr); - }; - - // These should do an infinite wait at return the event our asynchronous - // broadcast sends. - std::future async_broadcast = - std::async(std::launch::async, delayed_broadcast); - EXPECT_TRUE(listener_sp->GetEvent(event_sp, llvm::None)); - async_broadcast.get(); - - async_broadcast = std::async(std::launch::async, delayed_broadcast); - EXPECT_TRUE( - listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, llvm::None)); - async_broadcast.get(); - - async_broadcast = std::async(std::launch::async, delayed_broadcast); - EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType( - &broadcaster, event_mask, event_sp, llvm::None)); - async_broadcast.get(); -} Index: lldb/trunk/unittests/Utility/BroadcasterTest.cpp =================================================================== --- lldb/trunk/unittests/Utility/BroadcasterTest.cpp +++ lldb/trunk/unittests/Utility/BroadcasterTest.cpp @@ -0,0 +1,75 @@ +//===-- BroadcasterTest.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Event.h" +#include "lldb/Utility/Listener.h" +#include "lldb/Utility/Predicate.h" + +#include + +using namespace lldb; +using namespace lldb_private; + +TEST(BroadcasterTest, BroadcastEvent) { + EventSP event_sp; + Broadcaster broadcaster(nullptr, "test-broadcaster"); + std::chrono::seconds timeout(0); + + // Create a listener, sign it up, make sure it receives an event. + ListenerSP listener1_sp = Listener::MakeListener("test-listener1"); + const uint32_t event_mask1 = 1; + EXPECT_EQ(event_mask1, + listener1_sp->StartListeningForEvents(&broadcaster, event_mask1)); + broadcaster.BroadcastEvent(event_mask1, nullptr); + EXPECT_TRUE(listener1_sp->GetEvent(event_sp, timeout)); + EXPECT_EQ(event_mask1, event_sp->GetType()); + + { + // Add one more listener, make sure it works as well. + ListenerSP listener2_sp = Listener::MakeListener("test-listener2"); + const uint32_t event_mask2 = 1; + EXPECT_EQ(event_mask2, listener2_sp->StartListeningForEvents( + &broadcaster, event_mask1 | event_mask2)); + broadcaster.BroadcastEvent(event_mask2, nullptr); + EXPECT_TRUE(listener2_sp->GetEvent(event_sp, timeout)); + EXPECT_EQ(event_mask2, event_sp->GetType()); + + // Both listeners should get this event. + broadcaster.BroadcastEvent(event_mask1, nullptr); + EXPECT_TRUE(listener1_sp->GetEvent(event_sp, timeout)); + EXPECT_EQ(event_mask1, event_sp->GetType()); + EXPECT_TRUE(listener2_sp->GetEvent(event_sp, timeout)); + EXPECT_EQ(event_mask2, event_sp->GetType()); + } + + // Now again only one listener should be active. + broadcaster.BroadcastEvent(event_mask1, nullptr); + EXPECT_TRUE(listener1_sp->GetEvent(event_sp, timeout)); + EXPECT_EQ(event_mask1, event_sp->GetType()); +} + +TEST(BroadcasterTest, EventTypeHasListeners) { + EventSP event_sp; + Broadcaster broadcaster(nullptr, "test-broadcaster"); + + const uint32_t event_mask = 1; + EXPECT_FALSE(broadcaster.EventTypeHasListeners(event_mask)); + + { + ListenerSP listener_sp = Listener::MakeListener("test-listener"); + EXPECT_EQ(event_mask, + listener_sp->StartListeningForEvents(&broadcaster, event_mask)); + EXPECT_TRUE(broadcaster.EventTypeHasListeners(event_mask)); + } + + EXPECT_FALSE(broadcaster.EventTypeHasListeners(event_mask)); +} Index: lldb/trunk/unittests/Utility/CMakeLists.txt =================================================================== --- lldb/trunk/unittests/Utility/CMakeLists.txt +++ lldb/trunk/unittests/Utility/CMakeLists.txt @@ -3,14 +3,17 @@ ArgsTest.cpp OptionsWithRawTest.cpp ArchSpecTest.cpp + BroadcasterTest.cpp CleanUpTest.cpp ConstStringTest.cpp CompletionRequestTest.cpp DataExtractorTest.cpp EnvironmentTest.cpp + EventTest.cpp FileSpecTest.cpp FlagsTest.cpp JSONTest.cpp + ListenerTest.cpp LogTest.cpp NameMatchesTest.cpp PredicateTest.cpp Index: lldb/trunk/unittests/Utility/EventTest.cpp =================================================================== --- lldb/trunk/unittests/Utility/EventTest.cpp +++ lldb/trunk/unittests/Utility/EventTest.cpp @@ -0,0 +1,25 @@ +//===-- EventTest.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/Event.h" +#include "lldb/Utility/StreamString.h" +#include "gtest/gtest.h" + +using namespace lldb_private; + +static std::string to_string(const EventDataBytes &E) { + StreamString S; + E.Dump(&S); + return S.GetString(); +} + +TEST(EventTest, DumpEventDataBytes) { + EXPECT_EQ(R"("foo")", to_string(EventDataBytes("foo"))); + EXPECT_EQ("01 02 03", to_string(EventDataBytes("\x01\x02\x03"))); +} Index: lldb/trunk/unittests/Utility/ListenerTest.cpp =================================================================== --- lldb/trunk/unittests/Utility/ListenerTest.cpp +++ lldb/trunk/unittests/Utility/ListenerTest.cpp @@ -0,0 +1,114 @@ +//===-- ListenerTest.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Listener.h" +#include +#include + +using namespace lldb; +using namespace lldb_private; + +TEST(ListenerTest, GetEventImmediate) { + EventSP event_sp; + Broadcaster broadcaster(nullptr, "test-broadcaster"); + + // Create a listener, sign it up, make sure it receives an event. + ListenerSP listener_sp = Listener::MakeListener("test-listener"); + const uint32_t event_mask = 1; + ASSERT_EQ(event_mask, + listener_sp->StartListeningForEvents(&broadcaster, event_mask)); + + const std::chrono::seconds timeout(0); + // Without any events sent, these should return false. + EXPECT_FALSE(listener_sp->GetEvent(event_sp, timeout)); + EXPECT_FALSE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout)); + EXPECT_FALSE( + listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout)); + EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType( + &broadcaster, event_mask, event_sp, timeout)); + + // Now send events and make sure they get it. + broadcaster.BroadcastEvent(event_mask, nullptr); + EXPECT_TRUE(listener_sp->GetEvent(event_sp, timeout)); + + broadcaster.BroadcastEvent(event_mask, nullptr); + EXPECT_TRUE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout)); + + broadcaster.BroadcastEvent(event_mask, nullptr); + EXPECT_TRUE( + listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout)); + + broadcaster.BroadcastEvent(event_mask, nullptr); + EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType( + &broadcaster, event_mask * 2, event_sp, timeout)); + EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType( + &broadcaster, event_mask, event_sp, timeout)); +} + +TEST(ListenerTest, GetEventWait) { + EventSP event_sp; + Broadcaster broadcaster(nullptr, "test-broadcaster"); + + // Create a listener, sign it up, make sure it receives an event. + ListenerSP listener_sp = Listener::MakeListener("test-listener"); + const uint32_t event_mask = 1; + ASSERT_EQ(event_mask, + listener_sp->StartListeningForEvents(&broadcaster, event_mask)); + + // Without any events sent, these should make a short wait and return false. + std::chrono::microseconds timeout(10); + EXPECT_FALSE(listener_sp->GetEvent(event_sp, timeout)); + EXPECT_FALSE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout)); + EXPECT_FALSE( + listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout)); + EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType( + &broadcaster, event_mask, event_sp, timeout)); + + // Now send events and make sure they get it. + broadcaster.BroadcastEvent(event_mask, nullptr); + EXPECT_TRUE(listener_sp->GetEvent(event_sp, timeout)); + + broadcaster.BroadcastEvent(event_mask, nullptr); + EXPECT_TRUE(listener_sp->GetEventForBroadcaster(nullptr, event_sp, timeout)); + + broadcaster.BroadcastEvent(event_mask, nullptr); + EXPECT_TRUE( + listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, timeout)); + + broadcaster.BroadcastEvent(event_mask, nullptr); + EXPECT_FALSE(listener_sp->GetEventForBroadcasterWithType( + &broadcaster, event_mask * 2, event_sp, timeout)); + EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType( + &broadcaster, event_mask, event_sp, timeout)); + + auto delayed_broadcast = [&] { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + broadcaster.BroadcastEvent(event_mask, nullptr); + }; + + // These should do an infinite wait at return the event our asynchronous + // broadcast sends. + std::future async_broadcast = + std::async(std::launch::async, delayed_broadcast); + EXPECT_TRUE(listener_sp->GetEvent(event_sp, llvm::None)); + async_broadcast.get(); + + async_broadcast = std::async(std::launch::async, delayed_broadcast); + EXPECT_TRUE( + listener_sp->GetEventForBroadcaster(&broadcaster, event_sp, llvm::None)); + async_broadcast.get(); + + async_broadcast = std::async(std::launch::async, delayed_broadcast); + EXPECT_TRUE(listener_sp->GetEventForBroadcasterWithType( + &broadcaster, event_mask, event_sp, llvm::None)); + async_broadcast.get(); +}