1343181Sdim//===-- Listener.h ----------------------------------------------*- C++ -*-===//
2343181Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343181Sdim//
7343181Sdim//===----------------------------------------------------------------------===//
8343181Sdim
9343181Sdim#ifndef LLDB_UTILITY_LISTENER_H
10343181Sdim#define LLDB_UTILITY_LISTENER_H
11343181Sdim
12343181Sdim#include "lldb/Utility/Broadcaster.h"
13343181Sdim#include "lldb/Utility/Timeout.h"
14343181Sdim#include "lldb/lldb-defines.h"
15343181Sdim#include "lldb/lldb-forward.h"
16343181Sdim
17343181Sdim#include <condition_variable>
18343181Sdim#include <list>
19343181Sdim#include <map>
20343181Sdim#include <memory>
21343181Sdim#include <mutex>
22343181Sdim#include <ratio>
23343181Sdim#include <string>
24343181Sdim#include <vector>
25343181Sdim
26343181Sdim#include <stddef.h>
27343181Sdim#include <stdint.h>
28343181Sdim
29343181Sdimnamespace lldb_private {
30343181Sdimclass ConstString;
31343181Sdimclass Event;
32343181Sdim}
33343181Sdim
34343181Sdimnamespace lldb_private {
35343181Sdim
36343181Sdimclass Listener : public std::enable_shared_from_this<Listener> {
37343181Sdimpublic:
38343181Sdim  typedef bool (*HandleBroadcastCallback)(lldb::EventSP &event_sp, void *baton);
39343181Sdim
40343181Sdim  friend class Broadcaster;
41343181Sdim  friend class BroadcasterManager;
42343181Sdim
43343181Sdim  // Constructors and Destructors
44343181Sdim  //
45343181Sdim  // Listeners have to be constructed into shared pointers - at least if you
46343181Sdim  // want them to listen to Broadcasters,
47343181Sdimprotected:
48343181Sdim  Listener(const char *name);
49343181Sdim
50343181Sdimpublic:
51343181Sdim  static lldb::ListenerSP MakeListener(const char *name);
52343181Sdim
53343181Sdim  ~Listener();
54343181Sdim
55343181Sdim  void AddEvent(lldb::EventSP &event);
56343181Sdim
57343181Sdim  void Clear();
58343181Sdim
59343181Sdim  const char *GetName() { return m_name.c_str(); }
60343181Sdim
61353358Sdim  uint32_t
62353358Sdim  StartListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp,
63353358Sdim                             const BroadcastEventSpec &event_spec);
64343181Sdim
65353358Sdim  bool StopListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp,
66343181Sdim                                 const BroadcastEventSpec &event_spec);
67343181Sdim
68343181Sdim  uint32_t StartListeningForEvents(Broadcaster *broadcaster,
69343181Sdim                                   uint32_t event_mask);
70343181Sdim
71343181Sdim  uint32_t StartListeningForEvents(Broadcaster *broadcaster,
72343181Sdim                                   uint32_t event_mask,
73343181Sdim                                   HandleBroadcastCallback callback,
74343181Sdim                                   void *callback_user_data);
75343181Sdim
76343181Sdim  bool StopListeningForEvents(Broadcaster *broadcaster, uint32_t event_mask);
77343181Sdim
78343181Sdim  Event *PeekAtNextEvent();
79343181Sdim
80343181Sdim  Event *PeekAtNextEventForBroadcaster(Broadcaster *broadcaster);
81343181Sdim
82343181Sdim  Event *PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster,
83343181Sdim                                               uint32_t event_type_mask);
84343181Sdim
85343181Sdim  // Returns true if an event was received, false if we timed out.
86343181Sdim  bool GetEvent(lldb::EventSP &event_sp, const Timeout<std::micro> &timeout);
87343181Sdim
88343181Sdim  bool GetEventForBroadcaster(Broadcaster *broadcaster, lldb::EventSP &event_sp,
89343181Sdim                              const Timeout<std::micro> &timeout);
90343181Sdim
91343181Sdim  bool GetEventForBroadcasterWithType(Broadcaster *broadcaster,
92343181Sdim                                      uint32_t event_type_mask,
93343181Sdim                                      lldb::EventSP &event_sp,
94343181Sdim                                      const Timeout<std::micro> &timeout);
95343181Sdim
96343181Sdim  size_t HandleBroadcastEvent(lldb::EventSP &event_sp);
97343181Sdim
98343181Sdimprivate:
99343181Sdim  // Classes that inherit from Listener can see and modify these
100343181Sdim  struct BroadcasterInfo {
101343181Sdim    BroadcasterInfo(uint32_t mask, HandleBroadcastCallback cb = nullptr,
102343181Sdim                    void *ud = nullptr)
103343181Sdim        : event_mask(mask), callback(cb), callback_user_data(ud) {}
104343181Sdim
105343181Sdim    uint32_t event_mask;
106343181Sdim    HandleBroadcastCallback callback;
107343181Sdim    void *callback_user_data;
108343181Sdim  };
109343181Sdim
110343181Sdim  typedef std::multimap<Broadcaster::BroadcasterImplWP, BroadcasterInfo,
111343181Sdim                        std::owner_less<Broadcaster::BroadcasterImplWP>>
112343181Sdim      broadcaster_collection;
113343181Sdim  typedef std::list<lldb::EventSP> event_collection;
114343181Sdim  typedef std::vector<lldb::BroadcasterManagerWP>
115343181Sdim      broadcaster_manager_collection;
116343181Sdim
117343181Sdim  bool
118343181Sdim  FindNextEventInternal(std::unique_lock<std::mutex> &lock,
119343181Sdim                        Broadcaster *broadcaster, // nullptr for any broadcaster
120343181Sdim                        const ConstString *sources, // nullptr for any event
121343181Sdim                        uint32_t num_sources, uint32_t event_type_mask,
122343181Sdim                        lldb::EventSP &event_sp, bool remove);
123343181Sdim
124343181Sdim  bool GetEventInternal(const Timeout<std::micro> &timeout,
125343181Sdim                        Broadcaster *broadcaster, // nullptr for any broadcaster
126343181Sdim                        const ConstString *sources, // nullptr for any event
127343181Sdim                        uint32_t num_sources, uint32_t event_type_mask,
128343181Sdim                        lldb::EventSP &event_sp);
129343181Sdim
130343181Sdim  std::string m_name;
131343181Sdim  broadcaster_collection m_broadcasters;
132343181Sdim  std::recursive_mutex m_broadcasters_mutex; // Protects m_broadcasters
133343181Sdim  event_collection m_events;
134343181Sdim  std::mutex m_events_mutex; // Protects m_broadcasters and m_events
135343181Sdim  std::condition_variable m_events_condition;
136343181Sdim  broadcaster_manager_collection m_broadcaster_managers;
137343181Sdim
138343181Sdim  void BroadcasterWillDestruct(Broadcaster *);
139343181Sdim
140343181Sdim  void BroadcasterManagerWillDestruct(lldb::BroadcasterManagerSP manager_sp);
141343181Sdim
142343181Sdim  //    broadcaster_collection::iterator
143343181Sdim  //    FindBroadcasterWithMask (Broadcaster *broadcaster,
144343181Sdim  //                             uint32_t event_mask,
145343181Sdim  //                             bool exact);
146343181Sdim
147343181Sdim  // For Listener only
148343181Sdim  DISALLOW_COPY_AND_ASSIGN(Listener);
149343181Sdim};
150343181Sdim
151343181Sdim} // namespace lldb_private
152343181Sdim
153343181Sdim#endif // LLDB_UTILITY_LISTENER_H
154