1//===-- SBListener.cpp ------------------------------------------*- 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#include "lldb/API/SBListener.h"
10#include "SBReproducerPrivate.h"
11#include "lldb/API/SBBroadcaster.h"
12#include "lldb/API/SBDebugger.h"
13#include "lldb/API/SBEvent.h"
14#include "lldb/API/SBStream.h"
15#include "lldb/Core/Debugger.h"
16#include "lldb/Utility/Broadcaster.h"
17#include "lldb/Utility/Listener.h"
18#include "lldb/Utility/StreamString.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23SBListener::SBListener() : m_opaque_sp(), m_unused_ptr(nullptr) {
24  LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBListener);
25}
26
27SBListener::SBListener(const char *name)
28    : m_opaque_sp(Listener::MakeListener(name)), m_unused_ptr(nullptr) {
29  LLDB_RECORD_CONSTRUCTOR(SBListener, (const char *), name);
30}
31
32SBListener::SBListener(const SBListener &rhs)
33    : m_opaque_sp(rhs.m_opaque_sp), m_unused_ptr(nullptr) {
34  LLDB_RECORD_CONSTRUCTOR(SBListener, (const lldb::SBListener &), rhs);
35}
36
37const lldb::SBListener &SBListener::operator=(const lldb::SBListener &rhs) {
38  LLDB_RECORD_METHOD(const lldb::SBListener &,
39                     SBListener, operator=,(const lldb::SBListener &), rhs);
40
41  if (this != &rhs) {
42    m_opaque_sp = rhs.m_opaque_sp;
43    m_unused_ptr = nullptr;
44  }
45  return LLDB_RECORD_RESULT(*this);
46}
47
48SBListener::SBListener(const lldb::ListenerSP &listener_sp)
49    : m_opaque_sp(listener_sp), m_unused_ptr(nullptr) {}
50
51SBListener::~SBListener() {}
52
53bool SBListener::IsValid() const {
54  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBListener, IsValid);
55  return this->operator bool();
56}
57SBListener::operator bool() const {
58  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBListener, operator bool);
59
60  return m_opaque_sp != nullptr;
61}
62
63void SBListener::AddEvent(const SBEvent &event) {
64  LLDB_RECORD_METHOD(void, SBListener, AddEvent, (const lldb::SBEvent &),
65                     event);
66
67  EventSP &event_sp = event.GetSP();
68  if (event_sp)
69    m_opaque_sp->AddEvent(event_sp);
70}
71
72void SBListener::Clear() {
73  LLDB_RECORD_METHOD_NO_ARGS(void, SBListener, Clear);
74
75  if (m_opaque_sp)
76    m_opaque_sp->Clear();
77}
78
79uint32_t SBListener::StartListeningForEventClass(SBDebugger &debugger,
80                                                 const char *broadcaster_class,
81                                                 uint32_t event_mask) {
82  LLDB_RECORD_METHOD(uint32_t, SBListener, StartListeningForEventClass,
83                     (lldb::SBDebugger &, const char *, uint32_t), debugger,
84                     broadcaster_class, event_mask);
85
86  if (m_opaque_sp) {
87    Debugger *lldb_debugger = debugger.get();
88    if (!lldb_debugger)
89      return 0;
90    BroadcastEventSpec event_spec(ConstString(broadcaster_class), event_mask);
91    return m_opaque_sp->StartListeningForEventSpec(
92        lldb_debugger->GetBroadcasterManager(), event_spec);
93  } else
94    return 0;
95}
96
97bool SBListener::StopListeningForEventClass(SBDebugger &debugger,
98                                            const char *broadcaster_class,
99                                            uint32_t event_mask) {
100  LLDB_RECORD_METHOD(bool, SBListener, StopListeningForEventClass,
101                     (lldb::SBDebugger &, const char *, uint32_t), debugger,
102                     broadcaster_class, event_mask);
103
104  if (m_opaque_sp) {
105    Debugger *lldb_debugger = debugger.get();
106    if (!lldb_debugger)
107      return false;
108    BroadcastEventSpec event_spec(ConstString(broadcaster_class), event_mask);
109    return m_opaque_sp->StopListeningForEventSpec(
110        lldb_debugger->GetBroadcasterManager(), event_spec);
111  } else
112    return false;
113}
114
115uint32_t SBListener::StartListeningForEvents(const SBBroadcaster &broadcaster,
116                                             uint32_t event_mask) {
117  LLDB_RECORD_METHOD(uint32_t, SBListener, StartListeningForEvents,
118                     (const lldb::SBBroadcaster &, uint32_t), broadcaster,
119                     event_mask);
120
121  uint32_t acquired_event_mask = 0;
122  if (m_opaque_sp && broadcaster.IsValid()) {
123    acquired_event_mask =
124        m_opaque_sp->StartListeningForEvents(broadcaster.get(), event_mask);
125  }
126
127  return acquired_event_mask;
128}
129
130bool SBListener::StopListeningForEvents(const SBBroadcaster &broadcaster,
131                                        uint32_t event_mask) {
132  LLDB_RECORD_METHOD(bool, SBListener, StopListeningForEvents,
133                     (const lldb::SBBroadcaster &, uint32_t), broadcaster,
134                     event_mask);
135
136  if (m_opaque_sp && broadcaster.IsValid()) {
137    return m_opaque_sp->StopListeningForEvents(broadcaster.get(), event_mask);
138  }
139  return false;
140}
141
142bool SBListener::WaitForEvent(uint32_t timeout_secs, SBEvent &event) {
143  LLDB_RECORD_METHOD(bool, SBListener, WaitForEvent,
144                     (uint32_t, lldb::SBEvent &), timeout_secs, event);
145
146  bool success = false;
147
148  if (m_opaque_sp) {
149    Timeout<std::micro> timeout(llvm::None);
150    if (timeout_secs != UINT32_MAX) {
151      assert(timeout_secs != 0); // Take this out after all calls with timeout
152                                 // set to zero have been removed....
153      timeout = std::chrono::seconds(timeout_secs);
154    }
155    EventSP event_sp;
156    if (m_opaque_sp->GetEvent(event_sp, timeout)) {
157      event.reset(event_sp);
158      success = true;
159    }
160  }
161
162  if (!success)
163    event.reset(nullptr);
164  return success;
165}
166
167bool SBListener::WaitForEventForBroadcaster(uint32_t num_seconds,
168                                            const SBBroadcaster &broadcaster,
169                                            SBEvent &event) {
170  LLDB_RECORD_METHOD(bool, SBListener, WaitForEventForBroadcaster,
171                     (uint32_t, const lldb::SBBroadcaster &, lldb::SBEvent &),
172                     num_seconds, broadcaster, event);
173
174  if (m_opaque_sp && broadcaster.IsValid()) {
175    Timeout<std::micro> timeout(llvm::None);
176    if (num_seconds != UINT32_MAX)
177      timeout = std::chrono::seconds(num_seconds);
178    EventSP event_sp;
179    if (m_opaque_sp->GetEventForBroadcaster(broadcaster.get(), event_sp,
180                                            timeout)) {
181      event.reset(event_sp);
182      return true;
183    }
184  }
185  event.reset(nullptr);
186  return false;
187}
188
189bool SBListener::WaitForEventForBroadcasterWithType(
190    uint32_t num_seconds, const SBBroadcaster &broadcaster,
191    uint32_t event_type_mask, SBEvent &event) {
192  LLDB_RECORD_METHOD(
193      bool, SBListener, WaitForEventForBroadcasterWithType,
194      (uint32_t, const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &),
195      num_seconds, broadcaster, event_type_mask, event);
196
197  if (m_opaque_sp && broadcaster.IsValid()) {
198    Timeout<std::micro> timeout(llvm::None);
199    if (num_seconds != UINT32_MAX)
200      timeout = std::chrono::seconds(num_seconds);
201    EventSP event_sp;
202    if (m_opaque_sp->GetEventForBroadcasterWithType(
203            broadcaster.get(), event_type_mask, event_sp, timeout)) {
204      event.reset(event_sp);
205      return true;
206    }
207  }
208  event.reset(nullptr);
209  return false;
210}
211
212bool SBListener::PeekAtNextEvent(SBEvent &event) {
213  LLDB_RECORD_METHOD(bool, SBListener, PeekAtNextEvent, (lldb::SBEvent &),
214                     event);
215
216  if (m_opaque_sp) {
217    event.reset(m_opaque_sp->PeekAtNextEvent());
218    return event.IsValid();
219  }
220  event.reset(nullptr);
221  return false;
222}
223
224bool SBListener::PeekAtNextEventForBroadcaster(const SBBroadcaster &broadcaster,
225                                               SBEvent &event) {
226  LLDB_RECORD_METHOD(bool, SBListener, PeekAtNextEventForBroadcaster,
227                     (const lldb::SBBroadcaster &, lldb::SBEvent &),
228                     broadcaster, event);
229
230  if (m_opaque_sp && broadcaster.IsValid()) {
231    event.reset(m_opaque_sp->PeekAtNextEventForBroadcaster(broadcaster.get()));
232    return event.IsValid();
233  }
234  event.reset(nullptr);
235  return false;
236}
237
238bool SBListener::PeekAtNextEventForBroadcasterWithType(
239    const SBBroadcaster &broadcaster, uint32_t event_type_mask,
240    SBEvent &event) {
241  LLDB_RECORD_METHOD(bool, SBListener, PeekAtNextEventForBroadcasterWithType,
242                     (const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &),
243                     broadcaster, event_type_mask, event);
244
245  if (m_opaque_sp && broadcaster.IsValid()) {
246    event.reset(m_opaque_sp->PeekAtNextEventForBroadcasterWithType(
247        broadcaster.get(), event_type_mask));
248    return event.IsValid();
249  }
250  event.reset(nullptr);
251  return false;
252}
253
254bool SBListener::GetNextEvent(SBEvent &event) {
255  LLDB_RECORD_METHOD(bool, SBListener, GetNextEvent, (lldb::SBEvent &), event);
256
257  if (m_opaque_sp) {
258    EventSP event_sp;
259    if (m_opaque_sp->GetEvent(event_sp, std::chrono::seconds(0))) {
260      event.reset(event_sp);
261      return true;
262    }
263  }
264  event.reset(nullptr);
265  return false;
266}
267
268bool SBListener::GetNextEventForBroadcaster(const SBBroadcaster &broadcaster,
269                                            SBEvent &event) {
270  LLDB_RECORD_METHOD(bool, SBListener, GetNextEventForBroadcaster,
271                     (const lldb::SBBroadcaster &, lldb::SBEvent &),
272                     broadcaster, event);
273
274  if (m_opaque_sp && broadcaster.IsValid()) {
275    EventSP event_sp;
276    if (m_opaque_sp->GetEventForBroadcaster(broadcaster.get(), event_sp,
277                                            std::chrono::seconds(0))) {
278      event.reset(event_sp);
279      return true;
280    }
281  }
282  event.reset(nullptr);
283  return false;
284}
285
286bool SBListener::GetNextEventForBroadcasterWithType(
287    const SBBroadcaster &broadcaster, uint32_t event_type_mask,
288    SBEvent &event) {
289  LLDB_RECORD_METHOD(bool, SBListener, GetNextEventForBroadcasterWithType,
290                     (const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &),
291                     broadcaster, event_type_mask, event);
292
293  if (m_opaque_sp && broadcaster.IsValid()) {
294    EventSP event_sp;
295    if (m_opaque_sp->GetEventForBroadcasterWithType(broadcaster.get(),
296                                                    event_type_mask, event_sp,
297                                                    std::chrono::seconds(0))) {
298      event.reset(event_sp);
299      return true;
300    }
301  }
302  event.reset(nullptr);
303  return false;
304}
305
306bool SBListener::HandleBroadcastEvent(const SBEvent &event) {
307  LLDB_RECORD_METHOD(bool, SBListener, HandleBroadcastEvent,
308                     (const lldb::SBEvent &), event);
309
310  if (m_opaque_sp)
311    return m_opaque_sp->HandleBroadcastEvent(event.GetSP());
312  return false;
313}
314
315lldb::ListenerSP SBListener::GetSP() { return m_opaque_sp; }
316
317Listener *SBListener::operator->() const { return m_opaque_sp.get(); }
318
319Listener *SBListener::get() const { return m_opaque_sp.get(); }
320
321void SBListener::reset(ListenerSP listener_sp) {
322  m_opaque_sp = listener_sp;
323  m_unused_ptr = nullptr;
324}
325
326namespace lldb_private {
327namespace repro {
328
329template <>
330void RegisterMethods<SBListener>(Registry &R) {
331  LLDB_REGISTER_CONSTRUCTOR(SBListener, ());
332  LLDB_REGISTER_CONSTRUCTOR(SBListener, (const char *));
333  LLDB_REGISTER_CONSTRUCTOR(SBListener, (const lldb::SBListener &));
334  LLDB_REGISTER_METHOD(const lldb::SBListener &,
335                       SBListener, operator=,(const lldb::SBListener &));
336  LLDB_REGISTER_METHOD_CONST(bool, SBListener, IsValid, ());
337  LLDB_REGISTER_METHOD_CONST(bool, SBListener, operator bool, ());
338  LLDB_REGISTER_METHOD(void, SBListener, AddEvent, (const lldb::SBEvent &));
339  LLDB_REGISTER_METHOD(void, SBListener, Clear, ());
340  LLDB_REGISTER_METHOD(uint32_t, SBListener, StartListeningForEventClass,
341                       (lldb::SBDebugger &, const char *, uint32_t));
342  LLDB_REGISTER_METHOD(bool, SBListener, StopListeningForEventClass,
343                       (lldb::SBDebugger &, const char *, uint32_t));
344  LLDB_REGISTER_METHOD(uint32_t, SBListener, StartListeningForEvents,
345                       (const lldb::SBBroadcaster &, uint32_t));
346  LLDB_REGISTER_METHOD(bool, SBListener, StopListeningForEvents,
347                       (const lldb::SBBroadcaster &, uint32_t));
348  LLDB_REGISTER_METHOD(bool, SBListener, WaitForEvent,
349                       (uint32_t, lldb::SBEvent &));
350  LLDB_REGISTER_METHOD(
351      bool, SBListener, WaitForEventForBroadcaster,
352      (uint32_t, const lldb::SBBroadcaster &, lldb::SBEvent &));
353  LLDB_REGISTER_METHOD(
354      bool, SBListener, WaitForEventForBroadcasterWithType,
355      (uint32_t, const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &));
356  LLDB_REGISTER_METHOD(bool, SBListener, PeekAtNextEvent, (lldb::SBEvent &));
357  LLDB_REGISTER_METHOD(bool, SBListener, PeekAtNextEventForBroadcaster,
358                       (const lldb::SBBroadcaster &, lldb::SBEvent &));
359  LLDB_REGISTER_METHOD(
360      bool, SBListener, PeekAtNextEventForBroadcasterWithType,
361      (const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &));
362  LLDB_REGISTER_METHOD(bool, SBListener, GetNextEvent, (lldb::SBEvent &));
363  LLDB_REGISTER_METHOD(bool, SBListener, GetNextEventForBroadcaster,
364                       (const lldb::SBBroadcaster &, lldb::SBEvent &));
365  LLDB_REGISTER_METHOD(
366      bool, SBListener, GetNextEventForBroadcasterWithType,
367      (const lldb::SBBroadcaster &, uint32_t, lldb::SBEvent &));
368  LLDB_REGISTER_METHOD(bool, SBListener, HandleBroadcastEvent,
369                       (const lldb::SBEvent &));
370}
371
372}
373}
374