uvw  2.6.0
emitter.h
1 #ifndef UVW_EMITTER_INCLUDE_H
2 #define UVW_EMITTER_INCLUDE_H
3 
4 
5 #include <type_traits>
6 #include <functional>
7 #include <algorithm>
8 #include <utility>
9 #include <cstddef>
10 #include <vector>
11 #include <memory>
12 #include <list>
13 #include <uv.h>
14 
15 
16 namespace uvw {
17 
18 
24 struct ErrorEvent {
25  template<typename U, typename = std::enable_if_t<std::is_integral_v<U>>>
26  explicit ErrorEvent(U val) noexcept
27  : ec{static_cast<int>(val)}
28  {}
29 
42  static int translate(int sys) noexcept;
43 
51  const char * what() const noexcept;
52 
60  const char * name() const noexcept;
61 
66  int code() const noexcept;
67 
72  explicit operator bool() const noexcept;
73 
74 private:
75  const int ec;
76 };
77 
78 
85 template<typename T>
86 class Emitter {
87  struct BaseHandler {
88  virtual ~BaseHandler() noexcept = default;
89  virtual bool empty() const noexcept = 0;
90  virtual void clear() noexcept = 0;
91  };
92 
93  template<typename E>
94  struct Handler final: BaseHandler {
95  using Listener = std::function<void(E &, T &)>;
96  using Element = std::pair<bool, Listener>;
97  using ListenerList = std::list<Element>;
98  using Connection = typename ListenerList::iterator;
99 
100  bool empty() const noexcept override {
101  auto pred = [](auto &&element){ return element.first; };
102 
103  return std::all_of(onceL.cbegin(), onceL.cend(), pred) &&
104  std::all_of(onL.cbegin(), onL.cend(), pred);
105  }
106 
107  void clear() noexcept override {
108  if(publishing) {
109  auto func = [](auto &&element){ element.first = true; };
110  std::for_each(onceL.begin(), onceL.end(), func);
111  std::for_each(onL.begin(), onL.end(), func);
112  } else {
113  onceL.clear();
114  onL.clear();
115  }
116  }
117 
118  Connection once(Listener f) {
119  return onceL.emplace(onceL.cend(), false, std::move(f));
120  }
121 
122  Connection on(Listener f) {
123  return onL.emplace(onL.cend(), false, std::move(f));
124  }
125 
126  void erase(Connection conn) noexcept {
127  conn->first = true;
128 
129  if(!publishing) {
130  auto pred = [](auto &&element){ return element.first; };
131  onceL.remove_if(pred);
132  onL.remove_if(pred);
133  }
134  }
135 
136  void publish(E event, T &ref) {
137  ListenerList currentL;
138  onceL.swap(currentL);
139 
140  auto func = [&event, &ref](auto &&element) {
141  return element.first ? void() : element.second(event, ref);
142  };
143 
144  publishing = true;
145 
146  std::for_each(onL.rbegin(), onL.rend(), func);
147  std::for_each(currentL.rbegin(), currentL.rend(), func);
148 
149  publishing = false;
150 
151  onL.remove_if([](auto &&element){ return element.first; });
152  }
153 
154  private:
155  bool publishing{false};
156  ListenerList onceL{};
157  ListenerList onL{};
158  };
159 
160  static std::size_t next_type() noexcept {
161  static std::size_t counter = 0;
162  return counter++;
163  }
164 
165  template<typename>
166  static std::size_t event_type() noexcept {
167  static std::size_t value = next_type();
168  return value;
169  }
170 
171  template<typename E>
172  Handler<E> & handler() noexcept {
173  std::size_t type = event_type<E>();
174 
175  if(!(type < handlers.size())) {
176  handlers.resize(type+1);
177  }
178 
179  if(!handlers[type]) {
180  handlers[type] = std::make_unique<Handler<E>>();
181  }
182 
183  return static_cast<Handler<E>&>(*handlers[type]);
184  }
185 
186 protected:
187  template<typename E>
188  void publish(E event) {
189  handler<E>().publish(std::move(event), *static_cast<T*>(this));
190  }
191 
192 public:
193  template<typename E>
194  using Listener = typename Handler<E>::Listener;
195 
203  template<typename E>
204  struct Connection: private Handler<E>::Connection {
205  template<typename> friend class Emitter;
206 
207  Connection() = default;
208  Connection(const Connection &) = default;
209  Connection(Connection &&) = default;
210 
211  Connection(typename Handler<E>::Connection conn)
212  : Handler<E>::Connection{std::move(conn)}
213  {}
214 
215  Connection & operator=(const Connection &) = default;
216  Connection & operator=(Connection &&) = default;
217  };
218 
219  virtual ~Emitter() noexcept {
220  static_assert(std::is_base_of_v<Emitter<T>, T>);
221  }
222 
238  template<typename E>
239  Connection<E> on(Listener<E> f) {
240  return handler<E>().on(std::move(f));
241  }
242 
258  template<typename E>
259  Connection<E> once(Listener<E> f) {
260  return handler<E>().once(std::move(f));
261  }
262 
267  template<typename E>
268  void erase(Connection<E> conn) noexcept {
269  handler<E>().erase(std::move(conn));
270  }
271 
275  template<typename E>
276  void clear() noexcept {
277  handler<E>().clear();
278  }
279 
283  void clear() noexcept {
284  std::for_each(handlers.begin(), handlers.end(),
285  [](auto &&hdlr){ if(hdlr) { hdlr->clear(); } });
286  }
287 
293  template<typename E>
294  bool empty() const noexcept {
295  std::size_t type = event_type<E>();
296 
297  return (!(type < handlers.size()) ||
298  !handlers[type] ||
299  static_cast<Handler<E>&>(*handlers[type]).empty());
300  }
301 
307  bool empty() const noexcept {
308  return std::all_of(handlers.cbegin(), handlers.cend(),
309  [](auto &&hdlr){ return !hdlr || hdlr->empty(); });
310  }
311 
312 private:
313  std::vector<std::unique_ptr<BaseHandler>> handlers{};
314 };
315 
316 
317 }
318 
319 
320 #ifndef UVW_AS_LIB
321 #include "emitter.cpp"
322 #endif
323 
324 #endif // UVW_EMITTER_INCLUDE_H
uvw::Emitter::Connection
Connection type for a given event type.
Definition: emitter.h:204
uvw
uvw default namespace.
Definition: async.h:10
uvw::ErrorEvent::translate
static int translate(int sys) noexcept
Returns the libuv error code equivalent to the given platform dependent error code.
uvw::ErrorEvent
The ErrorEvent event.
Definition: emitter.h:24
uvw::Emitter::on
Connection< E > on(Listener< E > f)
Registers a long-lived listener with the event emitter.
Definition: emitter.h:239
uvw::ErrorEvent::name
const char * name() const noexcept
Returns the error name for the given error code.
uvw::Emitter::empty
bool empty() const noexcept
Checks if there are listeners registered for the specific event.
Definition: emitter.h:294
uvw::Emitter
Event emitter base class.
Definition: emitter.h:86
uvw::Emitter::once
Connection< E > once(Listener< E > f)
Registers a short-lived listener with the event emitter.
Definition: emitter.h:259
uvw::Emitter::clear
void clear() noexcept
Disconnects all the listeners for the given event type.
Definition: emitter.h:276
uvw::Emitter::erase
void erase(Connection< E > conn) noexcept
Disconnects a listener from the event emitter.
Definition: emitter.h:268
uvw::ErrorEvent::code
int code() const noexcept
Gets the underlying error code, that is an error constant of libuv.
uvw::Emitter::empty
bool empty() const noexcept
Checks if there are listeners registered with the event emitter.
Definition: emitter.h:307
uvw::ErrorEvent::what
const char * what() const noexcept
Returns the error message for the given error code.
uvw::Emitter::clear
void clear() noexcept
Disconnects all the listeners.
Definition: emitter.h:283