TAMSVIZ
Visualization and annotation tool for ROS
event.h
1 // TAMSVIZ
2 // (c) 2020 Philipp Ruppel
3 
4 #pragma once
5 
6 #include <atomic>
7 #include <functional>
8 #include <list>
9 #include <memory>
10 #include <mutex>
11 #include <vector>
12 
13 class QObject;
14 template <class T> class QPointer;
15 
16 class EventBase {
17  std::string name;
18 
19 public:
20  EventBase() {}
21  EventBase(const std::string &name) : name(name) {}
22  static bool
23  listenerCheckQPointer(const std::shared_ptr<QPointer<const QObject>> &q);
24  static std::shared_ptr<QPointer<const QObject>>
25  listenerMakeQPointer(const QObject *o);
26  void begin();
27  void end();
28 };
29 
30 template <class FNC> class Event : public EventBase {
31 
32  struct Listener {
33  std::function<FNC> callback;
34  virtual bool check() const = 0;
35  template <class... ARGS> void call(const ARGS &... args) const {
36  callback(args...);
37  }
38  virtual std::shared_ptr<void> pin() { return nullptr; }
39  Listener(const std::function<FNC> &callback) : callback(callback) {}
40  virtual ~Listener() {}
41  };
42  std::list<std::shared_ptr<Listener>> listeners;
43 
44  struct Listener0 : Listener {
45  bool check() const override { return true; }
46  Listener0(const std::function<FNC> &callback) : Listener(callback) {}
47  };
48 
49  template <class T> struct ListenerP : Listener {
50  std::weak_ptr<T> instance;
51  ListenerP(const std::shared_ptr<T> &instance,
52  const std::function<FNC> &callback)
53  : Listener(callback), instance(instance) {}
54  bool check() const override {
55  std::shared_ptr<T> ptr = instance.lock();
56  return ptr != nullptr;
57  }
58  virtual std::shared_ptr<void> pin() { return instance.lock(); }
59  };
60 
61  struct ListenerQ : Listener {
62  std::shared_ptr<QPointer<const QObject>> instance;
63  ListenerQ(const std::shared_ptr<QPointer<const QObject>> &instance,
64  const std::function<FNC> &callback)
65  : Listener(callback), instance(instance) {}
66  bool check() const override {
67  return EventBase::listenerCheckQPointer(instance);
68  }
69  };
70 
71  std::mutex mutex;
72 
73 public:
74  Event() {}
75  Event(const std::string &name) : EventBase(name) {}
76 
77  void clear() {
78  std::lock_guard<std::mutex> lock(mutex);
79  listeners.clear();
80  }
81 
82  void connect(const std::function<FNC> &callback) {
83  std::lock_guard<std::mutex> lock(mutex);
84  listeners.push_back(std::make_shared<Listener0>(callback));
85  }
86 
87  template <class T>
88  void connect(const std::shared_ptr<T> &instance,
89  const std::function<FNC> &callback) {
90  std::lock_guard<std::mutex> lock(mutex);
91  listeners.push_back(std::make_shared<ListenerP<T>>(instance, callback));
92  }
93 
94  void connect(const QObject *obj, const std::function<FNC> &callback) {
95  std::lock_guard<std::mutex> lock(mutex);
96  listeners.push_back(
97  std::make_shared<ListenerQ>(listenerMakeQPointer(obj), callback));
98  }
99 
100  template <class... ARGS> void operator()(const ARGS &... args) {
101  begin();
102  std::vector<std::shared_ptr<Listener>> ll;
103  {
104  std::lock_guard<std::mutex> lock(mutex);
105  ll.reserve(listeners.size());
106  for (auto it = listeners.begin(); it != listeners.end();) {
107  if ((*it)->check()) {
108  ll.push_back(*it);
109  it++;
110  } else {
111  it = listeners.erase(it);
112  }
113  }
114  }
115  for (auto &l : ll) {
116  auto ptr = l->pin();
117  if (l->check()) {
118  l->call(args...);
119  }
120  }
121  end();
122  }
123 };
124 
125 class EventFlag {
126  struct Data {
127  std::atomic<int> value;
128  Data() { value = 0; }
129  };
130  std::shared_ptr<Data> _data = std::make_shared<Data>();
131 
132 public:
133  EventFlag(Event<void()> &event) {
134  Data *ptr = _data.get();
135  event.connect(_data, [ptr]() { ptr->value = 1; });
136  }
137  bool poll() { return _data->value.exchange(0); }
138 };
Definition: event.h:14
Definition: event.h:30