added common base class Resource for Request and Handle

This commit is contained in:
Michele Caini 2016-07-14 22:36:20 +02:00
parent 29c8d22a6f
commit a3b75c1745
14 changed files with 122 additions and 91 deletions

View File

@ -7,6 +7,7 @@
#include "uvw/loop.hpp"
#include "uvw/prepare.hpp"
#include "uvw/request.hpp"
#include "uvw/resource.hpp"
#include "uvw/self.hpp"
#include "uvw/signal.hpp"
#include "uvw/stream.hpp"

View File

@ -19,7 +19,7 @@ class Async final: public Handle<Async> {
}
explicit Async(std::shared_ptr<Loop> ref)
: Handle{HandleType<uv_async_t>{}, std::move(ref)}
: Handle{ResourceType<uv_async_t>{}, std::move(ref)}
{ }
public:

View File

@ -19,7 +19,7 @@ class Check final: public Handle<Check> {
}
explicit Check(std::shared_ptr<Loop> ref)
: Handle{HandleType<uv_check_t>{}, std::move(ref)}
: Handle{ResourceType<uv_check_t>{}, std::move(ref)}
{ }
public:

View File

@ -4,42 +4,14 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "emitter.hpp"
#include "self.hpp"
#include "loop.hpp"
#include "resource.hpp"
namespace uvw {
template<typename>
struct HandleType;
template<> struct HandleType<uv_async_t> { };
template<> struct HandleType<uv_check_t> { };
template<> struct HandleType<uv_idle_t> { };
template<> struct HandleType<uv_prepare_t> { };
template<> struct HandleType<uv_signal_t> { };
template<> struct HandleType<uv_tcp_t> { };
template<> struct HandleType<uv_timer_t> { };
template<> struct HandleType<uv_tty_t> { };
template<typename T>
class Handle: public BaseHandle, public Emitter<T>, public Self<T> {
struct BaseWrapper {
virtual ~BaseWrapper() = default;
virtual void * get() const noexcept = 0;
};
template<typename U>
struct Wrapper: BaseWrapper {
Wrapper(): handle{std::make_unique<U>()} { }
void * get() const noexcept override { return handle.get(); }
private:
std::unique_ptr<U> handle;
};
class Handle: public BaseHandle, public Resource<T> {
static void closeCallback(uv_handle_t *handle) {
Handle<T> &ref = *(static_cast<T*>(handle->data));
auto ptr = ref.shared_from_this();
@ -49,25 +21,15 @@ class Handle: public BaseHandle, public Emitter<T>, public Self<T> {
protected:
template<typename U>
explicit Handle(HandleType<U>, std::shared_ptr<Loop> ref)
explicit Handle(ResourceType<U> rt, std::shared_ptr<Loop> ref)
: BaseHandle{},
Emitter<T>{},
Self<T>{},
wrapper{std::make_unique<Wrapper<U>>()},
pLoop{std::move(ref)}
{
this->template get<uv_handle_t>()->data = static_cast<T*>(this);
}
uv_loop_t* parent() const noexcept { return pLoop->loop.get(); }
template<typename U>
U* get() const noexcept { return reinterpret_cast<U*>(wrapper->get()); }
Resource<T>{std::move(rt), std::move(ref)}
{ }
template<typename U, typename F, typename... Args>
bool initialize(F &&f, Args&&... args) {
if(!this->self()) {
auto err = std::forward<F>(f)(parent(), get<U>(), std::forward<Args>(args)...);
auto err = std::forward<F>(f)(this->parent(), this->template get<U>(), std::forward<Args>(args)...);
if(err) {
this->publish(ErrorEvent{err});
@ -79,36 +41,32 @@ protected:
return this->self();
}
template<typename F, typename... Args>
auto invoke(F &&f, Args&&... args) {
auto err = std::forward<F>(f)(std::forward<Args>(args)...);
if(err) { Emitter<T>::publish(ErrorEvent{err}); }
return err;
}
public:
virtual ~Handle() {
static_assert(std::is_base_of<Handle<T>, T>::value, "!");
bool active() const noexcept override {
return !(uv_is_active(this->template get<uv_handle_t>()) == 0);
}
Loop& loop() const noexcept { return *pLoop; }
bool closing() const noexcept override {
return !(uv_is_closing(this->template get<uv_handle_t>()) == 0);
}
bool active() const noexcept override { return !(uv_is_active(get<uv_handle_t>()) == 0); }
bool closing() const noexcept override { return !(uv_is_closing(get<uv_handle_t>()) == 0); }
void reference() noexcept override {
uv_ref(this->template get<uv_handle_t>());
}
void reference() noexcept override { uv_ref(get<uv_handle_t>()); }
void unreference() noexcept override { uv_unref(get<uv_handle_t>()); }
bool referenced() const noexcept override { return !(uv_has_ref(get<uv_handle_t>()) == 0); }
void unreference() noexcept override {
uv_unref(this->template get<uv_handle_t>());
}
bool referenced() const noexcept override {
return !(uv_has_ref(this->template get<uv_handle_t>()) == 0);
}
void close() noexcept override {
if(!closing()) {
uv_close(get<uv_handle_t>(), &Handle<T>::closeCallback);
uv_close(this->template get<uv_handle_t>(), &Handle<T>::closeCallback);
}
}
private:
std::unique_ptr<BaseWrapper> wrapper;
std::shared_ptr<Loop> pLoop;
};

View File

@ -19,7 +19,7 @@ class Idle final: public Handle<Idle> {
}
explicit Idle(std::shared_ptr<Loop> ref)
: Handle{HandleType<uv_idle_t>{}, std::move(ref)}
: Handle{ResourceType<uv_idle_t>{}, std::move(ref)}
{ }
public:

View File

@ -26,7 +26,7 @@ public:
class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop> {
template<typename>
friend class Handle;
friend class Resource;
using Deleter = std::function<void(uv_loop_t *)>;

View File

@ -19,7 +19,7 @@ class Prepare final: public Handle<Prepare> {
}
explicit Prepare(std::shared_ptr<Loop> ref)
: Handle{HandleType<uv_prepare_t>{}, std::move(ref)}
: Handle{ResourceType<uv_prepare_t>{}, std::move(ref)}
{ }
public:

View File

@ -1,28 +1,22 @@
#pragma once
#include <utility>
#include <memory>
#include <uv.h>
#include "resource.hpp"
namespace uvw {
template<uv_req_type>
struct RequestType;
template<> struct RequestType<UV_CONNECT> { };
template<> struct RequestType<UV_WRITE> { };
template<> struct RequestType<UV_SHUTDOWN> { };
template<> struct RequestType<UV_UDP_SEND> { };
template<> struct RequestType<UV_FS> { };
template<> struct RequestType<UV_WORK> { };
template<> struct RequestType<UV_GETADDRINFO> { };
template<> struct RequestType<UV_GETNAMEINFO> { };
template<typename T>
struct Request: T {
// TODO room for a pointer to a memory pool and a better memory management
class Request: public Resource<T> {
protected:
template<typename U>
explicit Request(ResourceType<U> rt, std::shared_ptr<Loop> ref)
: Resource<T>{std::move(rt), std::move(ref)}
{ }
};

79
src/uvw/resource.hpp Normal file
View File

@ -0,0 +1,79 @@
#pragma once
#include <utility>
#include <memory>
#include <uv.h>
#include "emitter.hpp"
#include "self.hpp"
#include "loop.hpp"
namespace uvw {
template<typename>
struct ResourceType;
template<> struct ResourceType<uv_async_t> { };
template<> struct ResourceType<uv_check_t> { };
template<> struct ResourceType<uv_idle_t> { };
template<> struct ResourceType<uv_prepare_t> { };
template<> struct ResourceType<uv_signal_t> { };
template<> struct ResourceType<uv_tcp_t> { };
template<> struct ResourceType<uv_timer_t> { };
template<> struct ResourceType<uv_tty_t> { };
template<typename T>
class Resource: public Emitter<T>, public Self<T> {
struct BaseWrapper {
virtual ~BaseWrapper() = default;
virtual void * get() const noexcept = 0;
};
template<typename U>
struct Wrapper: BaseWrapper {
Wrapper(): resource{std::make_unique<U>()} { }
void * get() const noexcept override { return resource.get(); }
private:
std::unique_ptr<U> resource;
};
protected:
template<typename U>
explicit Resource(ResourceType<U>, std::shared_ptr<Loop> ref)
: Emitter<T>{},
Self<T>{},
wrapper{std::make_unique<Wrapper<U>>()},
pLoop{std::move(ref)}
{
this->template get<U>()->data = static_cast<T*>(this);
}
uv_loop_t* parent() const noexcept { return pLoop->loop.get(); }
template<typename U>
U* get() const noexcept { return reinterpret_cast<U*>(wrapper->get()); }
template<typename F, typename... Args>
auto invoke(F &&f, Args&&... args) {
auto err = std::forward<F>(f)(std::forward<Args>(args)...);
if(err) { Emitter<T>::publish(ErrorEvent{err}); }
return err;
}
public:
virtual ~Resource() {
static_assert(std::is_base_of<Resource<T>, T>::value, "!");
}
Loop& loop() const noexcept { return *pLoop; }
private:
std::unique_ptr<BaseWrapper> wrapper;
std::shared_ptr<Loop> pLoop;
};
}

View File

@ -19,7 +19,7 @@ class Signal final: public Handle<Signal> {
}
explicit Signal(std::shared_ptr<Loop> ref)
: Handle{HandleType<uv_signal_t>{}, std::move(ref)}
: Handle{ResourceType<uv_signal_t>{}, std::move(ref)}
{ }
public:

View File

@ -57,9 +57,8 @@ class Stream: public Handle<T> {
protected:
template<typename U>
Stream(HandleType<U> rt, std::shared_ptr<Loop> ref)
: Handle<T>{std::move(rt),
std::move(ref)},
Stream(ResourceType<U> rt, std::shared_ptr<Loop> ref)
: Handle<T>{std::move(rt), std::move(ref)},
sdown{std::make_unique<uv_shutdown_t>()}
{ }

View File

@ -22,7 +22,7 @@ class Tcp final: public Stream<Tcp> {
}
explicit Tcp(std::shared_ptr<Loop> ref)
: Stream{HandleType<uv_tcp_t>{}, std::move(ref)},
: Stream{ResourceType<uv_tcp_t>{}, std::move(ref)},
conn{std::make_unique<uv_connect_t>()}
{ }

View File

@ -20,7 +20,7 @@ class Timer final: public Handle<Timer> {
}
explicit Timer(std::shared_ptr<Loop> ref)
: Handle{HandleType<uv_timer_t>{}, std::move(ref)}
: Handle{ResourceType<uv_timer_t>{}, std::move(ref)}
{ }
public:

View File

@ -31,7 +31,7 @@ class TTY final: public Stream<TTY> {
explicit TTY(std::shared_ptr<Loop> ref,
details::FileDescriptor<FD>,
bool readable)
: Stream{HandleType<uv_tty_t>{}, std::move(ref)},
: Stream{ResourceType<uv_tty_t>{}, std::move(ref)},
fd{FD},
rw{readable ? 1 : 0}
{ }