WIP: common callback

This commit is contained in:
Michele Caini 2016-06-26 19:07:46 +02:00
parent 4cf0dfba4d
commit a411679970
5 changed files with 59 additions and 49 deletions

View File

@ -12,9 +12,8 @@ namespace uvw {
class Check final: public Resource<Check> {
static void startCallback(Check &ref, uv_check_t*) {
ref.startCb(UVWError{});
ref.startCb = nullptr;
static void startCallback(Check &, std::function<void(UVWError)> &cb, uv_check_t*) {
cb(UVWError{});
}
explicit Check(std::shared_ptr<Loop> ref)
@ -30,14 +29,10 @@ public:
}
void start(std::function<void(UVWError)> cb) noexcept {
auto func = Callback<void(uv_check_t*)>::get<&Check::startCallback>(*this);
using CB = Callback<void(uv_check_t*)>;
auto func = CB::on<&Check::startCallback>(*this, cb);
auto err = uv_check_start(get<uv_check_t>(), func);
if(err) {
startCb(UVWError{err});
} else {
startCb = std::move(cb);
}
if(err) { cb(UVWError{err}); }
}
UVWError stop() noexcept { return UVWError{uv_check_stop(get<uv_check_t>())}; }
@ -45,7 +40,6 @@ public:
explicit operator bool() { return initialized; }
private:
std::function<void(UVWError)> startCb;
bool initialized;
};

View File

@ -3,9 +3,11 @@
#include <type_traits>
#include <functional>
#include <utility>
#include <memory>
#include <uv.h>
#include "loop.hpp"
#include "error.hpp"
namespace uvw {
@ -32,12 +34,18 @@ struct UVCallback;
template<typename T,typename H, typename... Args>
struct UVCallback<T, void(H, Args...)> {
template<void(*F)(T &, H, Args...)>
static auto get(T &);
template<void(*F)(T &, std::function<void(UVWError)> &, H, Args...)>
static auto once(T &, std::function<void(UVWError)>);
template<void(*F)(T &, std::function<void(UVWError)> &, H, Args...)>
static auto on(T &, std::function<void(UVWError)>);
private:
template<void(*F)(T &, H, Args...)>
static void proto(H, Args...);
template<void(*F)(T &, std::function<void(UVWError)> &, H, Args...)>
static void protoOnce(H, Args...);
template<void(*F)(T &, std::function<void(UVWError)> &, H, Args...)>
static void protoOn(H, Args...);
};
@ -49,10 +57,8 @@ class Resource: public std::enable_shared_from_this<T> {
template<typename, typename>
friend struct details::UVCallback;
static void closeCallback(T &ref, uv_handle_t*) {
Resource<T> &res = ref;
res.closeCb(UVWError{});
res.closeCb = nullptr;
static void closeCallback(T &, std::function<void(UVWError)> &cb, uv_handle_t*) {
cb(UVWError{});
}
protected:
@ -88,16 +94,16 @@ public:
bool referenced() const noexcept { return !(uv_has_ref(get<uv_handle_t>()) == 0); }
void close(std::function<void(UVWError)> cb) noexcept {
auto func = Callback<void(uv_handle_t*)>::template get<&Resource<T>::closeCallback>(*static_cast<T*>(this));
closeCb = std::move(cb);
using CB = Callback<void(uv_handle_t*)>;
auto func = CB::template once<&Resource<T>::closeCallback>(*static_cast<T*>(this), std::move(cb));
uv_close(get<uv_handle_t>(), func);
}
private:
std::function<void(UVWError)> closeCb;
std::shared_ptr<Loop> pLoop;
std::shared_ptr<void> handle;
std::shared_ptr<void> leak;
std::function<void(UVWError)> callback;
};
@ -105,24 +111,44 @@ namespace details {
template<typename T, typename H, typename... Args>
template<void(*F)(T &, H, Args...)>
auto UVCallback<T, void(H, Args...)>::get(T &ref) {
template<void(*F)(T &, std::function<void(UVWError)> &, H, Args...)>
auto UVCallback<T, void(H, Args...)>::once(T &ref, std::function<void(UVWError)> cb) {
Resource<T> &res = ref;
res.callback = std::move(cb);
res.leak = res.shared_from_this();
res.template get<uv_handle_t>()->data = static_cast<void*>(&ref);
return &UVCallback<T, void(H, Args...)>::proto<F>;
return &UVCallback<T, void(H, Args...)>::protoOnce<F>;
}
template<typename T, typename H, typename... Args>
template<void(*F)(T &, H, Args...)>
void UVCallback<T, void(H, Args...)>::proto(H handle, Args... args) {
template<void(*F)(T &, std::function<void(UVWError)> &, H, Args...)>
auto UVCallback<T, void(H, Args...)>::on(T &ref, std::function<void(UVWError)> cb) {
Resource<T> &res = ref;
res.callback = std::move(cb);
res.leak = res.shared_from_this();
res.template get<uv_handle_t>()->data = static_cast<void*>(&ref);
return &UVCallback<T, void(H, Args...)>::protoOn<F>;
}
template<typename T, typename H, typename... Args>
template<void(*F)(T &, std::function<void(UVWError)> &, H, Args...)>
void UVCallback<T, void(H, Args...)>::protoOnce(H handle, Args... args) {
T &ref = *(static_cast<T*>(details::get(handle)));
auto cb = ref.callback;
auto ptr = ref.leak;
ref.leak.reset();
F(ref, handle, std::forward<Args>(args)...);
F(ref, ref.callback, handle, std::forward<Args>(args)...);
ref.callback = nullptr;
(void)ptr;
}
template<typename T, typename H, typename... Args>
template<void(*F)(T &, std::function<void(UVWError)> &, H, Args...)>
void UVCallback<T, void(H, Args...)>::protoOn(H handle, Args... args) {
T &ref = *(static_cast<T*>(details::get(handle)));
F(ref, ref.callback, handle, std::forward<Args>(args)...);
}
}

View File

@ -11,9 +11,8 @@ namespace uvw {
template<typename T>
class Stream: public Resource<T> {
static void listenCallback(T &ref, uv_stream_t* srv, int status) {
ref.listenCb(UVWError{status});
ref.listenCb = nullptr;
static void listenCallback(T &ref, std::function<void(UVWError)> &cb, uv_stream_t* srv, int status) {
cb(UVWError{status});
}
protected:
@ -24,15 +23,9 @@ public:
void listen(int backlog, std::function<void(UVWError)> cb) noexcept {
using CB = typename Resource<T>::template Callback<void(uv_stream_t*, int)>;
auto func = CB::get<&Stream<T>::listenCallback>(*static_cast<T*>(this));
auto func = CB::on<&Stream<T>::listenCallback>(*static_cast<T*>(this), cb);
auto err = uv_listen(this->template get<uv_stream_t>(), backlog, func);
if(err) {
listenCb(UVWError{err});
} else {
listenCb = std::move(cb);
}
if(err) { cb(UVWError{err}); }
}
// TODO read

View File

@ -65,6 +65,7 @@ private:
template<>
void Tcp::connect<Tcp::IPv4>(std::string ip, int port, std::function<void(UVWError)> cb) noexcept {
// TODO switch to the Callback model
sockaddr_in addr;
uv_ip4_addr(ip.c_str(), port, &addr);
connCb = std::move(cb);
@ -79,6 +80,7 @@ void Tcp::connect<Tcp::IPv4>(std::string ip, int port, std::function<void(UVWErr
template<>
void Tcp::connect<Tcp::IPv6>(std::string ip, int port, std::function<void(UVWError)> cb) noexcept {
// TODO switch to the Callback model
sockaddr_in6 addr;
uv_ip6_addr(ip.c_str(), port, &addr);
connCb = std::move(cb);

View File

@ -14,9 +14,8 @@ namespace uvw {
class Timer final: public Resource<Timer> {
static void startCallback(Timer &ref, uv_timer_t*) {
ref.startCb(UVWError{});
ref.startCb = nullptr;
static void startCallback(Timer &, std::function<void(UVWError)> &cb, uv_timer_t*) {
cb(UVWError{});
}
explicit Timer(std::shared_ptr<Loop> ref)
@ -34,14 +33,10 @@ public:
}
void start(const Time &timeout, const Time &rep, std::function<void(UVWError)> cb) noexcept {
auto func = Callback<void(uv_timer_t*)>::get<&Timer::startCallback>(*this);
using CB = Callback<void(uv_timer_t*)>;
auto func = CB::on<&Timer::startCallback>(*this, cb);
auto err = uv_timer_start(get<uv_timer_t>(), func, timeout.count(), rep.count());
if(err) {
startCb(UVWError{err});
} else {
startCb = std::move(cb);
}
if(err) { cb(UVWError{err}); }
}
UVWError stop() noexcept { return UVWError{uv_timer_stop(get<uv_timer_t>())}; }