diff --git a/src/uvw/check.hpp b/src/uvw/check.hpp index 61cf0535..da017266 100644 --- a/src/uvw/check.hpp +++ b/src/uvw/check.hpp @@ -12,8 +12,8 @@ namespace uvw { class Check final: public Resource { - static void proto(uv_check_t* h) { - static_cast(h->data)->callback(UVWError{}); + static void startCallback(uv_check_t* h) { + static_cast(h->data)->startCb(UVWError{}); } explicit Check(std::shared_ptr ref) @@ -23,20 +23,18 @@ class Check final: public Resource { } public: - using Callback = std::function; - template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new Check{std::forward(args)...}}; } - void start(Callback cb) noexcept { - callback = std::move(cb); + void start(std::function cb) noexcept { + startCb = std::move(cb); get()->data = this; - auto err = uv_check_start(get(), &proto); + auto err = uv_check_start(get(), &startCallback); if(err) { - callback(UVWError{err}); + startCb(UVWError{err}); } } @@ -45,7 +43,7 @@ public: explicit operator bool() { return initialized; } private: - Callback callback; + std::function startCb; bool initialized; }; diff --git a/src/uvw/loop.hpp b/src/uvw/loop.hpp index 3107eb8b..3e8fa76d 100644 --- a/src/uvw/loop.hpp +++ b/src/uvw/loop.hpp @@ -59,7 +59,8 @@ private: class Loop final: public std::enable_shared_from_this { - friend class BaseResource; + template + friend class Resource; using Deleter = std::function; diff --git a/src/uvw/resource.hpp b/src/uvw/resource.hpp index 28b9e17b..608db68d 100644 --- a/src/uvw/resource.hpp +++ b/src/uvw/resource.hpp @@ -15,24 +15,55 @@ template struct HandleType { }; -class BaseResource { +template +class Resource; + + +template +struct UVCallback; + + +template +struct UVCallback { + template + static auto get(T *res); + +private: + template + static void proto(Args... args); +}; + + +template +class Resource: public std::enable_shared_from_this { + template + friend struct UVCallback; + + static Resource* closeCallback(uv_handle_t* h) { + auto ptr = static_cast*>(h->data); + ptr->closeCb(UVWError{}); + return ptr; + } + protected: - template - explicit BaseResource(HandleType, std::shared_ptr r) - : pLoop{std::move(r)}, handle{std::make_shared()} + template + explicit Resource(HandleType, std::shared_ptr r) + : pLoop{std::move(r)}, handle{std::make_shared()} { } - template - T* get() const noexcept { return reinterpret_cast(handle.get()); } + template + U* get() const noexcept { return reinterpret_cast(handle.get()); } uv_loop_t* parent() const noexcept { return pLoop->loop.get(); } public: - explicit BaseResource(const BaseResource &) = delete; - explicit BaseResource(BaseResource &&) = delete; + explicit Resource(const Resource &) = delete; + explicit Resource(Resource &&) = delete; - void operator=(const BaseResource &) = delete; - void operator=(BaseResource &&) = delete; + ~Resource() { static_assert(std::is_base_of, T>::value, "!"); } + + void operator=(const Resource &) = delete; + void operator=(Resource &&) = delete; std::shared_ptr loop() const noexcept { return pLoop; } @@ -43,33 +74,35 @@ public: void unreference() noexcept { uv_ref(get()); } bool referenced() const noexcept { return !(uv_has_ref(get()) == 0); } + void close(std::function cb) noexcept { + using UVCB = UVCallback; + auto func = UVCB::get, &closeCallback>(this); + closeCb = std::move(cb); + uv_close(get(), func); + } + private: + std::function closeCb; std::shared_ptr pLoop; std::shared_ptr handle; + std::shared_ptr ref; }; -template -class Resource: public std::enable_shared_from_this, public BaseResource { - static void proto(uv_handle_t* h) { - static_cast*>(h->data)->callback(UVWError{}); - } +template +template +void UVCallback::proto(Args... args) { + T *res = F(std::forward(args)...); + res->ref = nullptr; +} -protected: - using BaseResource::BaseResource; - -public: - using Callback = std::function; - - void close(Callback cb) noexcept { - callback = std::move(cb); - get()->data = this; - uv_close(get(), &proto); - } - -private: - Callback callback; -}; +template +template +auto UVCallback::get(T *res) { + res->template get()->data = res; + res->ref = res->shared_from_this(); + return &proto; +} } diff --git a/test/main.cpp b/test/main.cpp index 967e2e5b..cc86ad7e 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -8,9 +8,8 @@ void f(uvw::Loop &loop) { auto cb = [handle](uvw::UVWError err) mutable { std::cout << "---" << ((bool)err) << std::endl; uvw::Tcp &tcp = handle; - tcp.close([handle](uvw::UVWError err) mutable { + tcp.close([](uvw::UVWError err) mutable { std::cout << "---" << ((bool)err) << std::endl; - handle = uvw::Handle{}; }); };