uvw  1.4.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::enable_if_t<std::is_base_of<BaseHandle, R>::value, std::shared_ptr<R>>
250  resource(Args&&... args) {
251  auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
252  ptr = ptr->init() ? ptr : nullptr;
253  return ptr;
254  }
255 
266  template<typename R, typename... Args>
267  std::enable_if_t<not std::is_base_of<BaseHandle, R>::value, std::shared_ptr<R>>
268  resource(Args&&... args) {
269  return R::create(shared_from_this(), std::forward<Args>(args)...);
270  }
271 
280  void close() {
281  auto err = uv_loop_close(loop.get());
282  if(err) { publish(ErrorEvent{err}); }
283  }
284 
303  template<Mode mode = Mode::DEFAULT>
304  bool run() noexcept {
305  auto utm = static_cast<std::underlying_type_t<Mode>>(mode);
306  auto uvrm = static_cast<uv_run_mode>(utm);
307  return (uv_run(loop.get(), uvrm) == 0);
308  }
309 
314  bool alive() const noexcept {
315  return !(uv_loop_alive(loop.get()) == 0);
316  }
317 
326  void stop() noexcept {
327  uv_stop(loop.get());
328  }
329 
339  int descriptor() const noexcept {
340  return uv_backend_fd(loop.get());
341  }
342 
349  std::pair<bool, Time> timeout() const noexcept {
350  auto to = uv_backend_timeout(loop.get());
351  return std::make_pair(to == -1, Time{to});
352  }
353 
366  Time now() const noexcept {
367  return Time{uv_now(loop.get())};
368  }
369 
379  void update() const noexcept {
380  return uv_update_time(loop.get());
381  }
382 
390  void walk(std::function<void(BaseHandle &)> callback) {
391  // remember: non-capturing lambdas decay to pointers to functions
392  uv_walk(loop.get(), [](uv_handle_t *handle, void *func) {
393  BaseHandle &ref = *static_cast<BaseHandle*>(handle->data);
394  std::function<void(BaseHandle &)> &f =
395  *static_cast<std::function<void(BaseHandle &)>*>(func);
396  f(ref);
397  }, &callback);
398  }
399 
430  void fork() noexcept {
431  auto err = uv_loop_fork(loop.get());
432  if(err) { publish(ErrorEvent{err}); }
433  }
434 
435 private:
436  std::unique_ptr<uv_loop_t, Deleter> loop;
437 };
438 
439 
440 }
std::enable_if_t< std::is_base_of< BaseHandle, R >::value, std::shared_ptr< R > > resource(Args &&... args)
Creates resources of handles&#39; types.
Definition: loop.hpp:250
Event emitter base class.
Definition: emitter.hpp:87
std::enable_if_t< not std::is_base_of< BaseHandle, R >::value, std::shared_ptr< R > > resource(Args &&... args)
Creates resources of types other than handles&#39; ones.
Definition: loop.hpp:268
int descriptor() const noexcept
Get backend file descriptor.
Definition: loop.hpp:339
void fork() noexcept
Reinitialize any kernel state necessary in the child process after a fork(2) system call...
Definition: loop.hpp:430
void update() const noexcept
Updates the event loop’s concept of now.
Definition: loop.hpp:379
Time now() const noexcept
Returns the current timestamp in milliseconds.
Definition: loop.hpp:366
bool run() noexcept
Runs the event loop.
Definition: loop.hpp:304
static std::shared_ptr< Loop > getDefault()
Gets the initialized default loop.
Definition: loop.hpp:184
std::pair< bool, Time > timeout() const noexcept
Gets the poll timeout.
Definition: loop.hpp:349
details::UVTypeWrapper< uv_handle_type > HandleCategory
Definition: util.hpp:197
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:314
void stop() noexcept
Stops the event loop.
Definition: loop.hpp:326
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:390
void close()
Releases all internal loop resources.
Definition: loop.hpp:280
uvw default namespace.
Definition: async.hpp:11