5 #include "uvcc/debug.hpp" 6 #include "uvcc/utility.hpp" 12 #include <type_traits> 38 friend class getaddrinfo;
39 friend class getnameinfo;
40 template<
typename >
friend class work;
44 using uv_t = ::uv_loop_t;
45 using on_destroy_t = std::function<
void(
void *_data) >;
47 using on_exit_t = std::function<
void(
loop _loop) >;
49 template<
typename... _Args_ >
50 using on_walk_t = std::function<
void(
handle _handle, _Args_&&... _args) >;
59 mutable int uv_error = 0;
63 uv_t uv_loop_struct = { 0,};
68 uv_error = ::uv_loop_init(&uv_loop_struct);
69 uvcc_debug_function_return(
"instance [0x%08tX] for loop [0x%08tX] (uv_error=%i)", (ptrdiff_t)
this, (ptrdiff_t)&uv_loop_struct, uv_error);
73 ~instance()
noexcept(
false)
75 uvcc_debug_function_enter(
"instance [0x%08tX] for loop [0x%08tX] (is_alive=%i)", (ptrdiff_t)
this, (ptrdiff_t)&uv_loop_struct, ::uv_loop_alive(&uv_loop_struct));
76 uvcc_debug_do_if(
true, {
77 uvcc_debug_log_if(
true,
"walk on loop [0x%08tX] destroying...", (ptrdiff_t)&uv_loop_struct);
78 debug::print_loop_handles(&uv_loop_struct);
81 uv_error = ::uv_loop_close(&uv_loop_struct);
82 auto loop_closed = (uv_error == 0);
83 uvcc_debug_condition(loop_closed,
"loop [0x%08tX] (is_alive=%i)", (ptrdiff_t)&uv_loop_struct, ::uv_loop_alive(&uv_loop_struct));
88 unsigned num_open_handles = 0;
91 [](::uv_handle_t *_h,
void *_n){
if (!::uv_is_closing(_h)) ++*
static_cast<
unsigned* >(_n); },
94 uvcc_debug_condition(num_open_handles == 0,
"loop [0x%08tX] (num_open_handles=%u)", (ptrdiff_t)&uv_loop_struct, num_open_handles);
101 if (std::uncaught_exception())
103 uvcc_debug_log_if(
true,
"loop [0x%08tX] is being destroyed during stack unwinding", (ptrdiff_t)&uv_loop_struct);
107 throw std::logic_error(
__PRETTY_FUNCTION__);
112 uvcc_debug_log_if(
true,
"try at loop [0x%08tX] premortal one shot nonblocking run", (ptrdiff_t)&uv_loop_struct);
113 uv_error = ::uv_run(&uv_loop_struct, UV_RUN_NOWAIT);
116 uv_error = ::uv_loop_close(&uv_loop_struct);
117 loop_closed = (uv_error == 0);
118 uvcc_debug_condition(loop_closed,
"loop [0x%08tX] (is_alive=%i)", (ptrdiff_t)&uv_loop_struct, ::uv_loop_alive(&uv_loop_struct));
119 if (!loop_closed)
throw std::runtime_error(
__PRETTY_FUNCTION__);
123 instance(
const instance&) =
delete;
124 instance& operator =(
const instance&) =
delete;
126 instance(instance&&) =
delete;
127 instance& operator =(instance&&) =
delete;
132 auto &destroy_cb = destroy_cb_storage.value();
133 if (destroy_cb) destroy_cb(uv_loop_struct.data);
138 static uv_t* create() {
return &(
new instance())->uv_loop_struct; }
140 constexpr static instance* from(uv_t *_uv_loop)
noexcept 142 static_assert(std::is_standard_layout< instance >::value,
"not a standard layout type");
143 return reinterpret_cast< instance* >(
reinterpret_cast<
char* >(_uv_loop) - offsetof(instance, uv_loop_struct));
148 uvcc_debug_function_enter(
"loop [0x%08tX]", (ptrdiff_t)&uv_loop_struct);
153 uvcc_debug_function_enter(
"loop [0x%08tX]", (ptrdiff_t)&uv_loop_struct);
154 auto nrefs = refs.dec();
155 uvcc_debug_condition(nrefs == 0,
"loop [0x%08tX] (nrefs=%li)", (ptrdiff_t)&uv_loop_struct, nrefs);
156 if (nrefs == 0) destroy();
160 friend typename loop::instance* debug::instance<>(loop&)
noexcept;
167 explicit loop(uv_t *_uv_loop)
169 if (_uv_loop) instance::from(_uv_loop)->ref();
174 ~loop() {
if (uv_loop) instance::from(uv_loop)->unref(); }
177 loop() : uv_loop(instance::create()) {}
179 loop(
const loop &_that) :
loop(_that.uv_loop) {}
184 if (_that.uv_loop) instance::from(_that.uv_loop)->ref();
186 uv_loop = _that.uv_loop;
187 if (t) instance::from(t)->unref();
192 loop(
loop &&_that)
noexcept : uv_loop(_that.uv_loop) { _that.uv_loop =
nullptr; }
193 loop& operator =(
loop &&_that)
noexcept 198 uv_loop = _that.uv_loop;
199 _that.uv_loop =
nullptr;
200 if (t) instance::from(t)->unref();
206 template<
typename =
void >
static void walk_cb(::uv_handle_t*,
void*);
208 int uv_status(
int _value)
const noexcept 210 instance::from(uv_loop)->uv_error = _value;
222 static loop default_loop;
226 void swap(
loop &_that)
noexcept { std::swap(uv_loop, _that.uv_loop); }
228 long nrefs()
const noexcept {
return instance::from(uv_loop)->refs.get_value(); }
230 int uv_status()
const noexcept {
return instance::from(uv_loop)->uv_error; }
232 on_destroy_t& on_destroy()
const noexcept {
return instance::from(uv_loop)->destroy_cb_storage.value(); }
234 on_exit_t& on_exit()
const noexcept {
return instance::from(uv_loop)->exit_cb_storage.value(); }
238 void*
const&
data()
const noexcept {
return uv_loop->data; }
239 void* & data()
noexcept {
return uv_loop->data; }
243 template<
typename... _Args_ >
246 return uv_status(::uv_loop_configure(uv_loop, _opt, std::forward< _Args_ >(_args)...));
255 int run(::uv_run_mode _mode)
257 auto uv_ret = uv_status(::uv_run(uv_loop, _mode));
259 uvcc_debug_do_if(
true, {
260 uvcc_debug_log_if(
true,
"walk on loop [0x%08tX] (is_alive=%i) exiting (uv_error=%i)...", (ptrdiff_t)uv_loop, ::uv_loop_alive(uv_loop), uv_ret);
261 debug::print_loop_handles(uv_loop);
264 auto &exit_cb = instance::from(uv_loop)->exit_cb_storage.value();
265 if (exit_cb) exit_cb(loop(uv_loop));
272 void stop() { ::uv_stop(uv_loop); }
275 int is_alive()
const noexcept {
return uv_status(::uv_loop_alive(uv_loop)); }
279 int backend_fd()
const noexcept {
return ::uv_backend_fd(uv_loop); }
284 uint64_t
now()
const noexcept {
return ::uv_now(uv_loop); }
295 template<
class _Func_,
typename... _Args_,
298 void walk(_Func_&& _walk_cb, _Args_&&... _args)
300 std::function<
void(
handle) > cb{ std::bind(std::forward< _Func_ >(_walk_cb), std::placeholders::_1, std::forward< _Args_ >(_args)...) };
301 if (cb) ::uv_walk(uv_loop, walk_cb, &cb);
305 explicit operator
const uv_t*()
const noexcept {
return uv_loop; }
306 explicit operator uv_t*()
noexcept {
return uv_loop; }
315 #include "uvcc/handle-base.hpp" 321 void loop::walk_cb(::uv_handle_t *_uv_handle,
void *_arg)
323 static_cast< std::function<
void(handle) >* >(_arg)->operator()(handle(_uv_handle));
332 template<>
inline void swap(
uv::
loop &_this,
uv::
loop &_that)
noexcept { _this.swap(_that); }
Namespace for all uvcc definitions.
void stop()
Stop the event loop.
int backend_timeout() const noexcept
Get the poll timeout. The return value is in milliseconds, or -1 for no timeout.
A wrapper providing the feature of being a standard layout type for the given type _T_...
long nrefs() const noexcept
The current number of existing references to the same loop as this variable refers to...
void update_time() noexcept
int uv_status() const noexcept
The status value returned by the last executed libuv API function.
int is_alive() const noexcept
Returns non-zero if there are active handles or request in the loop.
int configure(::uv_loop_option _opt, _Args_ &&... _args)
Set additional loop options.
loop()
Create a new event loop.
The base class for the libuv handles.
static loop & Default() noexcept
Returns the initialized loop that can be used as a global default loop throughout the program...
uint64_t now() const noexcept
int run(::uv_run_mode _mode)
Go into a loop and process events and their callbacks with the current thread.
operator bool() const noexcept
Equivalent to (uv_status() >= 0).
The I/O event loop class.
A reference counter with atomic increment/decrement.
void walk(_Func_ &&_walk_cb, _Args_ &&... _args)
int backend_fd() const noexcept
void *const & data() const noexcept