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