From f10bb0503ac955eb6eda6e88e292ba43b7bb598f Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Mon, 27 Jun 2016 09:22:14 +0200 Subject: [PATCH] reference given back to the caller + tcp.connect migrated to the callback model --- src/uvw/check.hpp | 10 +++++----- src/uvw/resource.hpp | 44 +++++++++++++++++++++----------------------- src/uvw/stream.hpp | 10 +++++----- src/uvw/tcp.hpp | 37 +++++++++++++------------------------ src/uvw/timer.hpp | 10 +++++----- test/main.cpp | 5 ++--- 6 files changed, 51 insertions(+), 65 deletions(-) diff --git a/src/uvw/check.hpp b/src/uvw/check.hpp index b6cac22b..a04cd0d1 100644 --- a/src/uvw/check.hpp +++ b/src/uvw/check.hpp @@ -12,8 +12,8 @@ namespace uvw { class Check final: public Resource { - static void startCallback(Check &, std::function &cb, uv_check_t*) { - cb(UVWError{}); + static void startCallback(Check &check, std::function &cb, uv_check_t *) { + cb(UVWError{}, check); } explicit Check(std::shared_ptr ref) @@ -28,11 +28,11 @@ public: return std::shared_ptr{new Check{std::forward(args)...}}; } - void start(std::function cb) noexcept { - using CB = Callback; + void start(std::function cb) noexcept { + using CB = Callback; auto func = CB::on<&Check::startCallback>(*this, cb); auto err = uv_check_start(get(), func); - if(err) { cb(UVWError{err}); } + if(err) { cb(UVWError{err}, *this); } } UVWError stop() noexcept { return UVWError{uv_check_stop(get())}; } diff --git a/src/uvw/resource.hpp b/src/uvw/resource.hpp index 42582664..220f1f71 100644 --- a/src/uvw/resource.hpp +++ b/src/uvw/resource.hpp @@ -24,8 +24,8 @@ class Resource; namespace details { -template -void* get(T *handle) { return handle->data; } +template void* get(T *handle) { return handle->data; } +void* get(uv_connect_t *conn) { return conn->handle->data; } template @@ -34,17 +34,17 @@ struct UVCallback; template struct UVCallback { - template &, H, Args...)> - static auto once(T &, std::function); + template &, H, Args...)> + static auto once(T &, std::function); - template &, H, Args...)> - static auto on(T &, std::function); + template &, H, Args...)> + static auto on(T &, std::function); private: - template &, H, Args...)> + template &, H, Args...)> static void protoOnce(H, Args...); - template &, H, Args...)> + template &, H, Args...)> static void protoOn(H, Args...); }; @@ -57,8 +57,8 @@ class Resource: public std::enable_shared_from_this { template friend struct details::UVCallback; - static void closeCallback(T &, std::function &cb, uv_handle_t*) { - cb(UVWError{}); + static void closeCallback(T &t, std::function &cb, uv_handle_t*) { + cb(UVWError{}, t); } protected: @@ -93,7 +93,7 @@ public: void unreference() noexcept { uv_ref(get()); } bool referenced() const noexcept { return !(uv_has_ref(get()) == 0); } - void close(std::function cb) noexcept { + void close(std::function cb) noexcept { using CB = Callback; auto func = CB::template once<&Resource::closeCallback>(*static_cast(this), std::move(cb)); uv_close(get(), func); @@ -103,7 +103,7 @@ private: std::shared_ptr pLoop; std::shared_ptr handle; std::shared_ptr leak; - std::function callback; + std::function callback; }; @@ -111,8 +111,8 @@ namespace details { template -template &, H, Args...)> -auto UVCallback::once(T &ref, std::function cb) { +template &, H, Args...)> +auto UVCallback::once(T &ref, std::function cb) { Resource &res = ref; res.callback = std::move(cb); res.leak = res.shared_from_this(); @@ -121,8 +121,8 @@ auto UVCallback::once(T &ref, std::function } template -template &, H, Args...)> -auto UVCallback::on(T &ref, std::function cb) { +template &, H, Args...)> +auto UVCallback::on(T &ref, std::function cb) { Resource &res = ref; res.callback = std::move(cb); res.leak = res.shared_from_this(); @@ -131,19 +131,17 @@ auto UVCallback::on(T &ref, std::function c } template -template &, H, Args...)> +template &, H, Args...)> void UVCallback::protoOnce(H handle, Args... args) { T &ref = *(static_cast(details::get(handle))); - auto cb = ref.callback; - auto ptr = ref.leak; + std::shared_ptr ptr = std::static_pointer_cast(ref.leak); + auto cb = std::move(ref.callback); ref.leak.reset(); - F(ref, ref.callback, handle, std::forward(args)...); - ref.callback = nullptr; - (void)ptr; + F(*ptr, cb, handle, std::forward(args)...); } template -template &, H, Args...)> +template &, H, Args...)> void UVCallback::protoOn(H handle, Args... args) { T &ref = *(static_cast(details::get(handle))); F(ref, ref.callback, handle, std::forward(args)...); diff --git a/src/uvw/stream.hpp b/src/uvw/stream.hpp index 9462298a..a22d4b77 100644 --- a/src/uvw/stream.hpp +++ b/src/uvw/stream.hpp @@ -11,8 +11,8 @@ namespace uvw { template class Stream: public Resource { - static void listenCallback(T &ref, std::function &cb, uv_stream_t* srv, int status) { - cb(UVWError{status}); + static void listenCallback(T &t, std::function &cb, uv_stream_t *, int status) { + cb(UVWError{status}, t); } protected: @@ -21,11 +21,11 @@ protected: public: // TODO shutdown - void listen(int backlog, std::function cb) noexcept { - using CB = typename Resource::template Callback; + void listen(int backlog, std::function cb) noexcept { + using CB = typename Resource::template Callback; auto func = CB::on<&Stream::listenCallback>(*static_cast(this), cb); auto err = uv_listen(this->template get(), backlog, func); - if(err) { cb(UVWError{err}); } + if(err) { cb(UVWError{err}, *static_cast(this)); } } // TODO read diff --git a/src/uvw/tcp.hpp b/src/uvw/tcp.hpp index ad2a58dc..88783b3c 100644 --- a/src/uvw/tcp.hpp +++ b/src/uvw/tcp.hpp @@ -16,10 +16,8 @@ namespace uvw { class Tcp final: public Stream { - static void protoConnect(uv_connect_t* req, int status) { - Tcp *tcp = static_cast(req->handle->data); - tcp->connCb(UVWError{status}); - tcp->connCb = nullptr; + static void connectCallback(Tcp &tcp, std::function &cb, uv_connect_t *, int status) { + cb(UVWError{status}, tcp); } explicit Tcp(std::shared_ptr ref) @@ -52,44 +50,35 @@ public: } template - void connect(std::string, int, std::function) noexcept; + void connect(std::string, int, std::function) noexcept; explicit operator bool() { return initialized; } private: std::unique_ptr conn; - std::function connCb; bool initialized; }; template<> -void Tcp::connect(std::string ip, int port, std::function cb) noexcept { - // TODO switch to the Callback model +void Tcp::connect(std::string ip, int port, std::function cb) noexcept { sockaddr_in addr; uv_ip4_addr(ip.c_str(), port, &addr); - connCb = std::move(cb); - get()->data = this; - auto err = uv_tcp_connect(conn.get(), get(), reinterpret_cast(&addr), &protoConnect); - - if(err) { - connCb(UVWError{err}); - } + using CB = Callback; + auto func = CB::template once<&Tcp::connectCallback>(*this, cb); + auto err = uv_tcp_connect(conn.get(), get(), reinterpret_cast(&addr), func); + if(err) { cb(UVWError{err}, *this); } } template<> -void Tcp::connect(std::string ip, int port, std::function cb) noexcept { - // TODO switch to the Callback model +void Tcp::connect(std::string ip, int port, std::function cb) noexcept { sockaddr_in6 addr; uv_ip6_addr(ip.c_str(), port, &addr); - connCb = std::move(cb); - get()->data = this; - auto err = uv_tcp_connect(conn.get(), get(), reinterpret_cast(&addr), &protoConnect); - - if(err) { - connCb(UVWError{err}); - } + using CB = Callback; + auto func = CB::template once<&Tcp::connectCallback>(*this, cb); + auto err = uv_tcp_connect(conn.get(), get(), reinterpret_cast(&addr), func); + if(err) { cb(UVWError{err}, *this); } } diff --git a/src/uvw/timer.hpp b/src/uvw/timer.hpp index 6af3189e..63030c14 100644 --- a/src/uvw/timer.hpp +++ b/src/uvw/timer.hpp @@ -14,8 +14,8 @@ namespace uvw { class Timer final: public Resource { - static void startCallback(Timer &, std::function &cb, uv_timer_t*) { - cb(UVWError{}); + static void startCallback(Timer &timer, std::function &cb, uv_timer_t *) { + cb(UVWError{}, timer); } explicit Timer(std::shared_ptr ref) @@ -32,11 +32,11 @@ public: return std::shared_ptr{new Timer{std::forward(args)...}}; } - void start(const Time &timeout, const Time &rep, std::function cb) noexcept { - using CB = Callback; + void start(const Time &timeout, const Time &rep, std::function cb) noexcept { + using CB = Callback; auto func = CB::on<&Timer::startCallback>(*this, cb); auto err = uv_timer_start(get(), func, timeout.count(), rep.count()); - if(err) { cb(UVWError{err}); } + if(err) { cb(UVWError{err}, *this); } } UVWError stop() noexcept { return UVWError{uv_timer_stop(get())}; } diff --git a/test/main.cpp b/test/main.cpp index cc86ad7e..b7a20e5e 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -5,10 +5,9 @@ void f(uvw::Loop &loop) { uvw::Handle handle = loop.handle(); - auto cb = [handle](uvw::UVWError err) mutable { + auto cb = [](uvw::UVWError err, uvw::Tcp &tcp) mutable { std::cout << "---" << ((bool)err) << std::endl; - uvw::Tcp &tcp = handle; - tcp.close([](uvw::UVWError err) mutable { + tcp.close([](uvw::UVWError err, uvw::Tcp &) mutable { std::cout << "---" << ((bool)err) << std::endl; }); };