From 2e5bb0f1134c7a8b8ab9f4c8d8e817e4d37e450a Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Sun, 26 Jun 2016 16:52:30 +0200 Subject: [PATCH] WIP: going crazy with uv --- src/uvw/check.hpp | 14 ++++---- src/uvw/resource.hpp | 78 +++++++++++++++++++++++++++++--------------- src/uvw/timer.hpp | 14 ++++---- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/uvw/check.hpp b/src/uvw/check.hpp index 34d9fb0e..7cc18777 100644 --- a/src/uvw/check.hpp +++ b/src/uvw/check.hpp @@ -12,10 +12,9 @@ namespace uvw { class Check final: public Resource { - static Check* startCallback(uv_check_t* h) { - Check *check = static_cast(h->data); - check->startCb(UVWError{}); - return check; + static void startCallback(Check &ref, uv_check_t* h) { + ref.startCb(UVWError{}); + ref.startCb = nullptr; } explicit Check(std::shared_ptr ref) @@ -31,14 +30,13 @@ public: } void start(std::function cb) noexcept { - using UVCB = UVCallback; - auto func = UVCB::get<&Check::startCallback>(this); - startCb = std::move(cb); + auto func = Callback::get<&Check::startCallback>(*this); auto err = uv_check_start(get(), func); if(err) { startCb(UVWError{err}); - reset(); + } else { + startCb = std::move(cb); } } diff --git a/src/uvw/resource.hpp b/src/uvw/resource.hpp index b72fc5c7..708c6383 100644 --- a/src/uvw/resource.hpp +++ b/src/uvw/resource.hpp @@ -19,29 +19,46 @@ template class Resource; -template -struct UVCallback { - template - static auto get(T *res); +namespace details { + + +template +void* get(T *handle) { return handle->data; } + + +template +struct UVCallback; + + +template +struct UVCallback { + template + static auto get(T &); private: - template - static void proto(Args... args); + template + static void proto(H, Args...); }; +} + + template class Resource: public std::enable_shared_from_this { - template - friend struct UVCallback; + template + friend struct details::UVCallback; - static Resource* closeCallback(uv_handle_t* h) { - auto *ptr = static_cast*>(h->data); - ptr->closeCb(UVWError{}); - return ptr; + static void closeCallback(T &ref, uv_handle_t* h) { + Resource &res = ref; + res.closeCb(UVWError{}); + res.closeCb = nullptr; } protected: + template + using Callback = details::UVCallback; + template explicit Resource(HandleType, std::shared_ptr r) : pLoop{std::move(r)}, handle{std::make_shared()} @@ -51,7 +68,6 @@ protected: U* get() const noexcept { return reinterpret_cast(handle.get()); } uv_loop_t* parent() const noexcept { return pLoop->loop.get(); } - void reset() noexcept { ref = nullptr; } public: explicit Resource(const Resource &) = delete; @@ -72,8 +88,7 @@ public: bool referenced() const noexcept { return !(uv_has_ref(get()) == 0); } void close(std::function cb) noexcept { - using UVCB = UVCallback, uv_handle_t*>; - auto func = UVCB::template get<&Resource::closeCallback>(this); + auto func = Callback::template get<&Resource::closeCallback>(*static_cast(this)); closeCb = std::move(cb); uv_close(get(), func); } @@ -82,23 +97,32 @@ private: std::function closeCb; std::shared_ptr pLoop; std::shared_ptr handle; - std::shared_ptr ref; + std::shared_ptr leak; }; -template -template -void UVCallback::proto(Args... args) { - T *res = F(std::forward(args)...); - res->ref = nullptr; +namespace details { + + +template +template +auto UVCallback::get(T &ref) { + Resource &res = ref; + res.leak = res.shared_from_this(); + res.template get()->data = static_cast(&ref); + return &UVCallback::proto; } -template -template -auto UVCallback::get(T *res) { - res->template get()->data = res; - res->ref = res->shared_from_this(); - return &UVCallback::proto; +template +template +void UVCallback::proto(H handle, Args... args) { + T &ref = *(static_cast(details::get(handle))); + F(ref, handle, std::forward(args)...); + ref.leak.reset(); + +} + + } diff --git a/src/uvw/timer.hpp b/src/uvw/timer.hpp index 8b3189a0..e508ec80 100644 --- a/src/uvw/timer.hpp +++ b/src/uvw/timer.hpp @@ -14,10 +14,9 @@ namespace uvw { class Timer final: public Resource { - static Timer* startCallback(uv_timer_t* h) { - Timer *timer = static_cast(h->data); - timer->startCb(UVWError{}); - return timer; + static void startCallback(Timer &ref, uv_timer_t* h) { + ref.startCb(UVWError{}); + ref.startCb = nullptr; } explicit Timer(std::shared_ptr ref) @@ -35,14 +34,13 @@ public: } void start(const Time &timeout, const Time &rep, std::function cb) noexcept { - using UVCB = UVCallback; - auto func = UVCB::get<&Timer::startCallback>(this); - startCb = std::move(cb); + auto func = Callback::get<&Timer::startCallback>(*this); auto err = uv_timer_start(get(), func, timeout.count(), rep.count()); if(err) { startCb(UVWError{err}); - reset(); + } else { + startCb = std::move(cb); } }