1 //===-- Event.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_EVENT_H
10 #define LLDB_UTILITY_EVENT_H
11 
12 #include "lldb/Utility/Broadcaster.h"
13 #include "lldb/Utility/ConstString.h"
14 #include "lldb/Utility/Predicate.h"
15 #include "lldb/Utility/StructuredData.h"
16 #include "lldb/lldb-defines.h"
17 #include "lldb/lldb-forward.h"
18 
19 #include "llvm/ADT/StringRef.h"
20 
21 #include <chrono>
22 #include <memory>
23 #include <string>
24 
25 #include <cstddef>
26 #include <cstdint>
27 
28 namespace lldb_private {
29 class Event;
30 class Stream;
31 }
32 
33 namespace lldb_private {
34 
35 // lldb::EventData
36 class EventData {
37   friend class Event;
38 
39 public:
40   EventData();
41 
42   virtual ~EventData();
43 
44   virtual llvm::StringRef GetFlavor() const = 0;
45 
GetLogChannel()46   virtual Log *GetLogChannel() { return nullptr; }
47 
48   virtual void Dump(Stream *s) const;
49 
50 private:
DoOnRemoval(Event * event_ptr)51   virtual void DoOnRemoval(Event *event_ptr) {}
52 
53   EventData(const EventData &) = delete;
54   const EventData &operator=(const EventData &) = delete;
55 };
56 
57 // lldb::EventDataBytes
58 class EventDataBytes : public EventData {
59 public:
60   // Constructors
61   EventDataBytes();
62 
63   EventDataBytes(llvm::StringRef str);
64 
65   ~EventDataBytes() override;
66 
67   // Member functions
68   llvm::StringRef GetFlavor() const override;
69 
70   void Dump(Stream *s) const override;
71 
72   const void *GetBytes() const;
73 
74   size_t GetByteSize() const;
75 
76   // Static functions
77   static const EventDataBytes *GetEventDataFromEvent(const Event *event_ptr);
78 
79   static const void *GetBytesFromEvent(const Event *event_ptr);
80 
81   static size_t GetByteSizeFromEvent(const Event *event_ptr);
82 
83   static llvm::StringRef GetFlavorString();
84 
85 private:
86   std::string m_bytes;
87 
88   EventDataBytes(const EventDataBytes &) = delete;
89   const EventDataBytes &operator=(const EventDataBytes &) = delete;
90 };
91 
92 class EventDataReceipt : public EventData {
93 public:
EventDataReceipt()94   EventDataReceipt() : m_predicate(false) {}
95 
96   ~EventDataReceipt() override = default;
97 
98   static llvm::StringRef GetFlavorString();
99 
GetFlavor()100   llvm::StringRef GetFlavor() const override { return GetFlavorString(); }
101 
102   bool WaitForEventReceived(const Timeout<std::micro> &timeout = std::nullopt) {
103     return m_predicate.WaitForValueEqualTo(true, timeout);
104   }
105 
106 private:
107   Predicate<bool> m_predicate;
108 
DoOnRemoval(Event * event_ptr)109   void DoOnRemoval(Event *event_ptr) override {
110     m_predicate.SetValue(true, eBroadcastAlways);
111   }
112 };
113 
114 /// This class handles one or more StructuredData::Dictionary entries
115 /// that are raised for structured data events.
116 
117 class EventDataStructuredData : public EventData {
118 public:
119   // Constructors
120   EventDataStructuredData();
121 
122   EventDataStructuredData(const lldb::ProcessSP &process_sp,
123                           const StructuredData::ObjectSP &object_sp,
124                           const lldb::StructuredDataPluginSP &plugin_sp);
125 
126   ~EventDataStructuredData() override;
127 
128   // Member functions
129   llvm::StringRef GetFlavor() const override;
130 
131   void Dump(Stream *s) const override;
132 
133   const lldb::ProcessSP &GetProcess() const;
134 
135   const StructuredData::ObjectSP &GetObject() const;
136 
137   const lldb::StructuredDataPluginSP &GetStructuredDataPlugin() const;
138 
139   void SetProcess(const lldb::ProcessSP &process_sp);
140 
141   void SetObject(const StructuredData::ObjectSP &object_sp);
142 
143   void SetStructuredDataPlugin(const lldb::StructuredDataPluginSP &plugin_sp);
144 
145   // Static functions
146   static const EventDataStructuredData *
147   GetEventDataFromEvent(const Event *event_ptr);
148 
149   static lldb::ProcessSP GetProcessFromEvent(const Event *event_ptr);
150 
151   static StructuredData::ObjectSP GetObjectFromEvent(const Event *event_ptr);
152 
153   static lldb::StructuredDataPluginSP
154   GetPluginFromEvent(const Event *event_ptr);
155 
156   static llvm::StringRef GetFlavorString();
157 
158 private:
159   lldb::ProcessSP m_process_sp;
160   StructuredData::ObjectSP m_object_sp;
161   lldb::StructuredDataPluginSP m_plugin_sp;
162 
163   EventDataStructuredData(const EventDataStructuredData &) = delete;
164   const EventDataStructuredData &
165   operator=(const EventDataStructuredData &) = delete;
166 };
167 
168 // lldb::Event
169 class Event : public std::enable_shared_from_this<Event> {
170   friend class Listener;
171   friend class EventData;
172   friend class Broadcaster::BroadcasterImpl;
173 
174 public:
175   Event(Broadcaster *broadcaster, uint32_t event_type,
176         EventData *data = nullptr);
177 
178   Event(Broadcaster *broadcaster, uint32_t event_type,
179         const lldb::EventDataSP &event_data_sp);
180 
181   Event(uint32_t event_type, EventData *data = nullptr);
182 
183   Event(uint32_t event_type, const lldb::EventDataSP &event_data_sp);
184 
185   ~Event();
186 
187   void Dump(Stream *s) const;
188 
GetData()189   EventData *GetData() { return m_data_sp.get(); }
190 
GetData()191   const EventData *GetData() const { return m_data_sp.get(); }
192 
SetData(EventData * new_data)193   void SetData(EventData *new_data) { m_data_sp.reset(new_data); }
194 
GetType()195   uint32_t GetType() const { return m_type; }
196 
SetType(uint32_t new_type)197   void SetType(uint32_t new_type) { m_type = new_type; }
198 
GetBroadcaster()199   Broadcaster *GetBroadcaster() const {
200     Broadcaster::BroadcasterImplSP broadcaster_impl_sp =
201         m_broadcaster_wp.lock();
202     if (broadcaster_impl_sp)
203       return broadcaster_impl_sp->GetBroadcaster();
204     else
205       return nullptr;
206   }
207 
BroadcasterIs(Broadcaster * broadcaster)208   bool BroadcasterIs(Broadcaster *broadcaster) {
209     Broadcaster::BroadcasterImplSP broadcaster_impl_sp =
210         m_broadcaster_wp.lock();
211     if (broadcaster_impl_sp)
212       return broadcaster_impl_sp->GetBroadcaster() == broadcaster;
213     else
214       return false;
215   }
216 
Clear()217   void Clear() { m_data_sp.reset(); }
218 
219   /// This is used by Broadcasters with Primary Listeners to store the other
220   /// Listeners till after the Event's DoOnRemoval has completed.
AddPendingListener(lldb::ListenerSP pending_listener_sp)221   void AddPendingListener(lldb::ListenerSP pending_listener_sp) {
222     m_pending_listeners.push_back(pending_listener_sp);
223   };
224 
225 private:
226   // This is only called by Listener when it pops an event off the queue for
227   // the listener.  It calls the Event Data's DoOnRemoval() method, which is
228   // virtual and can be overridden by the specific data classes.
229 
230   void DoOnRemoval();
231 
232   // Called by Broadcaster::BroadcastEvent prior to letting all the listeners
233   // know about it update the contained broadcaster so that events can be
234   // popped off one queue and re-broadcast to others.
SetBroadcaster(Broadcaster * broadcaster)235   void SetBroadcaster(Broadcaster *broadcaster) {
236     m_broadcaster_wp = broadcaster->GetBroadcasterImpl();
237   }
238 
239   Broadcaster::BroadcasterImplWP
240       m_broadcaster_wp;        // The broadcaster that sent this event
241   uint32_t m_type;             // The bit describing this event
242   lldb::EventDataSP m_data_sp; // User specific data for this event
243   std::vector<lldb::ListenerSP> m_pending_listeners;
244   std::mutex m_listeners_mutex;
245 
246   Event(const Event &) = delete;
247   const Event &operator=(const Event &) = delete;
248   Event() = delete;
249 };
250 
251 } // namespace lldb_private
252 
253 #endif // LLDB_UTILITY_EVENT_H
254