WIP: safer callbacks
This commit is contained in:
parent
d030c5c6f6
commit
8714fcf24a
@ -12,8 +12,8 @@ namespace uvw {
|
||||
|
||||
|
||||
class Check final: public Resource<Check> {
|
||||
static void proto(uv_check_t* h) {
|
||||
static_cast<Check*>(h->data)->callback(UVWError{});
|
||||
static void startCallback(uv_check_t* h) {
|
||||
static_cast<Check*>(h->data)->startCb(UVWError{});
|
||||
}
|
||||
|
||||
explicit Check(std::shared_ptr<Loop> ref)
|
||||
@ -23,20 +23,18 @@ class Check final: public Resource<Check> {
|
||||
}
|
||||
|
||||
public:
|
||||
using Callback = std::function<void(UVWError)>;
|
||||
|
||||
template<typename... Args>
|
||||
static std::shared_ptr<Check> create(Args&&... args) {
|
||||
return std::shared_ptr<Check>{new Check{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
void start(Callback cb) noexcept {
|
||||
callback = std::move(cb);
|
||||
void start(std::function<void(UVWError)> cb) noexcept {
|
||||
startCb = std::move(cb);
|
||||
get<uv_check_t>()->data = this;
|
||||
auto err = uv_check_start(get<uv_check_t>(), &proto);
|
||||
auto err = uv_check_start(get<uv_check_t>(), &startCallback);
|
||||
|
||||
if(err) {
|
||||
callback(UVWError{err});
|
||||
startCb(UVWError{err});
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +43,7 @@ public:
|
||||
explicit operator bool() { return initialized; }
|
||||
|
||||
private:
|
||||
Callback callback;
|
||||
std::function<void(UVWError)> startCb;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
|
||||
@ -59,7 +59,8 @@ private:
|
||||
|
||||
|
||||
class Loop final: public std::enable_shared_from_this<Loop> {
|
||||
friend class BaseResource;
|
||||
template<typename>
|
||||
friend class Resource;
|
||||
|
||||
using Deleter = std::function<void(uv_loop_t *)>;
|
||||
|
||||
|
||||
@ -15,24 +15,55 @@ template<typename>
|
||||
struct HandleType { };
|
||||
|
||||
|
||||
class BaseResource {
|
||||
template<typename>
|
||||
class Resource;
|
||||
|
||||
|
||||
template<typename>
|
||||
struct UVCallback;
|
||||
|
||||
|
||||
template<typename... Args>
|
||||
struct UVCallback<Args...> {
|
||||
template<typename T, T*(*F)(Args...)>
|
||||
static auto get(T *res);
|
||||
|
||||
private:
|
||||
template<typename T, T*(*F)(Args...)>
|
||||
static void proto(Args... args);
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class Resource: public std::enable_shared_from_this<T> {
|
||||
template<typename>
|
||||
friend struct UVCallback;
|
||||
|
||||
static Resource<T>* closeCallback(uv_handle_t* h) {
|
||||
auto ptr = static_cast<Resource<T>*>(h->data);
|
||||
ptr->closeCb(UVWError{});
|
||||
return ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
explicit BaseResource(HandleType<T>, std::shared_ptr<Loop> r)
|
||||
: pLoop{std::move(r)}, handle{std::make_shared<T>()}
|
||||
template<typename U>
|
||||
explicit Resource(HandleType<U>, std::shared_ptr<Loop> r)
|
||||
: pLoop{std::move(r)}, handle{std::make_shared<U>()}
|
||||
{ }
|
||||
|
||||
template<typename T>
|
||||
T* get() const noexcept { return reinterpret_cast<T*>(handle.get()); }
|
||||
template<typename U>
|
||||
U* get() const noexcept { return reinterpret_cast<U*>(handle.get()); }
|
||||
|
||||
uv_loop_t* parent() const noexcept { return pLoop->loop.get(); }
|
||||
|
||||
public:
|
||||
explicit BaseResource(const BaseResource &) = delete;
|
||||
explicit BaseResource(BaseResource &&) = delete;
|
||||
explicit Resource(const Resource &) = delete;
|
||||
explicit Resource(Resource &&) = delete;
|
||||
|
||||
void operator=(const BaseResource &) = delete;
|
||||
void operator=(BaseResource &&) = delete;
|
||||
~Resource() { static_assert(std::is_base_of<Resource<T>, T>::value, "!"); }
|
||||
|
||||
void operator=(const Resource &) = delete;
|
||||
void operator=(Resource &&) = delete;
|
||||
|
||||
std::shared_ptr<Loop> loop() const noexcept { return pLoop; }
|
||||
|
||||
@ -43,33 +74,35 @@ public:
|
||||
void unreference() noexcept { uv_ref(get<uv_handle_t>()); }
|
||||
bool referenced() const noexcept { return !(uv_has_ref(get<uv_handle_t>()) == 0); }
|
||||
|
||||
void close(std::function<void(UVWError)> cb) noexcept {
|
||||
using UVCB = UVCallback<uv_handle_t*>;
|
||||
auto func = UVCB::get<Resource<T>, &closeCallback>(this);
|
||||
closeCb = 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> ref;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class Resource: public std::enable_shared_from_this<T>, public BaseResource {
|
||||
static void proto(uv_handle_t* h) {
|
||||
static_cast<Resource<T>*>(h->data)->callback(UVWError{});
|
||||
}
|
||||
template<typename... Args>
|
||||
template<typename T, T*(*F)(Args...)>
|
||||
void UVCallback<Args...>::proto(Args... args) {
|
||||
T *res = F(std::forward<Args>(args)...);
|
||||
res->ref = nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
using BaseResource::BaseResource;
|
||||
|
||||
public:
|
||||
using Callback = std::function<void(UVWError)>;
|
||||
|
||||
void close(Callback cb) noexcept {
|
||||
callback = std::move(cb);
|
||||
get<uv_handle_t>()->data = this;
|
||||
uv_close(get<uv_handle_t>(), &proto);
|
||||
}
|
||||
|
||||
private:
|
||||
Callback callback;
|
||||
};
|
||||
template<typename... Args>
|
||||
template<typename T, T*(*F)(Args...)>
|
||||
auto UVCallback<Args...>::get(T *res) {
|
||||
res->template get<uv_handle_t>()->data = res;
|
||||
res->ref = res->shared_from_this();
|
||||
return &proto<T, F>;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -8,9 +8,8 @@ void f(uvw::Loop &loop) {
|
||||
auto cb = [handle](uvw::UVWError err) mutable {
|
||||
std::cout << "---" << ((bool)err) << std::endl;
|
||||
uvw::Tcp &tcp = handle;
|
||||
tcp.close([handle](uvw::UVWError err) mutable {
|
||||
tcp.close([](uvw::UVWError err) mutable {
|
||||
std::cout << "---" << ((bool)err) << std::endl;
|
||||
handle = uvw::Handle<uvw::Tcp>{};
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user