WIP: more and more functionalities

This commit is contained in:
Michele Caini 2016-06-27 12:04:29 +02:00
parent 928fb1269f
commit 79d2774ac5
7 changed files with 111 additions and 28 deletions

View File

@ -32,7 +32,7 @@ public:
using CBF = CallbackFactory<void(uv_check_t *)>;
auto func = CBF::on<&Check::startCallback>(*this, cb);
auto err = uv_check_start(get<uv_check_t>(), func);
if(err) { cb(UVWError{err}, *this); }
if(err) { error(err); }
}
UVWError stop() noexcept { return UVWError{uv_check_stop(get<uv_check_t>())}; }

View File

@ -12,7 +12,6 @@
namespace uvw {
class BaseResource;
class Loop;
@ -50,9 +49,6 @@ public:
constexpr operator R&() noexcept { return *res; }
constexpr operator const R&() const noexcept { return *res; }
template<typename T, std::enable_if_t<std::is_base_of<T, R>::value>* = nullptr>
constexpr operator Handle<T>() { return Handle<T>{res}; }
private:
std::shared_ptr<R> res;
};
@ -109,6 +105,11 @@ public:
}
}
template<typename R>
Handle<R> handle(std::shared_ptr<R> ptr) {
return Handle<R>{std::move(ptr)};
}
template<typename R, typename... Args>
Handle<R> handle(Args&&... args) {
return Handle<R>{shared_from_this(), std::forward<Args>(args)...};

View File

@ -67,11 +67,18 @@ protected:
template<typename U>
explicit Resource(HandleType<U>, std::shared_ptr<Loop> r)
: pLoop{std::move(r)}, handle{std::make_shared<U>()}
: uvHandle{std::make_shared<U>()}, pLoop{std::move(r)}
{ }
void error(int error) {
auto ptr = std::static_pointer_cast<T>(leak);
auto cb = std::move(callback);
leak.reset();
cb(UVWError{error}, *ptr);
}
template<typename U>
U* get() const noexcept { return reinterpret_cast<U*>(handle.get()); }
U* get() const noexcept { return reinterpret_cast<U*>(uvHandle.get()); }
uv_loop_t* parent() const noexcept { return pLoop->loop.get(); }
@ -84,7 +91,8 @@ public:
void operator=(const Resource &) = delete;
void operator=(Resource &&) = delete;
std::shared_ptr<Loop> loop() const noexcept { return pLoop; }
Handle<T> handle() noexcept { return pLoop->handle(Resource<T>::shared_from_this()); }
Loop& loop() const noexcept { return *pLoop; }
bool active() const noexcept { return !(uv_is_active(get<uv_handle_t>()) == 0); }
bool closing() const noexcept { return !(uv_is_closing(get<uv_handle_t>()) == 0); }
@ -100,8 +108,8 @@ public:
}
private:
std::shared_ptr<void> uvHandle;
std::shared_ptr<Loop> pLoop;
std::shared_ptr<void> handle;
std::shared_ptr<void> leak;
std::function<void(UVWError, T &)> callback;
};
@ -134,7 +142,7 @@ template<typename T, typename H, typename... Args>
template<void(*F)(T &, std::function<void(UVWError, T &)> &, H, Args...)>
void UVCallbackFactory<T, void(H, Args...)>::protoOnce(H handle, Args... args) {
T &ref = *(static_cast<T*>(details::get(handle)));
std::shared_ptr<T> ptr = std::static_pointer_cast<T>(ref.leak);
auto ptr = std::static_pointer_cast<T>(ref.leak);
auto cb = std::move(ref.callback);
ref.leak.reset();
F(*ptr, cb, handle, std::forward<Args>(args)...);

View File

@ -11,6 +11,8 @@ namespace uvw {
template<typename T>
class Stream: public Resource<T> {
static constexpr unsigned int DEFAULT_BACKLOG = 128;
static void listenCallback(T &t, std::function<void(UVWError, T &)> &cb, uv_stream_t *, int status) {
cb(UVWError{status}, t);
}
@ -21,11 +23,15 @@ protected:
public:
// TODO shutdown
void listen(std::function<void(UVWError, T &)> cb) noexcept {
listen(DEFAULT_BACKLOG, std::move(cb));
}
void listen(int backlog, std::function<void(UVWError, T &)> cb) noexcept {
using CBF = typename Resource<T>::template CallbackFactory<void(uv_stream_t *, int)>;
auto func = CBF::on<&Stream<T>::listenCallback>(*static_cast<T*>(this), cb);
auto func = CBF::template on<&Stream<T>::listenCallback>(*static_cast<T*>(this), cb);
auto err = uv_listen(this->template get<uv_stream_t>(), backlog, func);
if(err) { cb(UVWError{err}, *static_cast<T*>(this)); }
if(err) { Stream<T>::error(err); }
}
// TODO read

View File

@ -34,7 +34,7 @@ class Tcp final: public Stream<Tcp> {
public:
using Time = std::chrono::duration<uint64_t>;
enum { IPv4, IPv6 };
enum IP { IPv4, IPv6 };
template<typename... Args>
static std::shared_ptr<Tcp> create(Args&&... args) {
@ -49,8 +49,15 @@ public:
return UVWError{uv_tcp_keepalive(get<uv_tcp_t>(), enable ? 1 : 0, time.count())};
}
template<int>
void connect(std::string, int, std::function<void(UVWError, Tcp &)>) noexcept;
template<IP>
UVWError bind(std::string, unsigned int, bool = false);
template<IP>
void connect(std::string, unsigned int, std::function<void(UVWError, Tcp &)>) noexcept;
UVWError accept(Tcp &tcp) {
return UVWError{uv_accept(get<uv_stream_t>(), tcp.get<uv_stream_t>())};
}
explicit operator bool() { return initialized; }
@ -61,24 +68,41 @@ private:
template<>
void Tcp::connect<Tcp::IPv4>(std::string ip, int port, std::function<void(UVWError, Tcp &)> cb) noexcept {
UVWError Tcp::bind<Tcp::IPv4>(std::string ip, unsigned int port, bool ipv6only) {
sockaddr_in addr;
uv_ip4_addr(ip.c_str(), port, &addr);
unsigned int flags = ipv6only ? UV_TCP_IPV6ONLY : 0;
return UVWError(uv_tcp_bind(get<uv_tcp_t>(), reinterpret_cast<const sockaddr*>(&addr), flags));}
template<>
UVWError Tcp::bind<Tcp::IPv6>(std::string ip, unsigned int port, bool ipv6only) {
sockaddr_in6 addr;
uv_ip6_addr(ip.c_str(), port, &addr);
unsigned int flags = ipv6only ? UV_TCP_IPV6ONLY : 0;
return UVWError(uv_tcp_bind(get<uv_tcp_t>(), reinterpret_cast<const sockaddr*>(&addr), flags));
}
template<>
void Tcp::connect<Tcp::IPv4>(std::string ip, unsigned int port, std::function<void(UVWError, Tcp &)> cb) noexcept {
sockaddr_in addr;
uv_ip4_addr(ip.c_str(), port, &addr);
using CBF = CallbackFactory<void(uv_connect_t *, int)>;
auto func = CBF::template once<&Tcp::connectCallback>(*this, cb);
auto err = uv_tcp_connect(conn.get(), get<uv_tcp_t>(), reinterpret_cast<const sockaddr*>(&addr), func);
if(err) { cb(UVWError{err}, *this); }
if(err) { error(err); }
}
template<>
void Tcp::connect<Tcp::IPv6>(std::string ip, int port, std::function<void(UVWError, Tcp &)> cb) noexcept {
void Tcp::connect<Tcp::IPv6>(std::string ip, unsigned int port, std::function<void(UVWError, Tcp &)> cb) noexcept {
sockaddr_in6 addr;
uv_ip6_addr(ip.c_str(), port, &addr);
using CBF = CallbackFactory<void(uv_connect_t *, int)>;
auto func = CBF::template once<&Tcp::connectCallback>(*this, cb);
auto err = uv_tcp_connect(conn.get(), get<uv_tcp_t>(), reinterpret_cast<const sockaddr*>(&addr), func);
if(err) { cb(UVWError{err}, *this); }
if(err) { error(err); }
}

View File

@ -36,7 +36,7 @@ public:
using CBF = CallbackFactory<void(uv_timer_t *)>;
auto func = CBF::on<&Timer::startCallback>(*this, cb);
auto err = uv_timer_start(get<uv_timer_t>(), func, timeout.count(), rep.count());
if(err) { cb(UVWError{err}, *this); }
if(err) { error(err); }
}
UVWError stop() noexcept { return UVWError{uv_timer_stop(get<uv_timer_t>())}; }

View File

@ -2,23 +2,67 @@
#include <uvw.hpp>
void f(uvw::Loop &loop) {
void listen(uvw::Loop &loop) {
uvw::Handle<uvw::Tcp> handle = loop.handle<uvw::Tcp>();
auto cb = [](uvw::UVWError err, uvw::Tcp &tcp) mutable {
std::cout << "---" << ((bool)err) << std::endl;
tcp.close([](uvw::UVWError err, uvw::Tcp &) mutable {
std::cout << "---" << ((bool)err) << std::endl;
});
auto cb = [](uvw::UVWError err, uvw::Tcp &srv) mutable {
std::cout << "listen: " << ((bool)err) << std::endl;
if(!err) {
uvw::Handle<uvw::Tcp> handle = srv.loop().handle<uvw::Tcp>();
uvw::Tcp &client = handle;
err = srv.accept(client);
std::cout << "accept: " << ((bool)err) << std::endl;
if(!err) {
client.close([handle = srv.handle()](uvw::UVWError err, uvw::Tcp &) mutable {
std::cout << "close: " << ((bool)err) << std::endl;
uvw::Tcp &srv = handle;
srv.close([](uvw::UVWError err, uvw::Tcp &) mutable {
std::cout << "close: " << ((bool)err) << std::endl;
});
});
}
}
};
uvw::Tcp &tcp = handle;
tcp.connect<uvw::Tcp::IPv4>(std::string{"127.0.0.1"}, 80, cb);
uvw::UVWError err = tcp.bind<uvw::Tcp::IPv4>("127.0.0.1", 4242);
std::cout << "bind: " << ((bool)err) << std::endl;
if(err) {
tcp.close([](uvw::UVWError err, uvw::Tcp &) mutable {
std::cout << "close: " << ((bool)err) << std::endl;
});
} else {
tcp.listen(0, cb);
}
}
void conn(uvw::Loop &loop) {
uvw::Handle<uvw::Tcp> handle = loop.handle<uvw::Tcp>();
auto cb = [](uvw::UVWError err, uvw::Tcp &tcp) mutable {
std::cout << "connect: " << ((bool)err) << std::endl;
auto cb = [](uvw::UVWError err, uvw::Tcp &tcp) mutable {
std::cout << "close: " << ((bool)err) << std::endl;
};
tcp.close(cb);
};
uvw::Tcp &tcp = handle;
tcp.connect<uvw::Tcp::IPv4>(std::string{"127.0.0.1"}, 4242, cb);
}
void g() {
auto loop = uvw::Loop::getDefault();
f(*loop);
listen(*loop);
conn(*loop);
loop->run();
loop = nullptr;
}