diff --git a/src/uvw/resource.hpp b/src/uvw/resource.hpp index 808cbe65..d2470465 100644 --- a/src/uvw/resource.hpp +++ b/src/uvw/resource.hpp @@ -19,6 +19,7 @@ template<> struct ResourceType { }; template<> struct ResourceType { }; template<> struct ResourceType { }; template<> struct ResourceType { }; +template<> struct ResourceType { }; template<> struct ResourceType { }; template<> struct ResourceType { }; template<> struct ResourceType { }; @@ -28,6 +29,9 @@ template<> struct ResourceType { }; template class Resource: public Emitter, public Self { + template + friend class Resource; + struct BaseWrapper { virtual ~BaseWrapper() = default; virtual void * get() const noexcept = 0; diff --git a/src/uvw/shutdown.hpp b/src/uvw/shutdown.hpp new file mode 100644 index 00000000..d9494c1b --- /dev/null +++ b/src/uvw/shutdown.hpp @@ -0,0 +1,43 @@ +#pragma once + + +#include +#include +#include +#include "event.hpp" +#include "request.hpp" +#include "util.hpp" + + +namespace uvw { + + +class Shutdown final: public Request { + static void shutdownCallback(uv_shutdown_t *req, int status) { + Shutdown &shutdown = *(static_cast(req->data)); + auto ptr = shutdown.shared_from_this(); + ptr->reset(); + if(status) { shutdown.publish(ErrorEvent{status}); } + else { shutdown.publish(ShutdownEvent{}); } + } + + explicit Shutdown(std::shared_ptr ref) + : Request{ResourceType{}, std::move(ref)} + { } + +public: + template + static std::shared_ptr create(Args&&... args) { + return std::shared_ptr{new Shutdown{std::forward(args)...}}; + } + + template + void shutdown(Resource &res) noexcept { + if(0 == invoke(&uv_shutdown, get(), res.template get(), &shutdownCallback)) { + leak(); + } + } +}; + + +} diff --git a/src/uvw/stream.hpp b/src/uvw/stream.hpp index c38aebd8..607ebca1 100644 --- a/src/uvw/stream.hpp +++ b/src/uvw/stream.hpp @@ -9,6 +9,7 @@ #include "event.hpp" #include "handle.hpp" #include "util.hpp" +#include "shutdown.hpp" namespace uvw { @@ -44,13 +45,6 @@ class Stream: public Handle { delete req; } - static void shutdownCallback(uv_shutdown_t *req, int status) { - // TODO migrate to Request (see request.hpp for further details) - T &ref = *(static_cast(req->handle->data)); - if(status) { ref.publish(ErrorEvent{status}); } - else { ref.publish(ShutdownEvent{}); } - } - static void listenCallback(uv_stream_t *handle, int status) { T &ref = *(static_cast(handle->data)); if(status) ref.publish(ErrorEvent{status}); @@ -60,14 +54,16 @@ class Stream: public Handle { protected: template Stream(ResourceType rt, std::shared_ptr ref) - : Handle{std::move(rt), std::move(ref)}, - // TODO migrate to Request (see request.hpp for further details) - sdown{std::make_unique()} + : Handle{std::move(rt), std::move(ref)} { } public: void shutdown() noexcept { - this->invoke(&uv_shutdown, sdown.get(), this->template get(), &shutdownCallback); + auto listener = [this](const auto &event, Shutdown &) { publish(event); }; + auto shutdown = this->loop()->template resource(); + shutdown->template once(listener); + shutdown->template once(listener); + shutdown->shutdown(*this); } void listen(int backlog) noexcept { @@ -126,10 +122,6 @@ public: bool writable() const noexcept { return (uv_is_writable(this->template get()) == 1); } - -private: - // TODO migrate to Request (see request.hpp for further details) - std::unique_ptr sdown; };