Coverage Report

Created: 2022-01-15 10:30

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Utility/Broadcaster.h
Line
Count
Source (jump to first uncovered line)
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
27
namespace lldb_private {
28
class Broadcaster;
29
class EventData;
30
class Listener;
31
class Stream;
32
} // namespace lldb_private
33
34
namespace 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
40
class BroadcastEventSpec {
41
public:
42
  BroadcastEventSpec(const ConstString &broadcaster_class, uint32_t event_bits)
43
2.45k
      : m_broadcaster_class(broadcaster_class), m_event_bits(event_bits) {}
44
45
  ~BroadcastEventSpec() = default;
46
47
10.3k
  ConstString GetBroadcasterClass() const { return m_broadcaster_class; }
48
49
2.28k
  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
0
  bool IsContainedIn(const BroadcastEventSpec &in_spec) const {
55
0
    if (m_broadcaster_class != in_spec.GetBroadcasterClass())
56
0
      return false;
57
0
    uint32_t in_bits = in_spec.GetEventBits();
58
0
    if (in_bits == m_event_bits)
59
0
      return true;
60
61
0
    if ((m_event_bits & in_bits) != 0 && (m_event_bits & ~in_bits) == 0)
62
0
      return true;
63
64
0
    return false;
65
0
  }
66
67
  bool operator<(const BroadcastEventSpec &rhs) const;
68
69
private:
70
  ConstString m_broadcaster_class;
71
  uint32_t m_event_bits;
72
};
73
74
class BroadcasterManager
75
    : public std::enable_shared_from_this<BroadcasterManager> {
76
public:
77
  friend class Listener;
78
79
protected:
80
  BroadcasterManager();
81
82
public:
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
5.72k
  ~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
107
private:
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
2.28k
        : m_broadcaster_class(broadcaster_class) {}
122
123
    ~BroadcasterClassMatches() = default;
124
125
3.75k
    bool operator()(const event_listener_key &input) const {
126
3.75k
      return (input.first.GetBroadcasterClass() == m_broadcaster_class);
127
3.75k
    }
128
129
  private:
130
    ConstString m_broadcaster_class;
131
  };
132
133
  class BroadcastEventSpecMatches {
134
  public:
135
    BroadcastEventSpecMatches(const BroadcastEventSpec &broadcaster_spec)
136
0
        : m_broadcaster_spec(broadcaster_spec) {}
137
138
    ~BroadcastEventSpecMatches() = default;
139
140
0
    bool operator()(const event_listener_key &input) const {
141
0
      return (input.first.IsContainedIn(m_broadcaster_spec));
142
0
    }
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
1
        : m_broadcaster_spec(broadcaster_spec), m_listener_sp(listener_sp) {}
154
155
3
    ~ListenerMatchesAndSharedBits() = default;
156
157
1
    bool operator()(const event_listener_key &input) const {
158
1
      return (input.first.GetBroadcasterClass() ==
159
1
                  m_broadcaster_spec.GetBroadcasterClass() &&
160
1
              (input.first.GetEventBits() &
161
1
               m_broadcaster_spec.GetEventBits()) != 0 &&
162
1
              input.second == m_listener_sp);
163
1
    }
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
0
        : m_listener_sp(in_listener_sp) {}
174
175
0
    ~ListenerMatches() = default;
176
177
0
    bool operator()(const event_listener_key &input) const {
178
0
      if (input.second == m_listener_sp)
179
0
        return true;
180
181
0
      return false;
182
0
    }
183
184
  private:
185
    const lldb::ListenerSP m_listener_sp;
186
  };
