added common base class Resource for Request and Handle
This commit is contained in:
parent
29c8d22a6f
commit
a3b75c1745
@ -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"
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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 *)>;
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
79
src/uvw/resource.hpp
Normal 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;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@ -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:
|
||||
|
||||
@ -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>()}
|
||||
{ }
|
||||
|
||||
|
||||
@ -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>()}
|
||||
{ }
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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}
|
||||
{ }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user