uvw  2.1.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 
182  static std::shared_ptr<Loop> create(uv_loop_t *loop) {
183  auto ptr = std::unique_ptr<uv_loop_t, Deleter>{loop, [](uv_loop_t *){}};
184  return std::shared_ptr<Loop>{new Loop{std::move(ptr)}};
185  }
186 
199  static std::shared_ptr<Loop> getDefault() {
200  static std::weak_ptr<Loop> ref;
201  std::shared_ptr<Loop> loop;
202 
203  if(ref.expired()) {
204  auto def = uv_default_loop();
205 
206  if(def) {
207  auto ptr = std::unique_ptr<uv_loop_t, Deleter>(def, [](uv_loop_t *){});
208  loop = std::shared_ptr<Loop>{new Loop{std::move(ptr)}};
209  }
210 
211  ref = loop;
212  } else {
213  loop = ref.lock();
214  }
215 
216  return loop;
217  }
218 
219  Loop(const Loop &) = delete;
220  Loop(Loop &&other) = delete;
221  Loop & operator=(const Loop &) = delete;
222  Loop & operator=(Loop &&other) = delete;
223 
224  ~Loop() noexcept {
225  if(loop) {
226  close();
227  }
228  }
229 
246  template<typename... Args>
247  void configure(Configure flag, Args&&... args) {
248  auto option = static_cast<std::underlying_type_t<Configure>>(flag);
249  auto err = uv_loop_configure(loop.get(), static_cast<uv_loop_option>(option), std::forward<Args>(args)...);
250  if(err) { publish(ErrorEvent{err}); }
251  }
252 
263  template<typename R, typename... Args>
264  std::shared_ptr<R> resource(Args&&... args) {
265  if constexpr(std::is_base_of_v<BaseHandle, R>) {
266  auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
267  ptr = ptr->init() ? ptr : nullptr;
268  return ptr;
269  } else {
270  return R::create(shared_from_this(), std::forward<Args>(args)...);
271  }
272  }
273 
282  void close() {
283  auto err = uv_loop_close(loop.get());
284  return err ? publish(ErrorEvent{err}) : loop.reset();
285  }
286 
305  template<Mode mode = Mode::DEFAULT>
306  bool run() noexcept {
307  auto utm = static_cast<std::underlying_type_t<Mode>>(mode);
308  auto uvrm = static_cast<uv_run_mode>(utm);
309  return (uv_run(loop.get(), uvrm) == 0);
310  }
311 
316  bool alive() const noexcept {
317  return !(uv_loop_alive(loop.get()) == 0);
318  }
319 
328  void stop() noexcept {
329  uv_stop(loop.get());
330  }
331 
341  int descriptor() const noexcept {
342  return uv_backend_fd(loop.get());
343  }
344 
351  std::pair<bool, Time> timeout() const noexcept {
352  auto to = uv_backend_timeout(loop.get());
353  return std::make_pair(to == -1, Time{to});
354  }
355 
368  Time now() const noexcept {
369  return Time{uv_now(loop.get())};
370  }
371 
381  void update() const noexcept {
382  return uv_update_time(loop.get());
383  }
384 
392  void walk(std::function<void(BaseHandle &)> callback) {
393  // remember: non-capturing lambdas decay to pointers to functions
394  uv_walk(loop.get(), [](uv_handle_t *handle, void *func) {
395  BaseHandle &ref = *static_cast<BaseHandle*>(handle->data);
396  std::function<void(BaseHandle &)> &f =
397  *static_cast<std::function<void(BaseHandle &)>*>(func);
398  f(ref);
399  }, &callback);
400  }
401 
432  void fork() noexcept {
433  auto err = uv_loop_fork(loop.get());
434  if(err) { publish(ErrorEvent{err}); }
435  }
436 
441  template<typename R = void>
442  std::shared_ptr<R> data() const {
443  return std::static_pointer_cast<R>(userData);
444  }
445 
450  void data(std::shared_ptr<void> uData) {
451  userData = std::move(uData);
452  }
453 
469  const uv_loop_t * raw() const noexcept {
470  return loop.get();
471  }
472 
488  uv_loop_t * raw() noexcept {
489  return const_cast<uv_loop_t *>(const_cast<const Loop *>(this)->raw());
490  }
491 
492 private:
493  std::unique_ptr<uv_loop_t, Deleter> loop;
494  std::shared_ptr<void> userData{nullptr};
495 };
496 
497 
498 }
const uv_loop_t * raw() const noexcept
Gets the underlying raw data structure.
Definition: loop.hpp:469
Event emitter base class.
Definition: emitter.hpp:87
int descriptor() const noexcept
Get backend file descriptor.
Definition: loop.hpp:341
void fork() noexcept
Reinitialize any kernel state necessary in the child process after a fork(2) system call...
Definition: loop.hpp:432
void update() const noexcept
Updates the event loop’s concept of now.
Definition: loop.hpp:381
Time now() const noexcept
Returns the current timestamp in milliseconds.
Definition: loop.hpp:368
bool run() noexcept
Runs the event loop.
Definition: loop.hpp:306
std::shared_ptr< R > data() const
Gets user-defined data. uvw won&#39;t use this field in any case.
Definition: loop.hpp:442
static std::shared_ptr< Loop > getDefault()
Gets the initialized default loop.
Definition: loop.hpp:199
uv_loop_t * raw() noexcept
Gets the underlying raw data structure.
Definition: loop.hpp:488
std::pair< bool, Time > timeout() const noexcept
Gets the poll timeout.
Definition: loop.hpp:351
details::UVTypeWrapper< uv_handle_type > HandleCategory
Definition: util.hpp:188
void configure(Configure flag, Args &&... args)
Sets additional loop options.
Definition: loop.hpp:247
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:316
void stop() noexcept
Stops the event loop.
Definition: loop.hpp:328
void data(std::shared_ptr< void > uData)
Sets arbitrary data. uvw won&#39;t use this field in any case.
Definition: loop.hpp:450
static std::shared_ptr< Loop > create()
Initializes a new Loop instance.
Definition: loop.hpp:161
static std::shared_ptr< Loop > create(uv_loop_t *loop)
Initializes a new Loop instance from an existing resource.
Definition: loop.hpp:182
void walk(std::function< void(BaseHandle &)> callback)
Walks the list of handles.
Definition: loop.hpp:392
std::shared_ptr< R > resource(Args &&... args)
Creates resources of any type.
Definition: loop.hpp:264
void close()
Releases all internal loop resources.
Definition: loop.hpp:282
uvw default namespace.
Definition: async.hpp:11