/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.85k | : m_broadcaster_class(broadcaster_class), m_event_bits(event_bits) {} |
44 | | |
45 | | ~BroadcastEventSpec() = default; |
46 | | |
47 | 12.9k | ConstString GetBroadcasterClass() const { return m_broadcaster_class; } |
48 | | |
49 | 2.69k | 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.89k | ~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 | | |
117 | | /// \class Broadcaster Broadcaster.h "lldb/Utility/Broadcaster.h" An event |
118 | | /// broadcasting class. |
119 | | /// |
120 | | /// The Broadcaster class is designed to be subclassed by objects that wish to |
121 | | /// vend events in a multi-threaded environment. Broadcaster objects can each |
122 | | /// vend 32 events. Each event is represented by a bit in a 32 bit value and |
123 | | /// these bits can be set: |
124 | | /// \see Broadcaster::SetEventBits(uint32_t) |
125 | | /// or cleared: |
126 | | /// \see Broadcaster::ResetEventBits(uint32_t) |
127 | | /// When an event gets set the Broadcaster object will notify the Listener |
128 | | /// object that is listening for the event (if there is one). |
129 | | /// |
130 | | /// Subclasses should provide broadcast bit definitions for any events they |
131 | | /// vend, typically using an enumeration: |
132 | | /// \code |
133 | | /// class Foo : public Broadcaster |
134 | | /// { |
135 | | /// public: |
136 | | /// // Broadcaster event bits definitions. |
137 | | /// enum |
138 | | /// { |
139 | | /// eBroadcastBitOne = (1 << 0), |
140 | | /// eBroadcastBitTwo = (1 << 1), |
141 | | /// eBroadcastBitThree = (1 << 2), |
142 | | /// ... |
143 | | /// }; |
144 | | /// \endcode |
145 | | class Broadcaster { |
146 | | friend class Listener; |
147 | | friend class Event; |
148 | | |
149 | | public: |
150 | | /// Construct with a broadcaster with a name. |
151 | | /// |
152 | | /// \param[in] manager_sp |
153 | | /// A shared pointer to the BroadcasterManager that will manage this |
154 | | /// broadcaster. |
155 | | /// \param[in] name |
156 | | /// A std::string of the name that this broadcaster will have. |
157 | | Broadcaster(lldb::BroadcasterManagerSP manager_sp, std::string name); |
158 | | |
159 | | /// Destructor. |
160 | | /// |
161 | | /// The destructor is virtual since this class gets subclassed. |
162 | | virtual ~Broadcaster(); |
163 | | |
164 | | void CheckInWithManager(); |
165 | | |
166 | | /// Broadcast an event which has no associated data. |
167 | 79.6k | void BroadcastEvent(lldb::EventSP &event_sp) { |
168 | 79.6k | m_broadcaster_sp->BroadcastEvent(event_sp); |
169 | 79.6k | } |
170 | | |
171 | 0 | void BroadcastEventIfUnique(lldb::EventSP &event_sp) { |
172 | 0 | m_broadcaster_sp->BroadcastEventIfUnique(event_sp); |
173 | 0 | } |
174 | | |
175 | | void BroadcastEvent(uint32_t event_type, |
176 | 4.90k | const lldb::EventDataSP &event_data_sp) { |
177 | 4.90k | m_broadcaster_sp->BroadcastEvent(event_type, event_data_sp); |
178 | 4.90k | } |
179 | | |
180 | 73.9k | void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr) { |
181 | 73.9k | m_broadcaster_sp->BroadcastEvent(event_type, event_data); |
182 | 73.9k | } |
183 | | |
184 | | void BroadcastEventIfUnique(uint32_t event_type, |
185 | 3.85k | EventData *event_data = nullptr) { |
186 | 3.85k | m_broadcaster_sp->BroadcastEventIfUnique(event_type, event_data); |
187 | 3.85k | } |
188 | | |
189 | 62.1k | void Clear() { m_broadcaster_sp->Clear(); } |
190 | | |
191 | | virtual void AddInitialEventsToListener(const lldb::ListenerSP &listener_sp, |
192 | | uint32_t requested_events); |
193 | | |
194 | | /// Listen for any events specified by \a event_mask. |
195 | | /// |
196 | | /// Only one listener can listen to each event bit in a given Broadcaster. |
197 | | /// Once a listener has acquired an event bit, no other broadcaster will |
198 | | /// have access to it until it is relinquished by the first listener that |
199 | | /// gets it. The actual event bits that get acquired by \a listener may be |
200 | | /// different from what is requested in \a event_mask, and to track this the |
201 | | /// actual event bits that are acquired get returned. |
202 | | /// |
203 | | /// \param[in] listener_sp |
204 | | /// The Listener object that wants to monitor the events that |
205 | | /// get broadcast by this object. |
206 | | /// |
207 | | /// \param[in] event_mask |
208 | | /// A bit mask that indicates which events the listener is |
209 | | /// asking to monitor. |
210 | | /// |
211 | | /// \return |
212 | | /// The actual event bits that were acquired by \a listener. |
213 | | uint32_t AddListener(const lldb::ListenerSP &listener_sp, |
214 | 55.6k | uint32_t event_mask) { |
215 | 55.6k | return m_broadcaster_sp->AddListener(listener_sp, event_mask); |
216 | 55.6k | } |
217 | | |
218 | | /// Get this broadcaster's name. |
219 | | /// |
220 | | /// \return |
221 | | /// A reference to a constant std::string containing the name of the |
222 | | /// broadcaster. |
223 | 2.19k | const std::string &GetBroadcasterName() { return m_broadcaster_name; } |
224 | | |
225 | | /// Get the event name(s) for one or more event bits. |
226 | | /// |
227 | | /// \param[in] event_mask |
228 | | /// A bit mask that indicates which events to get names for. |
229 | | /// |
230 | | /// \return |
231 | | /// The NULL terminated C string name of this Broadcaster. |
232 | | bool GetEventNames(Stream &s, const uint32_t event_mask, |
233 | 7 | bool prefix_with_broadcaster_name) const { |
234 | 7 | return m_broadcaster_sp->GetEventNames(s, event_mask, |
235 | 7 | prefix_with_broadcaster_name); |
236 | 7 | } |
237 | | |
238 | | /// Set the name for an event bit. |
239 | | /// |
240 | | /// \param[in] event_mask |
241 | | /// A bit mask that indicates which events the listener is |
242 | | /// asking to monitor. |
243 | 147k | void SetEventName(uint32_t event_mask, const char *name) { |
244 | 147k | m_broadcaster_sp->SetEventName(event_mask, name); |
245 | 147k | } |
246 | | |
247 | 0 | const char *GetEventName(uint32_t event_mask) const { |
248 | 0 | return m_broadcaster_sp->GetEventName(event_mask); |
249 | 0 | } |
250 | | |
251 | 528k | bool EventTypeHasListeners(uint32_t event_type) { |
252 | 528k | return m_broadcaster_sp->EventTypeHasListeners(event_type); |
253 | 528k | } |
254 | | |
255 | | /// Removes a Listener from this broadcasters list and frees the event bits |
256 | | /// specified by \a event_mask that were previously acquired by \a listener |
257 | | /// (assuming \a listener was listening to this object) for other listener |
258 | | /// objects to use. |
259 | | /// |
260 | | /// \param[in] listener_sp |
261 | | /// A Listener object that previously called AddListener. |
262 | | /// |
263 | | /// \param[in] event_mask |
264 | | /// The event bits \a listener wishes to relinquish. |
265 | | /// |
266 | | /// \return |
267 | | /// \b True if the listener was listening to this broadcaster |
268 | | /// and was removed, \b false otherwise. |
269 | | /// |
270 | | /// \see uint32_t Broadcaster::AddListener (Listener*, uint32_t) |
271 | | bool RemoveListener(const lldb::ListenerSP &listener_sp, |
272 | 2 | uint32_t event_mask = UINT32_MAX) { |
273 | 2 | return m_broadcaster_sp->RemoveListener(listener_sp, event_mask); |
274 | 2 | } |
275 | | |
276 | | /// Provides a simple mechanism to temporarily redirect events from |
277 | | /// broadcaster. When you call this function passing in a listener and |
278 | | /// event type mask, all events from the broadcaster matching the mask will |
279 | | /// now go to the hijacking listener. Only one hijack can occur at a time. |
280 | | /// If we need more than this we will have to implement a Listener stack. |
281 | | /// |
282 | | /// \param[in] listener_sp |
283 | | /// A Listener object. You do not need to call StartListeningForEvents |
284 | | /// for this broadcaster (that would fail anyway since the event bits |
285 | | /// would most likely be taken by the listener(s) you are usurping. |
286 | | /// |
287 | | /// \param[in] event_mask |
288 | | /// The event bits \a listener wishes to hijack. |
289 | | /// |
290 | | /// \return |
291 | | /// \b True if the event mask could be hijacked, \b false otherwise. |
292 | | /// |
293 | | /// \see uint32_t Broadcaster::AddListener (Listener*, uint32_t) |
294 | | bool HijackBroadcaster(const lldb::ListenerSP &listener_sp, |
295 | 9.86k | uint32_t event_mask = UINT32_MAX) { |
296 | 9.86k | return m_broadcaster_sp->HijackBroadcaster(listener_sp, event_mask); |
297 | 9.86k | } |
298 | | |
299 | 57.9k | bool IsHijackedForEvent(uint32_t event_mask) { |
300 | 57.9k | return m_broadcaster_sp->IsHijackedForEvent(event_mask); |
301 | 57.9k | } |
302 | | |
303 | | /// Restore the state of the Broadcaster from a previous hijack attempt. |
304 | 9.85k | void RestoreBroadcaster() { m_broadcaster_sp->RestoreBroadcaster(); } |
305 | | |
306 | | /// This needs to be filled in if you are going to register the broadcaster |
307 | | /// with the broadcaster manager and do broadcaster class matching. |
308 | | /// FIXME: Probably should make a ManagedBroadcaster subclass with all the |
309 | | /// bits needed to work with the BroadcasterManager, so that it is clearer |
310 | | /// how to add one. |
311 | | virtual ConstString &GetBroadcasterClass() const; |
312 | | |
313 | | lldb::BroadcasterManagerSP GetManager(); |
314 | | |
315 | 2.67k | void SetPrimaryListener(lldb::ListenerSP listener_sp) { |
316 | 2.67k | m_broadcaster_sp->SetPrimaryListener(listener_sp); |
317 | 2.67k | } |
318 | | |
319 | 0 | lldb::ListenerSP GetPrimaryListener() { |
320 | 0 | return m_broadcaster_sp->m_primary_listener_sp; |
321 | 0 | } |
322 | | |
323 | | protected: |
324 | | /// BroadcasterImpl contains the actual Broadcaster implementation. The |
325 | | /// Broadcaster makes a BroadcasterImpl which lives as long as it does. The |
326 | | /// Listeners & the Events hold a weak pointer to the BroadcasterImpl, so |
327 | | /// that they can survive if a Broadcaster they were listening to is |
328 | | /// destroyed w/o their being able to unregister from it (which can happen if |
329 | | /// the Broadcasters & Listeners are being destroyed on separate threads |
330 | | /// simultaneously. The Broadcaster itself can't be shared out as a weak |
331 | | /// pointer, because some things that are broadcasters (e.g. the Target and |
332 | | /// the Process) are shared in their own right. |
333 | | /// |
334 | | /// For the most part, the Broadcaster functions dispatch to the |
335 | | /// BroadcasterImpl, and are documented in the public Broadcaster API above. |
336 | | class BroadcasterImpl { |
337 | | friend class Listener; |
338 | | friend class Broadcaster; |
339 | | |
340 | | public: |
341 | | BroadcasterImpl(Broadcaster &broadcaster); |
342 | | |
343 | 59.4k | ~BroadcasterImpl() = default; |
344 | | |
345 | | void BroadcastEvent(lldb::EventSP &event_sp); |
346 | | |
347 | | void BroadcastEventIfUnique(lldb::EventSP &event_sp); |
348 | | |
349 | | void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr); |
350 | | |
351 | | void BroadcastEvent(uint32_t event_type, |
352 | | const lldb::EventDataSP &event_data_sp); |
353 | | |
354 | | void BroadcastEventIfUnique(uint32_t event_type, |
355 | | EventData *event_data = nullptr); |
356 | | |
357 | | void Clear(); |
358 | | |
359 | | uint32_t AddListener(const lldb::ListenerSP &listener_sp, |
360 | | uint32_t event_mask); |
361 | | |
362 | 0 | const std::string &GetBroadcasterName() const { |
363 | 0 | return m_broadcaster.GetBroadcasterName(); |
364 | 0 | } |
365 | | |
366 | | Broadcaster *GetBroadcaster(); |
367 | | |
368 | | bool GetEventNames(Stream &s, const uint32_t event_mask, |
369 | | bool prefix_with_broadcaster_name) const; |
370 | | |
371 | 147k | void SetEventName(uint32_t event_mask, const char *name) { |
372 | 147k | m_event_names[event_mask] = name; |
373 | 147k | } |
374 | | |
375 | 0 | const char *GetEventName(uint32_t event_mask) const { |
376 | 0 | const auto pos = m_event_names.find(event_mask); |
377 | 0 | if (pos != m_event_names.end()) |
378 | 0 | return pos->second.c_str(); |
379 | 0 | return nullptr; |
380 | 0 | } |
381 | | |
382 | | bool EventTypeHasListeners(uint32_t event_type); |
383 | | |
384 | | void SetPrimaryListener(lldb::ListenerSP listener_sp); |
385 | | |
386 | | bool RemoveListener(lldb_private::Listener *listener, |
387 | | uint32_t event_mask = UINT32_MAX); |
388 | | |
389 | | bool RemoveListener(const lldb::ListenerSP &listener_sp, |
390 | | uint32_t event_mask = UINT32_MAX); |
391 | | |
392 | | bool HijackBroadcaster(const lldb::ListenerSP &listener_sp, |
393 | | uint32_t event_mask = UINT32_MAX); |
394 | | |
395 | | bool IsHijackedForEvent(uint32_t event_mask); |
396 | | |
397 | | void RestoreBroadcaster(); |
398 | | |
399 | | protected: |
400 | | void PrivateBroadcastEvent(lldb::EventSP &event_sp, bool unique); |
401 | | |
402 | | const char *GetHijackingListenerName(); |
403 | | |
404 | | typedef llvm::SmallVector<std::pair<lldb::ListenerWP, uint32_t>, 4> |
405 | | collection; |
406 | | typedef std::map<uint32_t, std::string> event_names_map; |
407 | | |
408 | | llvm::SmallVector<std::pair<lldb::ListenerSP, uint32_t &>, 4> |
409 | | GetListeners(uint32_t event_mask = UINT32_MAX, bool include_primary = true); |
410 | | |
411 | | bool HasListeners(uint32_t event_mask); |
412 | | |
413 | | /// The broadcaster that this implements. |
414 | | Broadcaster &m_broadcaster; |
415 | | |
416 | | /// Optionally define event names for readability and logging for each |
417 | | /// event bit. |
418 | | event_names_map m_event_names; |
419 | | |
420 | | /// A Broadcaster can have zero, one or many listeners. A Broadcaster with |
421 | | /// zero listeners is a no-op, with one Listener is trivial. |
422 | | /// In most cases of multiple Listeners,the Broadcaster treats all its |
423 | | /// Listeners as equal, sending each event to all of the Listeners in no |
424 | | /// guaranteed order. |
425 | | /// However, some Broadcasters - in particular the Process broadcaster, can |
426 | | /// designate one Listener to be the "Primary Listener". In the case of |
427 | | /// the Process Broadcaster, the Listener passed to the Process constructor |
428 | | /// will be the Primary Listener. |
429 | | /// If the broadcaster has a Primary Listener, then the event gets |
430 | | /// sent first to the Primary Listener, and then when the Primary Listener |
431 | | /// pulls the event and the the event's DoOnRemoval finishes running, |
432 | | /// the event is forwarded to all the other Listeners. |
433 | | /// The other wrinkle is that a Broadcaster may be serving a Hijack |
434 | | /// Listener. If the Hijack Listener is present, events are only sent to |
435 | | /// the Hijack Listener. We use that, for instance, to absorb all the |
436 | | /// events generated by running an expression so that they don't show up to |
437 | | /// the driver or UI as starts and stops. |
438 | | /// If a Broadcaster has both a Primary and a Hijack Listener, the top-most |
439 | | /// Hijack Listener is treated as the current Primary Listener. |
440 | | |
441 | | /// A list of Listener / event_mask pairs that are listening to this |
442 | | /// broadcaster. |
443 | | collection m_listeners; |
444 | | |
445 | | /// A mutex that protects \a m_listeners. |
446 | | std::recursive_mutex m_listeners_mutex; |
447 | | |
448 | | /// See the discussion of Broadcasters and Listeners above. |
449 | | lldb::ListenerSP m_primary_listener_sp; |
450 | | // The primary listener listens to all bits: |
451 | | uint32_t m_primary_listener_mask = UINT32_MAX; |
452 | | |
453 | | /// A simple mechanism to intercept events from a broadcaster |
454 | | std::vector<lldb::ListenerSP> m_hijacking_listeners; |
455 | | |
456 | | /// At some point we may want to have a stack or Listener collections, but |
457 | | /// for now this is just for private hijacking. |
458 | | std::vector<uint32_t> m_hijacking_masks; |
459 | | |
460 | | private: |
461 | | BroadcasterImpl(const BroadcasterImpl &) = delete; |
462 | | const BroadcasterImpl &operator=(const BroadcasterImpl &) = delete; |
463 | | }; |
464 | | |
465 | | typedef std::shared_ptr<BroadcasterImpl> BroadcasterImplSP; |
466 | | typedef std::weak_ptr<BroadcasterImpl> BroadcasterImplWP; |
467 | | |
468 | 220k | BroadcasterImplSP GetBroadcasterImpl() { return m_broadcaster_sp; } |
469 | | |
470 | 28.9k | const char *GetHijackingListenerName() { |
471 | 28.9k | return m_broadcaster_sp->GetHijackingListenerName(); |
472 | 28.9k | } |
473 | | |
474 | | private: |
475 | | BroadcasterImplSP m_broadcaster_sp; |
476 | | lldb::BroadcasterManagerSP m_manager_sp; |
477 | | |
478 | | /// The name of this broadcaster object. |
479 | | const std::string m_broadcaster_name; |
480 | | |
481 | | Broadcaster(const Broadcaster &) = delete; |
482 | | const Broadcaster &operator=(const Broadcaster &) = delete; |
483 | | }; |
484 | | |
485 | | } // namespace lldb_private |
486 | | |
487 | | #endif // LLDB_UTILITY_BROADCASTER_H |