uvw  2.0.0
loop.hpp
1 #pragma once
2 
3 
4 #ifdef _WIN32
5 #include <ciso646>
6 #endif
7 
8 #include <functional>
9 #include <memory>
10 #include <utility>
11 #include <type_traits>
12 #include <chrono>
13 #include <uv.h>
14 #include "emitter.hpp"
15 #include "util.hpp"
16 
17 
18 namespace uvw {
19 
20 
21 namespace details {
22 
23 
24 enum class UVLoopOption: std::underlying_type_t<uv_loop_option> {
25  BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL
26 };
27 
28 
29 enum class UVRunMode: std::underlying_type_t<uv_run_mode> {
30  DEFAULT = UV_RUN_DEFAULT,
31  ONCE = UV_RUN_ONCE,
32  NOWAIT = UV_RUN_NOWAIT
33 };
34 
35 
36 }
37 
38 
47 struct BaseHandle {
57  virtual HandleCategory category() const noexcept = 0;
58 
68  virtual HandleType type() const noexcept = 0;
69 
89  virtual bool active() const noexcept = 0;
90 
99  virtual bool closing() const noexcept = 0;
100 
107  virtual void reference() noexcept = 0;
108 
115  virtual void unreference() noexcept = 0;
116 
121  virtual bool referenced() const noexcept = 0;
122 
130  virtual void close() noexcept = 0;
131 };
132 
133 
142 class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
143  using Deleter = void(*)(uv_loop_t *);
144 
145  template<typename, typename>
146  friend class Resource;
147 
148  Loop(std::unique_ptr<uv_loop_t, Deleter> ptr) noexcept
149  : loop{std::move(ptr)}
150  {}
151 
152 public:
153  using Time = std::chrono::duration<uint64_t, std::milli>;
154  using Configure = details::UVLoopOption;
155  using Mode = details::UVRunMode;
156 
161  static std::shared_ptr<Loop> create() {
162  auto ptr = std::unique_ptr<uv_loop_t, Deleter>{new uv_loop_t, [](uv_loop_t *l){ delete l; }};
163  auto loop = std::shared_ptr<Loop>{new Loop{std::move(ptr)}};
164 
165  if(uv_loop_init(loop->loop.get())) {
166  loop = nullptr;
167  }
168 
169  return loop;
170  }
171 
184  static std::shared_ptr<Loop> getDefault() {
185  static std::weak_ptr<Loop> ref;
186  std::shared_ptr<Loop> loop;
187 
188  if(ref.expired()) {
189  auto def = uv_default_loop();
190 
191  if(def) {
192  auto ptr = std::unique_ptr<uv_loop_t, Deleter>(def, [](uv_loop_t *){});
193  loop = std::shared_ptr<Loop>{new Loop{std::move(ptr)}};
194  }
195 
196  ref = loop;
197  } else {
198  loop = ref.lock();
199  }
200 
201  return loop;
202  }
203 
204  Loop(const Loop &) = delete;
205  Loop(Loop &&other) = delete;
206  Loop & operator=(const Loop &) = delete;
207  Loop & operator=(Loop &&other) = delete;
208 
209  ~Loop() noexcept {
210  if(loop) {
211  close();
212  }
213  }
214 
231  template<typename... Args>
232  void configure(Configure flag, Args&&... args) {
233  auto option = static_cast<std::underlying_type_t<Configure>>(flag);
234  auto err = uv_loop_configure(loop.get(), static_cast<uv_loop_option>(option), std::forward<Args>(args)...);
235  if(err) { publish(ErrorEvent{err}); }
236  }
237 
248  template<typename R, typename... Args>
249  std::shared_ptr<R> resource(Args&&... args) {
250  if constexpr(std::is_base_of_v<BaseHandle, R>) {
251  auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
252  ptr = ptr->init() ? ptr : nullptr;
253  return ptr;
254  } else {
255  return R::create(shared_from_this(), std::forward<Args>(args)...);
256  }
257  }
258 
267  void close() {
268  auto err = uv_loop_close(loop.get());
269  return err ? publish(ErrorEvent{err}) : loop.reset();
270  }
271 
290  template<Mode mode = Mode::DEFAULT>
291  bool run() noexcept {
292  auto utm = static_cast<std::underlying_type_t<Mode>>(mode);
293  auto uvrm = static_cast<uv_run_mode>(utm);
294  return (uv_run(loop.get(), uvrm) == 0);
295  }
296 
301  bool alive() const noexcept {
302  return !(uv_loop_alive(loop.get()) == 0);
303  }
304 
313  void stop() noexcept {
314  uv_stop(loop.get());
315  }
316 
326  int descriptor() const noexcept {
327  return uv_backend_fd(loop.get());
328  }
329 
336  std::pair<bool, Time> timeout() const noexcept {
337  auto to = uv_backend_timeout(loop.get());
338  return std::make_pair(to == -1, Time{to});
339  }
340 
353  Time now() const noexcept {
354  return Time{uv_now(loop.get())};
355  }
356 
366  void update() const noexcept {
367  return uv_update_time(loop.get());
368  }
369 
377  void walk(std::function<void(BaseHandle &)> callback) {
378  // remember: non-capturing lambdas decay to pointers to functions
379  uv_walk(loop.get(), [](uv_handle_t *handle, void *func) {
380  BaseHandle &ref = *static_cast<BaseHandle*>(handle->data);
381  std::function<void(BaseHandle &)> &f =
382  *static_cast<std::function<void(BaseHandle &)>*>(func);
383  f(ref);
384  }, &callback);
385  }
386 
417  void fork() noexcept {
418  auto err = uv_loop_fork(loop.get());
419  if(err) { publish(ErrorEvent{err}); }
420  }
421 
426  template<typename R = void>
427  std::shared_ptr<R> data() const {
428  return std::static_pointer_cast<R>(userData);
429  }
430 
435  void data(std::shared_ptr<void> uData) {
436  userData = std::move(uData);
437  }
438 
454  const uv_loop_t * raw() const noexcept {
455  return loop.get();
456  }
457 
473  uv_loop_t * raw() noexcept {
474  return const_cast<uv_loop_t *>(const_cast<const Loop *>(this)->raw());
475  }
476 
477 private:
478  std::unique_ptr<uv_loop_t, Deleter> loop;
479  std::shared_ptr<void> userData{nullptr};
480 };
481 
482 
483 }
const uv_loop_t * raw() const noexcept
Gets the underlying raw data structure.
Definition: loop.hpp:454
Event emitter base class.
Definition: emitter.hpp:87
int descriptor() const noexcept
Get backend file descriptor.
Definition: loop.hpp:326
void fork() noexcept
Reinitialize any kernel state necessary in the child process after a fork(2) system call...
Definition: loop.hpp:417
void update() const noexcept
Updates the event loop’s concept of now.
Definition: loop.hpp:366
Time now() const noexcept
Returns the current timestamp in milliseconds.
Definition: loop.hpp:353
bool run() noexcept
Runs the event loop.
Definition: loop.hpp:291
std::shared_ptr< R > data() const
Gets user-defined data. uvw won&#39;t use this field in any case.
Definition: loop.hpp:427
static std::shared_ptr< Loop > getDefault()
Gets the initialized default loop.
Definition: loop.hpp:184
uv_loop_t * raw() noexcept
Gets the underlying raw data structure.
Definition: loop.hpp:473
std::pair< bool, Time > timeout() const noexcept
Gets the poll timeout.
Definition: loop.hpp:336
details::UVTypeWrapper< uv_handle_type > HandleCategory
Definition: util.hpp:188
void configure(Configure flag, Args &&... args)
Sets additional loop options.
Definition: loop.hpp:232
The ErrorEvent event.
Definition: emitter.hpp:23
The Loop class.
Definition: loop.hpp:142
Common class for almost all the resources available in uvw.
Definition: resource.hpp:19
Untyped handle class.
Definition: loop.hpp:47
bool alive() const noexcept
Checks if there are active resources.
Definition: loop.hpp:301
void stop() noexcept
Stops the event loop.
Definition: loop.hpp:313
void data(std::shared_ptr< void > uData)
Sets arbitrary data. uvw won&#39;t use this field in any case.
Definition: loop.hpp:435
static std::shared_ptr< Loop > create()
Initializes a new Loop instance.
Definition: loop.hpp:161
void walk(std::function< void(BaseHandle &)> callback)
Walks the list of handles.
Definition: loop.hpp:377
std::shared_ptr< R > resource(Args &&... args)
Creates resources of any type.
Definition: loop.hpp:249
void close()
Releases all internal loop resources.
Definition: loop.hpp:267
uvw default namespace.
Definition: async.hpp:11