1//===-- Broadcaster.h -------------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_UTILITY_BROADCASTER_H
10#define LLDB_UTILITY_BROADCASTER_H
11
12#include "lldb/Utility/ConstString.h"
13#include "lldb/lldb-defines.h"
14#include "lldb/lldb-forward.h"
15
16#include "llvm/ADT/SmallVector.h"
17
18#include <cstdint>
19#include <map>
20#include <memory>
21#include <mutex>
22#include <set>
23#include <string>
24#include <utility>
25#include <vector>
26
27namespace lldb_private {
28class Broadcaster;
29class EventData;
30class Listener;
31class Stream;
32} // namespace lldb_private
33
34namespace lldb_private {
35
36/// lldb::BroadcastEventSpec
37///
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
40class BroadcastEventSpec {
41public:
42 BroadcastEventSpec(const ConstString &broadcaster_class, uint32_t event_bits)
43 : m_broadcaster_class(broadcaster_class), m_event_bits(event_bits) {}
44
45 ~BroadcastEventSpec() = default;
46
47 ConstString GetBroadcasterClass() const { return m_broadcaster_class; }
48
49 uint32_t GetEventBits() const { return m_event_bits; }
50
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())
56 return false;
57 uint32_t in_bits = in_spec.GetEventBits();
58 if (in_bits == m_event_bits)
59 return true;
60
61 if ((m_event_bits & in_bits) != 0 && (m_event_bits & ~in_bits) == 0)
62 return true;
63
64 return false;
65 }
66
67 bool operator<(const BroadcastEventSpec &rhs) const;
68
69private:
70 ConstString m_broadcaster_class;
71 uint32_t m_event_bits;
72};
73
74class BroadcasterManager
75 : public std::enable_shared_from_this<BroadcasterManager> {
76public:
77 friend class Listener;
78
79protected:
80 BroadcasterManager();
81
82public:
83 /// Listeners hold onto weak pointers to their broadcaster managers. So they
84 /// must be made into shared pointers, which you do with
85 /// MakeBroadcasterManager.
86 static lldb::BroadcasterManagerSP MakeBroadcasterManager();
87
88 ~BroadcasterManager() = default;
89
90 uint32_t RegisterListenerForEvents(const lldb::ListenerSP &listener_sp,
91 const BroadcastEventSpec &event_spec);
92
93 bool UnregisterListenerForEvents(const lldb::ListenerSP &listener_sp,
94 const BroadcastEventSpec &event_spec);
95
96 lldb::ListenerSP
97 GetListenerForEventSpec(const BroadcastEventSpec &event_spec) const;
98
99 void SignUpListenersForBroadcaster(Broadcaster &broadcaster);
100
101 void RemoveListener(const lldb::ListenerSP &listener_sp);
102
103 void RemoveListener(Listener *listener);
104
105 void Clear();
106
107private:
108 typedef std::pair<BroadcastEventSpec, lldb::ListenerSP> event_listener_key;
109 typedef std::map<BroadcastEventSpec, lldb::ListenerSP> collection;
110 typedef std::set<lldb::ListenerSP> listener_collection;
111 collection m_event_map;
112 listener_collection m_listeners;
113
114 mutable std::recursive_mutex m_manager_mutex;
115
116 // A couple of comparator classes for find_if:
117
118 class BroadcasterClassMatches {
119 public:
120 BroadcasterClassMatches(const ConstString &broadcaster_class)
121 : m_broadcaster_class(broadcaster_class) {}
122
123 ~BroadcasterClassMatches() = default;
124
125 bool operator()(const event_listener_key &input) const {
126 return (input.first.GetBroadcasterClass() == m_broadcaster_class);
127 }
128
129 private:
130 ConstString m_broadcaster_class;
131 };
132
133 class BroadcastEventSpecMatches {
134 public:
135 BroadcastEventSpecMatches(const BroadcastEventSpec &broadcaster_spec)
136 : m_broadcaster_spec(broadcaster_spec) {}
137
138 ~BroadcastEventSpecMatches() = default;
139
140 bool operator()(const event_listener_key &input) const {
141 return (input.first.IsContainedIn(m_broadcaster_spec));
142 }
143
144 private:
145 BroadcastEventSpec m_broadcaster_spec;
146 };
147
148 class ListenerMatchesAndSharedBits {
149 public:
150 explicit ListenerMatchesAndSharedBits(
151 const BroadcastEventSpec &broadcaster_spec,
152 const lldb::ListenerSP &listener_sp)
153 : m_broadcaster_spec(broadcaster_spec), m_listener_sp(listener_sp) {}
154
155 ~ListenerMatchesAndSharedBits() = default;
156
157 bool operator()(const event_listener_key &input) const {
158 return (input.first.GetBroadcasterClass() ==
159 m_broadcaster_spec.GetBroadcasterClass() &&
160 (input.first.GetEventBits() &
161 m_broadcaster_spec.GetEventBits()) != 0 &&
162 input.second == m_listener_sp);
163 }
164
165 private:
166 BroadcastEventSpec m_broadcaster_spec;
167 const lldb::ListenerSP m_listener_sp;
168 };
169
170 class ListenerMatches {
171 public:
172 explicit ListenerMatches(const lldb::ListenerSP &in_listener_sp)
173 : m_listener_sp(in_listener_sp) {}
174
175 ~ListenerMatches() = default;
176
177 bool operator()(const event_listener_key &input) const {
178 if (input.second == m_listener_sp)
179 return true;
180
181 return false;
182 }
183
184 private:
185 const lldb::ListenerSP m_listener_sp;
186 };
187
188 class ListenerMatchesPointer {
189 public:
190 ListenerMatchesPointer(const Listener *in_listener)
191 : m_listener(in_listener) {}
192
193 ~ListenerMatchesPointer() = default;
194
195 bool operator()(const event_listener_key &input) const {
196 if (input.second.get() == m_listener)
197 return true;
198
199 return false;
200 }
201
202 bool operator()(const lldb::ListenerSP &input) const {
203 if (input.get() == m_listener)
204 return true;
205
206 return false;
207 }
208
209 private:
210 const Listener *m_listener;
211 };
212};
213
214/// \class Broadcaster Broadcaster.h "lldb/Utility/Broadcaster.h" An event
215/// broadcasting class.
216///
217/// The Broadcaster class is designed to be subclassed by objects that wish to
218/// vend events in a multi-threaded environment. Broadcaster objects can each
219/// vend 32 events. Each event is represented by a bit in a 32 bit value and
220/// these bits can be set:
221/// \see Broadcaster::SetEventBits(uint32_t)
222/// or cleared:
223/// \see Broadcaster::ResetEventBits(uint32_t)
224/// When an event gets set the Broadcaster object will notify the Listener
225/// object that is listening for the event (if there is one).
226///
227/// Subclasses should provide broadcast bit definitions for any events they
228/// vend, typically using an enumeration:
229/// \code
230/// class Foo : public Broadcaster
231/// {
232/// public:
233/// // Broadcaster event bits definitions.
234/// enum
235/// {
236/// eBroadcastBitOne = (1 << 0),
237/// eBroadcastBitTwo = (1 << 1),
238/// eBroadcastBitThree = (1 << 2),
239/// ...
240/// };
241/// \endcode
242class Broadcaster {
243 friend class Listener;
244 friend class Event;
245
246public:
247 /// Construct with a broadcaster with a name.
248 ///
249 /// \param[in] name
250 /// A NULL terminated C string that contains the name of the
251 /// broadcaster object.
252 Broadcaster(lldb::BroadcasterManagerSP manager_sp, const char *name);
253
254 /// Destructor.
255 ///
256 /// The destructor is virtual since this class gets subclassed.
257 virtual ~Broadcaster();
258
259 void CheckInWithManager();
260
261 /// Broadcast an event which has no associated data.
262 void BroadcastEvent(lldb::EventSP &event_sp) {
263 m_broadcaster_sp->BroadcastEvent(event_sp);
264 }
265
266 void BroadcastEventIfUnique(lldb::EventSP &event_sp) {
267 m_broadcaster_sp->BroadcastEventIfUnique(event_sp);
268 }
269
270 void BroadcastEvent(uint32_t event_type,
271 const lldb::EventDataSP &event_data_sp) {
272 m_broadcaster_sp->BroadcastEvent(event_type, event_data_sp);
273 }
274
275 void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr) {
276 m_broadcaster_sp->BroadcastEvent(event_type, event_data);
277 }
278
279 void BroadcastEventIfUnique(uint32_t event_type,
280 EventData *event_data = nullptr) {
281 m_broadcaster_sp->BroadcastEventIfUnique(event_type, event_data);
282 }
283
284 void Clear() { m_broadcaster_sp->Clear(); }
285
286 virtual void AddInitialEventsToListener(const lldb::ListenerSP &listener_sp,
287 uint32_t requested_events);
288
289 /// Listen for any events specified by \a event_mask.
290 ///
291 /// Only one listener can listen to each event bit in a given Broadcaster.
292 /// Once a listener has acquired an event bit, no other broadcaster will
293 /// have access to it until it is relinquished by the first listener that
294 /// gets it. The actual event bits that get acquired by \a listener may be
295 /// different from what is requested in \a event_mask, and to track this the
296 /// actual event bits that are acquired get returned.
297 ///
298 /// \param[in] listener_sp
299 /// The Listener object that wants to monitor the events that
300 /// get broadcast by this object.
301 ///
302 /// \param[in] event_mask
303 /// A bit mask that indicates which events the listener is
304 /// asking to monitor.
305 ///
306 /// \return
307 /// The actual event bits that were acquired by \a listener.
308 uint32_t AddListener(const lldb::ListenerSP &listener_sp,
309 uint32_t event_mask) {
310 return m_broadcaster_sp->AddListener(listener_sp, event_mask);
311 }
312
313 /// Get the NULL terminated C string name of this Broadcaster object.
314 ///
315 /// \return
316 /// The NULL terminated C string name of this Broadcaster.
317 ConstString GetBroadcasterName() { return m_broadcaster_name; }
318
319 /// Get the event name(s) for one or more event bits.
320 ///
321 /// \param[in] event_mask
322 /// A bit mask that indicates which events to get names for.
323 ///
324 /// \return
325 /// The NULL terminated C string name of this Broadcaster.
326 bool GetEventNames(Stream &s, const uint32_t event_mask,
327 bool prefix_with_broadcaster_name) const {
328 return m_broadcaster_sp->GetEventNames(s, event_mask,
329 prefix_with_broadcaster_name);
330 }
331
332 /// Set the name for an event bit.
333 ///
334 /// \param[in] event_mask
335 /// A bit mask that indicates which events the listener is
336 /// asking to monitor.
337 void SetEventName(uint32_t event_mask, const char *name) {
338 m_broadcaster_sp->SetEventName(event_mask, name);
339 }
340
341 const char *GetEventName(uint32_t event_mask) const {
342 return m_broadcaster_sp->GetEventName(event_mask);
343 }
344
345 bool EventTypeHasListeners(uint32_t event_type) {
346 return m_broadcaster_sp->EventTypeHasListeners(event_type);
347 }
348
349 /// Removes a Listener from this broadcasters list and frees the event bits
350 /// specified by \a event_mask that were previously acquired by \a listener
351 /// (assuming \a listener was listening to this object) for other listener
352 /// objects to use.
353 ///
354 /// \param[in] listener_sp
355 /// A Listener object that previously called AddListener.
356 ///
357 /// \param[in] event_mask
358 /// The event bits \a listener wishes to relinquish.
359 ///
360 /// \return
361 /// \b True if the listener was listening to this broadcaster
362 /// and was removed, \b false otherwise.
363 ///
364 /// \see uint32_t Broadcaster::AddListener (Listener*, uint32_t)
365 bool RemoveListener(const lldb::ListenerSP &listener_sp,
366 uint32_t event_mask = UINT32_MAX) {
367 return m_broadcaster_sp->RemoveListener(listener_sp, event_mask);
368 }
369
370 /// Provides a simple mechanism to temporarily redirect events from
371 /// broadcaster. When you call this function passing in a listener and
372 /// event type mask, all events from the broadcaster matching the mask will
373 /// now go to the hijacking listener. Only one hijack can occur at a time.
374 /// If we need more than this we will have to implement a Listener stack.
375 ///
376 /// \param[in] listener_sp
377 /// A Listener object. You do not need to call StartListeningForEvents
378 /// for this broadcaster (that would fail anyway since the event bits
379 /// would most likely be taken by the listener(s) you are usurping.
380 ///
381 /// \param[in] event_mask
382 /// The event bits \a listener wishes to hijack.
383 ///
384 /// \return
385 /// \b True if the event mask could be hijacked, \b false otherwise.
386 ///
387 /// \see uint32_t Broadcaster::AddListener (Listener*, uint32_t)
388 bool HijackBroadcaster(const lldb::ListenerSP &listener_sp,
389 uint32_t event_mask = UINT32_MAX) {
390 return m_broadcaster_sp->HijackBroadcaster(listener_sp, event_mask);
391 }
392
393 bool IsHijackedForEvent(uint32_t event_mask) {
394 return m_broadcaster_sp->IsHijackedForEvent(event_mask);
395 }
396
397 /// Restore the state of the Broadcaster from a previous hijack attempt.
398 void RestoreBroadcaster() { m_broadcaster_sp->RestoreBroadcaster(); }
399
400 /// This needs to be filled in if you are going to register the broadcaster
401 /// with the broadcaster manager and do broadcaster class matching.
402 /// FIXME: Probably should make a ManagedBroadcaster subclass with all the
403 /// bits needed to work with the BroadcasterManager, so that it is clearer
404 /// how to add one.
405 virtual ConstString &GetBroadcasterClass() const;
406
407 lldb::BroadcasterManagerSP GetManager();
408
409protected:
410 /// BroadcasterImpl contains the actual Broadcaster implementation. The
411 /// Broadcaster makes a BroadcasterImpl which lives as long as it does. The
412 /// Listeners & the Events hold a weak pointer to the BroadcasterImpl, so
413 /// that they can survive if a Broadcaster they were listening to is
414 /// destroyed w/o their being able to unregister from it (which can happen if
415 /// the Broadcasters & Listeners are being destroyed on separate threads
416 /// simultaneously. The Broadcaster itself can't be shared out as a weak
417 /// pointer, because some things that are broadcasters (e.g. the Target and
418 /// the Process) are shared in their own right.
419 ///
420 /// For the most part, the Broadcaster functions dispatch to the
421 /// BroadcasterImpl, and are documented in the public Broadcaster API above.
422 class BroadcasterImpl {
423 friend class Listener;
424 friend class Broadcaster;
425
426 public:
427 BroadcasterImpl(Broadcaster &broadcaster);
428
429 ~BroadcasterImpl() = default;
430
431 void BroadcastEvent(lldb::EventSP &event_sp);
432
433 void BroadcastEventIfUnique(lldb::EventSP &event_sp);
434
435 void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr);
436
437 void BroadcastEvent(uint32_t event_type,
438 const lldb::EventDataSP &event_data_sp);
439
440 void BroadcastEventIfUnique(uint32_t event_type,
441 EventData *event_data = nullptr);
442
443 void Clear();
444
445 uint32_t AddListener(const lldb::ListenerSP &listener_sp,
446 uint32_t event_mask);
447
448 const char *GetBroadcasterName() const {
449 return m_broadcaster.GetBroadcasterName().AsCString();
450 }
451
452 Broadcaster *GetBroadcaster();
453
454 bool GetEventNames(Stream &s, const uint32_t event_mask,
455 bool prefix_with_broadcaster_name) const;
456
457 void SetEventName(uint32_t event_mask, const char *name) {
458 m_event_names[event_mask] = name;
459 }
460
461 const char *GetEventName(uint32_t event_mask) const {
462 const auto pos = m_event_names.find(event_mask);
463 if (pos != m_event_names.end())
464 return pos->second.c_str();
465 return nullptr;
466 }
467
468 bool EventTypeHasListeners(uint32_t event_type);
469
470 bool RemoveListener(lldb_private::Listener *listener,
471 uint32_t event_mask = UINT32_MAX);
472
473 bool RemoveListener(const lldb::ListenerSP &listener_sp,
474 uint32_t event_mask = UINT32_MAX);
475
476 bool HijackBroadcaster(const lldb::ListenerSP &listener_sp,
477 uint32_t event_mask = UINT32_MAX);
478
479 bool IsHijackedForEvent(uint32_t event_mask);
480
481 void RestoreBroadcaster();
482
483 protected:
484 void PrivateBroadcastEvent(lldb::EventSP &event_sp, bool unique);
485
486 const char *GetHijackingListenerName();
487
488 typedef llvm::SmallVector<std::pair<lldb::ListenerWP, uint32_t>, 4>
489 collection;
490 typedef std::map<uint32_t, std::string> event_names_map;
491
492 llvm::SmallVector<std::pair<lldb::ListenerSP, uint32_t &>, 4>
493 GetListeners();
494
495 /// The broadcaster that this implements.
496 Broadcaster &m_broadcaster;
497
498 /// Optionally define event names for readability and logging for each
499 /// event bit.
500 event_names_map m_event_names;
501
502 /// A list of Listener / event_mask pairs that are listening to this
503 /// broadcaster.
504 collection m_listeners;
505
506 /// A mutex that protects \a m_listeners.
507 std::recursive_mutex m_listeners_mutex;
508
509 /// A simple mechanism to intercept events from a broadcaster
510 std::vector<lldb::ListenerSP> m_hijacking_listeners;
511
512 /// At some point we may want to have a stack or Listener collections, but
513 /// for now this is just for private hijacking.
514 std::vector<uint32_t> m_hijacking_masks;
515
516 private:
517 BroadcasterImpl(const BroadcasterImpl &) = delete;
518 const BroadcasterImpl &operator=(const BroadcasterImpl &) = delete;
519 };
520
521 typedef std::shared_ptr<BroadcasterImpl> BroadcasterImplSP;
522 typedef std::weak_ptr<BroadcasterImpl> BroadcasterImplWP;
523
524 BroadcasterImplSP GetBroadcasterImpl() { return m_broadcaster_sp; }
525
526 const char *GetHijackingListenerName() {
527 return m_broadcaster_sp->GetHijackingListenerName();
528 }
529
530private:
531 BroadcasterImplSP m_broadcaster_sp;
532 lldb::BroadcasterManagerSP m_manager_sp;
533
534 /// The name of this broadcaster object.
535 const ConstString m_broadcaster_name;
536
537 Broadcaster(const Broadcaster &) = delete;
538 const Broadcaster &operator=(const Broadcaster &) = delete;
539};
540
541} // namespace lldb_private
542
543#endif // LLDB_UTILITY_BROADCASTER_H
544