WIP: requests + refactoring
This commit is contained in:
parent
176a8f0b31
commit
09acc1accf
@ -5,7 +5,7 @@
|
||||
#include "uvw/idle.hpp"
|
||||
#include "uvw/loop.hpp"
|
||||
#include "uvw/prepare.hpp"
|
||||
#include "uvw/resource.hpp"
|
||||
#include "uvw/request.hpp"
|
||||
#include "uvw/self.hpp"
|
||||
#include "uvw/stream.hpp"
|
||||
#include "uvw/tcp.hpp"
|
||||
|
||||
@ -17,11 +17,7 @@ class Check final: public Handle<Check> {
|
||||
check.publish(CheckEvent{});
|
||||
}
|
||||
|
||||
explicit Check(std::shared_ptr<Loop> ref)
|
||||
: Handle{ResourceType<uv_check_t>{}, std::move(ref)}
|
||||
{
|
||||
initialized = (uv_check_init(parent(), get<uv_check_t>()) == 0);
|
||||
}
|
||||
using Handle<Check>::Handle;
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
@ -29,9 +25,13 @@ public:
|
||||
return std::shared_ptr<Check>{new Check{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
bool init() {
|
||||
return Handle<Check>::init<uv_check_t>(&uv_check_init);
|
||||
}
|
||||
|
||||
void start() {
|
||||
using CBF = CallbackFactory<void(uv_check_t *)>;
|
||||
auto func = CBF::create<&Check::startCallback>(*this);
|
||||
auto func = &CBF::template proto<&Check::startCallback>;
|
||||
auto err = uv_check_start(get<uv_check_t>(), func);
|
||||
if(err) publish(ErrorEvent{err});
|
||||
}
|
||||
@ -41,10 +41,8 @@ public:
|
||||
if(err) publish(ErrorEvent{err});
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept { return initialized; }
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
bool initialized = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -32,6 +32,12 @@ struct CheckEvent: Event<CheckEvent> { };
|
||||
struct CloseEvent: Event<CloseEvent> { };
|
||||
struct ConnectEvent: Event<ConnectEvent> { };
|
||||
|
||||
struct DataEvent: Event<DataEvent> {
|
||||
Buffer buffer{};
|
||||
};
|
||||
|
||||
struct EndEvent: Event<EndEvent> { };
|
||||
|
||||
struct ErrorEvent: Event<ErrorEvent> {
|
||||
explicit ErrorEvent(int code = 0): ec(code) { }
|
||||
|
||||
@ -47,6 +53,8 @@ struct ListenEvent: Event<ListenEvent> { };
|
||||
struct PrepareEvent: Event<PrepareEvent> { };
|
||||
struct ShutdownEvent: Event<ShutdownEvent> { };
|
||||
struct TimerEvent: Event<TimerEvent> { };
|
||||
struct UninitializedEvent: Event<UninitializedEvent> { };
|
||||
struct WriteEvent: Event<WriteEvent> { };
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <uv.h>
|
||||
#include "emitter.hpp"
|
||||
#include "resource.hpp"
|
||||
#include "self.hpp"
|
||||
#include "loop.hpp"
|
||||
|
||||
@ -24,10 +24,6 @@ struct UVCallbackFactory;
|
||||
|
||||
template<typename T, typename H, typename... Args>
|
||||
struct UVCallbackFactory<T, void(H, Args...)> {
|
||||
template<void(*F)(T &, H, Args...)>
|
||||
static auto create(T &) noexcept;
|
||||
|
||||
private:
|
||||
template<void(*F)(T &, H, Args...)>
|
||||
static void proto(H, Args...) noexcept;
|
||||
};
|
||||
@ -36,13 +32,37 @@ private:
|
||||
}
|
||||
|
||||
|
||||
template<typename>
|
||||
struct HandleType;
|
||||
|
||||
template<> struct HandleType<uv_timer_t> { };
|
||||
template<> struct HandleType<uv_prepare_t> { };
|
||||
template<> struct HandleType<uv_check_t> { };
|
||||
template<> struct HandleType<uv_idle_t> { };
|
||||
template<> struct HandleType<uv_tcp_t> { };
|
||||
|
||||
|
||||
template<typename T>
|
||||
class Handle: public Emitter<T>, public Self<T>, public ResourceWrapper {
|
||||
class Handle: public Emitter<T>, public Self<T> {
|
||||
template<typename, typename>
|
||||
friend struct details::UVCallbackFactory;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
static void closeCallback(T &ref, uv_handle_t *) {
|
||||
ref.publish(CloseEvent{});
|
||||
ref.reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -50,12 +70,37 @@ protected:
|
||||
using CallbackFactory = details::UVCallbackFactory<T, F>;
|
||||
|
||||
template<typename U>
|
||||
explicit Handle(ResourceType<U> rt, std::shared_ptr<Loop> ref)
|
||||
: Emitter<T>{}, Self<T>{}, ResourceWrapper{std::move(rt)}, pLoop{std::move(ref)}
|
||||
{ }
|
||||
explicit Handle(HandleType<U>, std::shared_ptr<Loop> ref)
|
||||
: 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()); }
|
||||
|
||||
template<typename U, typename F>
|
||||
bool init(F &&f) {
|
||||
bool ret = true;
|
||||
|
||||
if(!active()) {
|
||||
auto err = std::forward<F>(f)(parent(), get<U>());
|
||||
|
||||
if(err) {
|
||||
this->publish(ErrorEvent{err});
|
||||
ret = false;
|
||||
} else {
|
||||
this->leak();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~Handle() {
|
||||
static_assert(std::is_base_of<Handle<T>, T>::value, "!");
|
||||
@ -71,17 +116,15 @@ public:
|
||||
bool referenced() const noexcept { return !(uv_has_ref(get<uv_handle_t>()) == 0); }
|
||||
|
||||
void close() noexcept {
|
||||
auto handle = get<uv_handle_t>();
|
||||
|
||||
if(!uv_is_closing(handle)) {
|
||||
if(!closing()) {
|
||||
using CBF = CallbackFactory<void(uv_handle_t *)>;
|
||||
T &ref = *static_cast<T*>(this);
|
||||
auto func = CBF::template create<&Handle<T>::closeCallback>(ref);
|
||||
uv_close(handle, func);
|
||||
auto func = &CBF::template proto<&Handle<T>::closeCallback>;
|
||||
uv_close(get<uv_handle_t>(), func);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<BaseWrapper> wrapper;
|
||||
std::shared_ptr<Loop> pLoop;
|
||||
};
|
||||
|
||||
@ -89,28 +132,11 @@ private:
|
||||
namespace details {
|
||||
|
||||
|
||||
template<typename T, typename H, typename... Args>
|
||||
template<void(*F)(T &, H, Args...)>
|
||||
auto UVCallbackFactory<T, void(H, Args...)>::create(T &ref) noexcept {
|
||||
Handle<T> &handle = ref;
|
||||
handle.leak();
|
||||
handle.template get<uv_handle_t>()->data = &ref;
|
||||
return &UVCallbackFactory<T, void(H, Args...)>::proto<F>;
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename H, typename... Args>
|
||||
template<void(*F)(T &, H, Args...)>
|
||||
void UVCallbackFactory<T, void(H, Args...)>::proto(H handle, Args... args) noexcept {
|
||||
T &ref = *(static_cast<T*>(details::get(handle)));
|
||||
|
||||
if(0 == uv_is_active(ref.template get<uv_handle_t>())) {
|
||||
auto ptr = ref.shared_from_this();
|
||||
ref.reset();
|
||||
F(*ptr, handle, args...);
|
||||
} else {
|
||||
F(ref, handle, args...);
|
||||
}
|
||||
F(ref, handle, args...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -17,11 +17,7 @@ class Idle final: public Handle<Idle> {
|
||||
idle.publish(IdleEvent{});
|
||||
}
|
||||
|
||||
explicit Idle(std::shared_ptr<Loop> ref)
|
||||
: Handle{ResourceType<uv_idle_t>{}, std::move(ref)}
|
||||
{
|
||||
initialized = (uv_idle_init(parent(), get<uv_idle_t>()) == 0);
|
||||
}
|
||||
using Handle<Idle>::Handle;
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
@ -29,9 +25,13 @@ public:
|
||||
return std::shared_ptr<Idle>{new Idle{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
bool init() {
|
||||
return Handle<Idle>::init<uv_idle_t>(&uv_idle_init);
|
||||
}
|
||||
|
||||
void start() {
|
||||
using CBF = CallbackFactory<void(uv_idle_t *)>;
|
||||
auto func = CBF::create<&Idle::startCallback>(*this);
|
||||
auto func = &CBF::template proto<&Idle::startCallback>;
|
||||
auto err = uv_idle_start(get<uv_idle_t>(), func);
|
||||
if(err) publish(ErrorEvent{err});
|
||||
}
|
||||
@ -40,11 +40,6 @@ public:
|
||||
auto err = uv_idle_stop(get<uv_idle_t>());
|
||||
if(err) publish(ErrorEvent{err});
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept { return initialized; }
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -66,7 +66,9 @@ public:
|
||||
|
||||
template<typename R, typename... Args>
|
||||
std::shared_ptr<R> resource(Args&&... args) {
|
||||
return R::create(shared_from_this(), std::forward<Args>(args)...);
|
||||
auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
|
||||
ptr = ptr->init() ? ptr : nullptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void close() noexcept {
|
||||
|
||||
@ -17,11 +17,7 @@ class Prepare final: public Handle<Prepare> {
|
||||
prepare.publish(PrepareEvent{});
|
||||
}
|
||||
|
||||
explicit Prepare(std::shared_ptr<Loop> ref)
|
||||
: Handle{ResourceType<uv_prepare_t>{}, std::move(ref)}
|
||||
{
|
||||
initialized = (uv_prepare_init(parent(), get<uv_prepare_t>()) == 0);
|
||||
}
|
||||
using Handle<Prepare>::Handle;
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
@ -29,9 +25,13 @@ public:
|
||||
return std::shared_ptr<Prepare>{new Prepare{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
bool init() {
|
||||
return Handle<Prepare>::init<uv_prepare_t>(&uv_prepare_init);
|
||||
}
|
||||
|
||||
void start() {
|
||||
using CBF = CallbackFactory<void(uv_prepare_t *)>;
|
||||
auto func = CBF::create<&Prepare::startCallback>(*this);
|
||||
auto func = &CBF::template proto<&Prepare::startCallback>;
|
||||
auto err = uv_prepare_start(get<uv_prepare_t>(), func);
|
||||
if(err) publish(ErrorEvent{err});
|
||||
}
|
||||
@ -40,11 +40,6 @@ public:
|
||||
auto err = uv_prepare_stop(get<uv_prepare_t>());
|
||||
if(err) publish(ErrorEvent{err});
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept { return initialized; }
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
|
||||
|
||||
29
src/uvw/request.hpp
Normal file
29
src/uvw/request.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
|
||||
template<typename>
|
||||
struct ResourceType { };
|
||||
|
||||
|
||||
class ResourceWrapper {
|
||||
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;
|
||||
};
|
||||
|
||||
protected:
|
||||
template<typename U>
|
||||
explicit ResourceWrapper(ResourceType<U>)
|
||||
: wrapper{std::make_unique<Wrapper<U>>()}
|
||||
{ }
|
||||
|
||||
virtual ~ResourceWrapper() = default;
|
||||
|
||||
template<typename U>
|
||||
U* get() const noexcept { return reinterpret_cast<U*>(wrapper->get()); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<BaseWrapper> wrapper;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@ -8,46 +8,51 @@
|
||||
#include <uv.h>
|
||||
#include "event.hpp"
|
||||
#include "handle.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
|
||||
template<typename T>
|
||||
class Stream;
|
||||
|
||||
|
||||
class Buffer final {
|
||||
template<typename>
|
||||
friend class Stream;
|
||||
|
||||
uv_buf_t uvBuf() const noexcept {
|
||||
return uv_buf_init(data.get(), size);
|
||||
}
|
||||
|
||||
public:
|
||||
Buffer(std::unique_ptr<char[]> dt, std::size_t s)
|
||||
: data{std::move(dt)}, size{s}
|
||||
{ }
|
||||
|
||||
Buffer(Buffer &&) = default;
|
||||
Buffer& operator=(Buffer &&) = default;
|
||||
|
||||
void reset(std::unique_ptr<char[]> dt, std::size_t s) noexcept {
|
||||
data.swap(dt);
|
||||
size = s;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<char[]> data;
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class Stream: public Handle<T> {
|
||||
static constexpr unsigned int DEFAULT_BACKLOG = 128;
|
||||
|
||||
static void allocCallback(T &, uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
|
||||
buf->base = new char[suggested];
|
||||
buf->len = suggested;
|
||||
}
|
||||
|
||||
static void readCallback(T &ref, uv_stream_t *, ssize_t nread, const uv_buf_t *cbuf) {
|
||||
uv_buf_t *buf = const_cast<uv_buf_t *>(cbuf);
|
||||
|
||||
if(nread == UV_EOF) {
|
||||
ref.publish(EndEvent{});
|
||||
delete buf->base;
|
||||
} else if(nread > 0) {
|
||||
std::unique_ptr<char[]> data{buf->base};
|
||||
DataEvent event;
|
||||
event.buffer.reset(std::move(data), nread);
|
||||
ref.publish(std::move(event));
|
||||
} else {
|
||||
ref.publish(ErrorEvent(nread));
|
||||
delete buf->base;
|
||||
}
|
||||
|
||||
buf->base = nullptr;
|
||||
buf->len = 0;
|
||||
}
|
||||
|
||||
static void writeCallback(T &ref, uv_write_t *req, int status) {
|
||||
if(status) {
|
||||
ref.publish(ErrorEvent{status});
|
||||
} else {
|
||||
ref.publish(WriteEvent{});
|
||||
}
|
||||
|
||||
delete req;
|
||||
}
|
||||
|
||||
static void shutdownCallback(T &ref, uv_shutdown_t *, int status) {
|
||||
if(status) ref.publish(ErrorEvent{status});
|
||||
else ref.publish(ShutdownEvent{});
|
||||
@ -60,21 +65,21 @@ class Stream: public Handle<T> {
|
||||
|
||||
protected:
|
||||
template<typename U>
|
||||
Stream(ResourceType<U> rt, std::shared_ptr<Loop> ref)
|
||||
Stream(HandleType<U> rt, std::shared_ptr<Loop> ref)
|
||||
: Handle<T>{std::move(rt), std::move(ref)}, sdown{std::make_unique<uv_shutdown_t>()}
|
||||
{ }
|
||||
|
||||
public:
|
||||
void shutdown() noexcept {
|
||||
using CBF = typename Handle<T>::template CallbackFactory<void(uv_shutdown_t *, int)>;
|
||||
auto func = CBF::template create<&Stream<T>::shutdownCallback>(*static_cast<T*>(this));
|
||||
auto func = &CBF::template proto<&Stream<T>::shutdownCallback>;
|
||||
auto err = uv_shutdown(sdown.get(), this->template get<uv_stream_t>(), func);
|
||||
if(err) this->publish(ErrorEvent{err});
|
||||
}
|
||||
|
||||
void listen(int backlog) noexcept {
|
||||
using CBF = typename Handle<T>::template CallbackFactory<void(uv_stream_t *, int)>;
|
||||
auto func = CBF::template create<&Stream<T>::listenCallback>(*static_cast<T*>(this));
|
||||
auto func = &CBF::template proto<&Stream<T>::listenCallback>;
|
||||
auto err = uv_listen(this->template get<uv_stream_t>(), backlog, func);
|
||||
if(err) this->publish(ErrorEvent{err});
|
||||
}
|
||||
@ -83,14 +88,31 @@ public:
|
||||
listen(DEFAULT_BACKLOG);
|
||||
}
|
||||
|
||||
// TODO read
|
||||
void read() {
|
||||
using CBFAlloc = typename Handle<T>::template CallbackFactory<void(uv_handle_t *, std::size_t, uv_buf_t *)>;
|
||||
using CBFRead = typename Handle<T>::template CallbackFactory<void(uv_stream_t *, ssize_t, const uv_buf_t *)>;
|
||||
auto allocFunc = &CBFAlloc::template proto<&Stream<T>::allocCallback>;
|
||||
auto readFunc = &CBFRead::template proto<&Stream<T>::readCallback>;
|
||||
auto err = uv_read_start(this->template get<uv_stream_t>(), allocFunc, readFunc);
|
||||
if(err) this->publish(ErrorEvent{err});
|
||||
}
|
||||
|
||||
void stop() noexcept {
|
||||
auto err = uv_read_stop(this->template get<uv_stream_t>());
|
||||
if(err) this->publish(ErrorEvent{err});
|
||||
}
|
||||
|
||||
// TODO write
|
||||
void write(Buffer buf) {
|
||||
using CBF = typename Handle<T>::template CallbackFactory<void(uv_write_t *, int)>;
|
||||
auto func = &CBF::template proto<&Stream<T>::writeCallback>;
|
||||
uv_buf_t data[] = { buf.uvBuf() };
|
||||
uv_write_t *req = new uv_write_t;
|
||||
auto err = uv_write(req, this->template get<uv_stream_t>(), data, 1, func);
|
||||
if(err) {
|
||||
delete req;
|
||||
this->publish(ErrorEvent{err});
|
||||
}
|
||||
}
|
||||
|
||||
int tryWrite(Buffer buf) noexcept {
|
||||
uv_buf_t data[] = { buf.uvBuf() };
|
||||
|
||||
@ -21,11 +21,9 @@ class Tcp final: public Stream<Tcp> {
|
||||
}
|
||||
|
||||
explicit Tcp(std::shared_ptr<Loop> ref)
|
||||
: Stream{ResourceType<uv_tcp_t>{}, std::move(ref)},
|
||||
: Stream{HandleType<uv_tcp_t>{}, std::move(ref)},
|
||||
conn{std::make_unique<uv_connect_t>()}
|
||||
{
|
||||
initialized = (uv_tcp_init(parent(), get<uv_tcp_t>()) == 0);
|
||||
}
|
||||
{ }
|
||||
|
||||
template<typename I, typename F, typename..., typename Traits = details::IpTraits<I>>
|
||||
Addr address(F &&f) {
|
||||
@ -63,6 +61,10 @@ public:
|
||||
return std::shared_ptr<Tcp>{new Tcp{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
bool init() {
|
||||
return Stream<Tcp>::init<uv_tcp_t>(&uv_tcp_init);
|
||||
}
|
||||
|
||||
void noDelay(bool value = false) noexcept {
|
||||
auto err = uv_tcp_nodelay(get<uv_tcp_t>(), value ? 1 : 0);
|
||||
if(err) publish(ErrorEvent{err});
|
||||
@ -102,7 +104,7 @@ public:
|
||||
typename Traits::Type addr;
|
||||
Traits::AddrFunc(ip.c_str(), port, &addr);
|
||||
using CBF = CallbackFactory<void(uv_connect_t *, int)>;
|
||||
auto func = CBF::create<&Tcp::connectCallback>(*this);
|
||||
auto func = &CBF::proto<&Tcp::connectCallback>;
|
||||
auto err = uv_tcp_connect(conn.get(), get<uv_tcp_t>(), reinterpret_cast<const sockaddr *>(&addr), func);
|
||||
if(err) publish(ErrorEvent{err});
|
||||
}
|
||||
|
||||
@ -18,11 +18,7 @@ class Timer final: public Handle<Timer> {
|
||||
timer.publish(TimerEvent{});
|
||||
}
|
||||
|
||||
explicit Timer(std::shared_ptr<Loop> ref)
|
||||
: Handle{ResourceType<uv_timer_t>{}, std::move(ref)}
|
||||
{
|
||||
initialized = (uv_timer_init(parent(), get<uv_timer_t>()) == 0);
|
||||
}
|
||||
using Handle<Timer>::Handle;
|
||||
|
||||
public:
|
||||
using Time = std::chrono::milliseconds;
|
||||
@ -32,9 +28,13 @@ public:
|
||||
return std::shared_ptr<Timer>{new Timer{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
bool init() {
|
||||
return Handle<Timer>::init<uv_timer_t>(&uv_timer_init);
|
||||
}
|
||||
|
||||
void start(Time timeout, Time repeat) {
|
||||
using CBF = CallbackFactory<void(uv_timer_t *)>;
|
||||
auto func = CBF::create<&Timer::startCallback>(*this);
|
||||
auto func = &CBF::template proto<&Timer::startCallback>;
|
||||
auto err = uv_timer_start(get<uv_timer_t>(), func, timeout.count(), repeat.count());
|
||||
if(err) publish(ErrorEvent{err});
|
||||
}
|
||||
@ -56,11 +56,6 @@ public:
|
||||
Time repeat() {
|
||||
return Time{uv_timer_get_repeat(get<uv_timer_t>())};
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept { return initialized; }
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -70,4 +70,33 @@ private:
|
||||
using Addr = std::pair<std::string, unsigned int>;
|
||||
|
||||
|
||||
class Buffer final {
|
||||
template<typename>
|
||||
friend class Stream;
|
||||
|
||||
uv_buf_t uvBuf() const noexcept {
|
||||
return uv_buf_init(data.get(), size);
|
||||
}
|
||||
|
||||
public:
|
||||
Buffer(): data{}, size{} { }
|
||||
|
||||
Buffer(std::unique_ptr<char[]> dt, std::size_t s)
|
||||
: data{std::move(dt)}, size{s}
|
||||
{ }
|
||||
|
||||
Buffer(Buffer &&) = default;
|
||||
Buffer& operator=(Buffer &&) = default;
|
||||
|
||||
void reset(std::unique_ptr<char[]> dt, std::size_t s) noexcept {
|
||||
data.swap(dt);
|
||||
size = s;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<char[]> data;
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -36,7 +36,16 @@ void listen(uvw::Loop &loop) {
|
||||
uvw::Addr remote = client->remote<uvw::Tcp::IPv4>();
|
||||
std::cout << "remote: " << remote.first << " " << remote.second << std::endl;
|
||||
|
||||
client->close();
|
||||
client->on<uvw::DataEvent>([](const uvw::DataEvent &event, uvw::Tcp &) {
|
||||
std::cout << "data" << std::endl;
|
||||
});
|
||||
|
||||
client->on<uvw::EndEvent>([](const uvw::EndEvent &, uvw::Tcp &client) {
|
||||
std::cout << "end" << std::endl;
|
||||
client.close();
|
||||
});
|
||||
|
||||
client->read();
|
||||
});
|
||||
|
||||
tcp->once<uvw::CloseEvent>([](const uvw::CloseEvent &, uvw::Tcp &) mutable {
|
||||
@ -55,11 +64,11 @@ void conn(uvw::Loop &loop) {
|
||||
std::cout << "error " << std::endl;
|
||||
});
|
||||
|
||||
tcp->once<uvw::ConnectEvent>([](const uvw::ConnectEvent &event, uvw::Tcp &tcp) mutable {
|
||||
tcp->once<uvw::ConnectEvent>([](const uvw::ConnectEvent &, uvw::Tcp &tcp) mutable {
|
||||
std::cout << "connect" << std::endl;
|
||||
|
||||
auto data = std::unique_ptr<char[]>(new char[1]);
|
||||
data[0] = 42;
|
||||
data[0] = 'a';
|
||||
uvw::Buffer buf{std::move(data), 1};
|
||||
int bw = tcp.tryWrite(std::move(buf));
|
||||
std::cout << "written: " << ((int)bw) << std::endl;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user