1 //===-- Broadcaster.h -------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_UTILITY_BROADCASTER_H
10 #define LLDB_UTILITY_BROADCASTER_H
12 #include "lldb/Utility/ConstString.h"
13 #include "lldb/lldb-defines.h"
14 #include "lldb/lldb-forward.h"
16 #include "llvm/ADT/SmallVector.h"
27 namespace lldb_private {
32 } // namespace lldb_private
34 namespace lldb_private {
36 /// lldb::BroadcastEventSpec
38 /// This class is used to specify a kind of event to register for. The
39 /// Debugger maintains a list of BroadcastEventSpec's and when it is made
40 class BroadcastEventSpec {
42 BroadcastEventSpec(ConstString broadcaster_class, uint32_t event_bits)
43 : m_broadcaster_class(broadcaster_class), m_event_bits(event_bits) {}
45 ~BroadcastEventSpec() = default;
47 ConstString GetBroadcasterClass() const { return m_broadcaster_class; }
49 uint32_t GetEventBits() const { return m_event_bits; }
51 /// Tell whether this BroadcastEventSpec is contained in in_spec. That is:
52 /// (a) the two spec's share the same broadcaster class (b) the event bits of
53 /// this spec are wholly contained in those of in_spec.
54 bool IsContainedIn(const BroadcastEventSpec &in_spec) const {
55 if (m_broadcaster_class != in_spec.GetBroadcasterClass())
57 uint32_t in_bits = in_spec.GetEventBits();
58 if (in_bits == m_event_bits)
61 if ((m_event_bits & in_bits) != 0 && (m_event_bits & ~in_bits) == 0)
67 bool operator<(const BroadcastEventSpec &rhs) const;
68 BroadcastEventSpec &operator=(const BroadcastEventSpec &rhs);
71 ConstString m_broadcaster_class;
72 uint32_t m_event_bits;
75 class BroadcasterManager
76 : public std::enable_shared_from_this<BroadcasterManager> {
78 friend class Listener;
84 /// Listeners hold onto weak pointers to their broadcaster managers. So they
85 /// must be made into shared pointers, which you do with
86 /// MakeBroadcasterManager.
87 static lldb::BroadcasterManagerSP MakeBroadcasterManager();
89 ~BroadcasterManager() = default;
91 uint32_t RegisterListenerForEvents(const lldb::ListenerSP &listener_sp,
92 const BroadcastEventSpec &event_spec);
94 bool UnregisterListenerForEvents(const lldb::ListenerSP &listener_sp,
95 const BroadcastEventSpec &event_spec);
98 GetListenerForEventSpec(const BroadcastEventSpec &event_spec) const;
100 void SignUpListenersForBroadcaster(Broadcaster &broadcaster);
102 void RemoveListener(const lldb::ListenerSP &listener_sp);
104 void RemoveListener(Listener *listener);
109 typedef std::pair<BroadcastEventSpec, lldb::ListenerSP> event_listener_key;
110 typedef std::map<BroadcastEventSpec, lldb::ListenerSP> collection;
111 typedef std::set<lldb::ListenerSP> listener_collection;
112 collection m_event_map;
113 listener_collection m_listeners;
115 mutable std::recursive_mutex m_manager_mutex;
117 // A couple of comparator classes for find_if:
119 class BroadcasterClassMatches {
121 BroadcasterClassMatches(ConstString broadcaster_class)
122 : m_broadcaster_class(broadcaster_class) {}
124 ~BroadcasterClassMatches() = default;
126 bool operator()(const event_listener_key &input) const {
127 return (input.first.GetBroadcasterClass() == m_broadcaster_class);
131 ConstString m_broadcaster_class;
134 class BroadcastEventSpecMatches {
136 BroadcastEventSpecMatches(const BroadcastEventSpec &broadcaster_spec)
137 : m_broadcaster_spec(broadcaster_spec) {}
139 ~BroadcastEventSpecMatches() = default;
141 bool operator()(const event_listener_key &input) const {
142 return (input.first.IsContainedIn(m_broadcaster_spec));
146 BroadcastEventSpec m_broadcaster_spec;
149 class ListenerMatchesAndSharedBits {
151 explicit ListenerMatchesAndSharedBits(
152 const BroadcastEventSpec &broadcaster_spec,
153 const lldb::ListenerSP &listener_sp)
154 : m_broadcaster_spec(broadcaster_spec), m_listener_sp(listener_sp) {}
156 ~ListenerMatchesAndSharedBits() = default;
158 bool operator()(const event_listener_key &input) const {
159 return (input.first.GetBroadcasterClass() ==
160 m_broadcaster_spec.GetBroadcasterClass() &&
161 (input.first.GetEventBits() &
162 m_broadcaster_spec.GetEventBits()) != 0 &&
163 input.second == m_listener_sp);
167 BroadcastEventSpec m_broadcaster_spec;
168 const lldb::ListenerSP m_listener_sp;
171 class ListenerMatches {
173 explicit ListenerMatches(const lldb::ListenerSP &in_listener_sp)
174 : m_listener_sp(in_listener_sp) {}
176 ~ListenerMatches() = default;
178 bool operator()(const event_listener_key &input) const {
179 if (input.second == m_listener_sp)
186 const lldb::ListenerSP m_listener_sp;
189 class ListenerMatchesPointer {
191 ListenerMatchesPointer(const Listener *in_listener)
192 : m_listener(in_listener) {}
194 ~ListenerMatchesPointer() = default;
196 bool operator()(const event_listener_key &input) const {
197 if (input.second.get() == m_listener)
203 bool operator()(const lldb::ListenerSP &input) const {
204 if (input.get() == m_listener)
211 const Listener *m_listener;
215 /// \class Broadcaster Broadcaster.h "lldb/Utility/Broadcaster.h" An event
216 /// broadcasting class.
218 /// The Broadcaster class is designed to be subclassed by objects that wish to
219 /// vend events in a multi-threaded environment. Broadcaster objects can each
220 /// vend 32 events. Each event is represented by a bit in a 32 bit value and
221 /// these bits can be set:
222 /// \see Broadcaster::SetEventBits(uint32_t)
224 /// \see Broadcaster::ResetEventBits(uint32_t)
225 /// When an event gets set the Broadcaster object will notify the Listener
226 /// object that is listening for the event (if there is one).
228 /// Subclasses should provide broadcast bit definitions for any events they
229 /// vend, typically using an enumeration:
231 /// class Foo : public Broadcaster
234 /// // Broadcaster event bits definitions.
237 /// eBroadcastBitOne = (1 << 0),
238 /// eBroadcastBitTwo = (1 << 1),
239 /// eBroadcastBitThree = (1 << 2),
244 friend class Listener;
248 /// Construct with a broadcaster with a name.
251 /// A NULL terminated C string that contains the name of the
252 /// broadcaster object.
253 Broadcaster(lldb::BroadcasterManagerSP manager_sp, const char *name);
257 /// The destructor is virtual since this class gets subclassed.
258 virtual ~Broadcaster();
260 void CheckInWithManager();
262 /// Broadcast an event which has no associated data.
264 /// \param[in] event_type
265 /// The element from the enum defining this broadcaster's events
266 /// that is being broadcast.
268 /// \param[in] event_data
269 /// User event data that will be owned by the lldb::Event that
270 /// is created internally.
272 /// \param[in] unique
273 /// If true, then only add an event of this type if there isn't
274 /// one already in the queue.
276 void BroadcastEvent(lldb::EventSP &event_sp) {
277 m_broadcaster_sp->BroadcastEvent(event_sp);
280 void BroadcastEventIfUnique(lldb::EventSP &event_sp) {
281 m_broadcaster_sp->BroadcastEventIfUnique(event_sp);
284 void BroadcastEvent(uint32_t event_type,
285 const lldb::EventDataSP &event_data_sp) {
286 m_broadcaster_sp->BroadcastEvent(event_type, event_data_sp);
289 void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr) {
290 m_broadcaster_sp->BroadcastEvent(event_type, event_data);
293 void BroadcastEventIfUnique(uint32_t event_type,
294 EventData *event_data = nullptr) {
295 m_broadcaster_sp->BroadcastEventIfUnique(event_type, event_data);
298 void Clear() { m_broadcaster_sp->Clear(); }
300 virtual void AddInitialEventsToListener(const lldb::ListenerSP &listener_sp,
301 uint32_t requested_events);
303 /// Listen for any events specified by \a event_mask.
305 /// Only one listener can listen to each event bit in a given Broadcaster.
306 /// Once a listener has acquired an event bit, no other broadcaster will
307 /// have access to it until it is relinquished by the first listener that
308 /// gets it. The actual event bits that get acquired by \a listener may be
309 /// different from what is requested in \a event_mask, and to track this the
310 /// actual event bits that are acquired get returned.
312 /// \param[in] listener
313 /// The Listener object that wants to monitor the events that
314 /// get broadcast by this object.
316 /// \param[in] event_mask
317 /// A bit mask that indicates which events the listener is
318 /// asking to monitor.
321 /// The actual event bits that were acquired by \a listener.
322 uint32_t AddListener(const lldb::ListenerSP &listener_sp,
323 uint32_t event_mask) {
324 return m_broadcaster_sp->AddListener(listener_sp, event_mask);
327 /// Get the NULL terminated C string name of this Broadcaster object.
330 /// The NULL terminated C string name of this Broadcaster.
331 ConstString GetBroadcasterName() { return m_broadcaster_name; }
333 /// Get the event name(s) for one or more event bits.
335 /// \param[in] event_mask
336 /// A bit mask that indicates which events to get names for.
339 /// The NULL terminated C string name of this Broadcaster.
340 bool GetEventNames(Stream &s, const uint32_t event_mask,
341 bool prefix_with_broadcaster_name) const {
342 return m_broadcaster_sp->GetEventNames(s, event_mask,
343 prefix_with_broadcaster_name);
346 /// Set the name for an event bit.
348 /// \param[in] event_mask
349 /// A bit mask that indicates which events the listener is
350 /// asking to monitor.
353 /// The NULL terminated C string name of this Broadcaster.
354 void SetEventName(uint32_t event_mask, const char *name) {
355 m_broadcaster_sp->SetEventName(event_mask, name);
358 const char *GetEventName(uint32_t event_mask) const {
359 return m_broadcaster_sp->GetEventName(event_mask);
362 bool EventTypeHasListeners(uint32_t event_type) {
363 return m_broadcaster_sp->EventTypeHasListeners(event_type);
366 /// Removes a Listener from this broadcasters list and frees the event bits
367 /// specified by \a event_mask that were previously acquired by \a listener
368 /// (assuming \a listener was listening to this object) for other listener
371 /// \param[in] listener
372 /// A Listener object that previously called AddListener.
374 /// \param[in] event_mask
375 /// The event bits \a listener wishes to relinquish.
378 /// \b True if the listener was listening to this broadcaster
379 /// and was removed, \b false otherwise.
381 /// \see uint32_t Broadcaster::AddListener (Listener*, uint32_t)
382 bool RemoveListener(const lldb::ListenerSP &listener_sp,
383 uint32_t event_mask = UINT32_MAX) {
384 return m_broadcaster_sp->RemoveListener(listener_sp, event_mask);
387 /// Provides a simple mechanism to temporarily redirect events from
388 /// broadcaster. When you call this function passing in a listener and
389 /// event type mask, all events from the broadcaster matching the mask will
390 /// now go to the hijacking listener. Only one hijack can occur at a time.
391 /// If we need more than this we will have to implement a Listener stack.
393 /// \param[in] listener
394 /// A Listener object. You do not need to call StartListeningForEvents
395 /// for this broadcaster (that would fail anyway since the event bits
396 /// would most likely be taken by the listener(s) you are usurping.
398 /// \param[in] event_mask
399 /// The event bits \a listener wishes to hijack.
402 /// \b True if the event mask could be hijacked, \b false otherwise.
404 /// \see uint32_t Broadcaster::AddListener (Listener*, uint32_t)
405 bool HijackBroadcaster(const lldb::ListenerSP &listener_sp,
406 uint32_t event_mask = UINT32_MAX) {
407 return m_broadcaster_sp->HijackBroadcaster(listener_sp, event_mask);
410 bool IsHijackedForEvent(uint32_t event_mask) {
411 return m_broadcaster_sp->IsHijackedForEvent(event_mask);
414 /// Restore the state of the Broadcaster from a previous hijack attempt.
415 void RestoreBroadcaster() { m_broadcaster_sp->RestoreBroadcaster(); }
417 /// This needs to be filled in if you are going to register the broadcaster
418 /// with the broadcaster manager and do broadcaster class matching.
419 /// FIXME: Probably should make a ManagedBroadcaster subclass with all the
420 /// bits needed to work with the BroadcasterManager, so that it is clearer
422 virtual ConstString &GetBroadcasterClass() const;
424 lldb::BroadcasterManagerSP GetManager();
427 /// BroadcasterImpl contains the actual Broadcaster implementation. The
428 /// Broadcaster makes a BroadcasterImpl which lives as long as it does. The
429 /// Listeners & the Events hold a weak pointer to the BroadcasterImpl, so
430 /// that they can survive if a Broadcaster they were listening to is
431 /// destroyed w/o their being able to unregister from it (which can happen if
432 /// the Broadcasters & Listeners are being destroyed on separate threads
433 /// simultaneously. The Broadcaster itself can't be shared out as a weak
434 /// pointer, because some things that are broadcasters (e.g. the Target and
435 /// the Process) are shared in their own right.
437 /// For the most part, the Broadcaster functions dispatch to the
438 /// BroadcasterImpl, and are documented in the public Broadcaster API above.
439 class BroadcasterImpl {
440 friend class Listener;
441 friend class Broadcaster;
444 BroadcasterImpl(Broadcaster &broadcaster);
446 ~BroadcasterImpl() = default;
448 void BroadcastEvent(lldb::EventSP &event_sp);
450 void BroadcastEventIfUnique(lldb::EventSP &event_sp);
452 void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr);
454 void BroadcastEvent(uint32_t event_type,
455 const lldb::EventDataSP &event_data_sp);
457 void BroadcastEventIfUnique(uint32_t event_type,
458 EventData *event_data = nullptr);
462 uint32_t AddListener(const lldb::ListenerSP &listener_sp,
463 uint32_t event_mask);
465 const char *GetBroadcasterName() const {
466 return m_broadcaster.GetBroadcasterName().AsCString();
469 Broadcaster *GetBroadcaster();
471 bool GetEventNames(Stream &s, const uint32_t event_mask,
472 bool prefix_with_broadcaster_name) const;
474 void SetEventName(uint32_t event_mask, const char *name) {
475 m_event_names[event_mask] = name;
478 const char *GetEventName(uint32_t event_mask) const {
479 const auto pos = m_event_names.find(event_mask);
480 if (pos != m_event_names.end())
481 return pos->second.c_str();
485 bool EventTypeHasListeners(uint32_t event_type);
487 bool RemoveListener(lldb_private::Listener *listener,
488 uint32_t event_mask = UINT32_MAX);
490 bool RemoveListener(const lldb::ListenerSP &listener_sp,
491 uint32_t event_mask = UINT32_MAX);
493 bool HijackBroadcaster(const lldb::ListenerSP &listener_sp,
494 uint32_t event_mask = UINT32_MAX);
496 bool IsHijackedForEvent(uint32_t event_mask);
498 void RestoreBroadcaster();
501 void PrivateBroadcastEvent(lldb::EventSP &event_sp, bool unique);
503 const char *GetHijackingListenerName();
505 typedef llvm::SmallVector<std::pair<lldb::ListenerWP, uint32_t>, 4>
507 typedef std::map<uint32_t, std::string> event_names_map;
509 llvm::SmallVector<std::pair<lldb::ListenerSP, uint32_t &>, 4>
512 /// The broadcaster that this implements.
513 Broadcaster &m_broadcaster;
515 /// Optionally define event names for readability and logging for each
517 event_names_map m_event_names;
519 /// A list of Listener / event_mask pairs that are listening to this
521 collection m_listeners;
523 /// A mutex that protects \a m_listeners.
524 std::recursive_mutex m_listeners_mutex;
526 /// A simple mechanism to intercept events from a broadcaster
527 std::vector<lldb::ListenerSP> m_hijacking_listeners;
529 /// At some point we may want to have a stack or Listener collections, but
530 /// for now this is just for private hijacking.
531 std::vector<uint32_t> m_hijacking_masks;
534 DISALLOW_COPY_AND_ASSIGN(BroadcasterImpl);
537 typedef std::shared_ptr<BroadcasterImpl> BroadcasterImplSP;
538 typedef std::weak_ptr<BroadcasterImpl> BroadcasterImplWP;
540 BroadcasterImplSP GetBroadcasterImpl() { return m_broadcaster_sp; }
542 const char *GetHijackingListenerName() {
543 return m_broadcaster_sp->GetHijackingListenerName();
547 BroadcasterImplSP m_broadcaster_sp;
548 lldb::BroadcasterManagerSP m_manager_sp;
550 /// The name of this broadcaster object.
551 const ConstString m_broadcaster_name;
553 DISALLOW_COPY_AND_ASSIGN(Broadcaster);
556 } // namespace lldb_private
558 #endif // LLDB_UTILITY_BROADCASTER_H