| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543 |
- //===-- Broadcaster.h -------------------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #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 <cstdint>
- #include <map>
- #include <memory>
- #include <mutex>
- #include <set>
- #include <string>
- #include <utility>
- #include <vector>
- namespace lldb_private {
- class Broadcaster;
- class EventData;
- class Listener;
- class Stream;
- } // namespace lldb_private
- 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() = default;
- 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(const 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;
- if ((m_event_bits & in_bits) != 0 && (m_event_bits & ~in_bits) == 0)
- return true;
- return false;
- }
- bool operator<(const BroadcastEventSpec &rhs) const;
- private:
- ConstString m_broadcaster_class;
- uint32_t m_event_bits;
- };
- class BroadcasterManager
- : public std::enable_shared_from_this<BroadcasterManager> {
- 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,
- const BroadcastEventSpec &event_spec);
- bool UnregisterListenerForEvents(const lldb::ListenerSP &listener_sp,
- const BroadcastEventSpec &event_spec);
- lldb::ListenerSP
- GetListenerForEventSpec(const 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<BroadcastEventSpec, lldb::ListenerSP> event_listener_key;
- typedef std::map<BroadcastEventSpec, lldb::ListenerSP> collection;
- typedef std::set<lldb::ListenerSP> 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(const 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(
- const 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;
- 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;
- return false;
- }
- bool operator()(const lldb::ListenerSP &input) const {
- if (input.get() == m_listener)
- return true;
- 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.
- 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_sp
- /// 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.
- 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.
- 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_sp
- /// 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_sp
- /// 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<std::pair<lldb::ListenerWP, uint32_t>, 4>
- collection;
- typedef std::map<uint32_t, std::string> event_names_map;
- llvm::SmallVector<std::pair<lldb::ListenerSP, uint32_t &>, 4>
- GetListeners();
- /// The broadcaster that this implements.
- Broadcaster &m_broadcaster;
- /// Optionally define event names for readability and logging for each
- /// event bit.
- event_names_map m_event_names;
- /// A list of Listener / event_mask pairs that are listening to this
- /// broadcaster.
- collection m_listeners;
- /// A mutex that protects \a m_listeners.
- std::recursive_mutex m_listeners_mutex;
- /// A simple mechanism to intercept events from a broadcaster
- std::vector<lldb::ListenerSP> m_hijacking_listeners;
- /// At some point we may want to have a stack or Listener collections, but
- /// for now this is just for private hijacking.
- std::vector<uint32_t> m_hijacking_masks;
- private:
- BroadcasterImpl(const BroadcasterImpl &) = delete;
- const BroadcasterImpl &operator=(const BroadcasterImpl &) = delete;
- };
- typedef std::shared_ptr<BroadcasterImpl> BroadcasterImplSP;
- typedef std::weak_ptr<BroadcasterImpl> BroadcasterImplWP;
- BroadcasterImplSP GetBroadcasterImpl() { return m_broadcaster_sp; }
- const char *GetHijackingListenerName() {
- return m_broadcaster_sp->GetHijackingListenerName();
- }
- private:
- BroadcasterImplSP m_broadcaster_sp;
- lldb::BroadcasterManagerSP m_manager_sp;
- /// The name of this broadcaster object.
- const ConstString m_broadcaster_name;
- Broadcaster(const Broadcaster &) = delete;
- const Broadcaster &operator=(const Broadcaster &) = delete;
- };
- } // namespace lldb_private
- #endif // LLDB_UTILITY_BROADCASTER_H
|