187
188
  class ListenerMatchesPointer {
189
  public:
190
    ListenerMatchesPointer(const Listener *in_listener)
191
710
        : m_listener(in_listener) {}
192
193
    ~ListenerMatchesPointer() = default;
194
195
1.07k
    bool operator()(const event_listener_key &input) const {
196
1.07k
      if (input.second.get() == m_listener)
197
1.07k
        return true;
198
199
4
      return false;
200
1.07k
    }
201
202
361
    bool operator()(const lldb::ListenerSP &input) const {
203
361
      if (input.get() == m_listener)
204
359
        return true;
205
206
2
      return false;
207
361
    }
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
242
class Broadcaster {
243
  friend class Listener;
244
  friend class Event;
245
246
public:
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
73.5k
  void BroadcastEvent(lldb::EventSP &event_sp) {
263
73.5k
    m_broadcaster_sp->BroadcastEvent(event_sp);
264
73.5k
  }
265
266
0
  void BroadcastEventIfUnique(lldb::EventSP &event_sp) {
267
0
    m_broadcaster_sp->BroadcastEventIfUnique(event_sp);
268
0
  }
269
270
  void BroadcastEvent(uint32_t event_type,
271
5.69k
                      const lldb::EventDataSP &event_data_sp) {
272
5.69k
    m_broadcaster_sp->BroadcastEvent(event_type, event_data_sp);
273
5.69k
  }
274
275
90.7k
  void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr) {
276
90.7k
    m_broadcaster_sp->BroadcastEvent(event_type, event_data);
277
90.7k
  }
278
279
  void BroadcastEventIfUnique(uint32_t event_type,
280
4.91k
                              EventData *event_data = nullptr) {
281
4.91k
    m_broadcaster_sp->BroadcastEventIfUnique(event_type, event_data);
282
4.91k
  }
283
284
63.6k
  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
72.9k
                       uint32_t event_mask) {
310
72.9k
    return m_broadcaster_sp->AddListener(listener_sp, event_mask);
311
72.9k
  }
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
2.64k
  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
2
                     bool prefix_with_broadcaster_name) const {
328
2
    return m_broadcaster_sp->GetEventNames(s, event_mask,
329
2
                                           prefix_with_broadcaster_name);
330
2
  }
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
166k
  void SetEventName(uint32_t event_mask, const char *name) {
338
166k
    m_broadcaster_sp->SetEventName(event_mask, name);
339
166k
  }
340
341
0
  const char *GetEventName(uint32_t event_mask) const {
342
0
    return m_broadcaster_sp->GetEventName(event_mask);
343
0
  }
344
345
359k
  bool EventTypeHasListeners(uint32_t event_type) {
346
359k
    return m_broadcaster_sp->EventTypeHasListeners(event_type);
347
359k
  }
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
2
                      uint32_t event_mask = UINT32_MAX) {
367
2
    return m_broadcaster_sp->RemoveListener(listener_sp, event_mask);
368
2
  }
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
12.5k
                         uint32_t event_mask = UINT32_MAX) {
390
12.5k
    return m_broadcaster_sp->HijackBroadcaster(listener_sp, event_mask);
391
12.5k
  }
392
393
73.1k
  bool IsHijackedForEvent(uint32_t event_mask) {
394
73.1k
    return m_broadcaster_sp->IsHijackedForEvent(event_mask);
395
73.1k
  }
396
397
  /// Restore the state of the Broadcaster from a previous hijack attempt.
398
15.0k
  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
409
protected:
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
60.6k
    ~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
0
    const char *GetBroadcasterName() const {
449
0
      return m_broadcaster.GetBroadcasterName().AsCString();
450
0
    }
451
452
    Broadcaster *GetBroadcaster();
453
454
    bool GetEventNames(Stream &s, const uint32_t event_mask,
455
                       bool prefix_with_broadcaster_name) const;
456
457
166k
    void SetEventName(uint32_t event_mask, const char *name) {
458
166k
      m_event_names[event_mask] = name;
459
166k
    }
460
461
0
    const char *GetEventName(uint32_t event_mask) const {
462
0
      const auto pos = m_event_names.find(event_mask);
463
0
      if (pos != m_event_names.end())
464
0
        return pos->second.c_str();
465
0
      return nullptr;
466
0
    }
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
250k
  BroadcasterImplSP GetBroadcasterImpl() { return m_broadcaster_sp; }
525
526
36.7k
  const char *GetHijackingListenerName() {
527
36.7k
    return m_broadcaster_sp->GetHijackingListenerName();
528
36.7k
  }
529
530
private:
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