Merge pull request #28 from cynnyx/master

Review + FsEvent
This commit is contained in:
Michele Caini 2016-07-26 11:46:36 +02:00 committed by GitHub
commit 1aa256b30e
21 changed files with 269 additions and 136 deletions

View File

@ -2,6 +2,7 @@
#include "uvw/check.hpp"
#include "uvw/event.hpp"
#include "uvw/fs.hpp"
#include "uvw/fs_event.hpp"
#include "uvw/fs_poll.hpp"
#include "uvw/idle.hpp"
#include "uvw/lib.hpp"

View File

@ -12,6 +12,9 @@
namespace uvw {
struct AsyncEvent: Event<AsyncEvent> { };
class Async final: public Handle<Async, uv_async_t> {
static void sendCallback(uv_async_t *handle) {
Async &async = *(static_cast<Async*>(handle->data));

View File

@ -12,6 +12,9 @@
namespace uvw {
struct CheckEvent: Event<CheckEvent> { };
class Check final: public Handle<Check, uv_check_t> {
static void startCallback(uv_check_t *handle) {
Check &check = *(static_cast<Check*>(handle->data));

View File

@ -87,6 +87,9 @@ protected:
}
public:
template<typename E>
using Listener = typename Handler<E>::Listener;
template<typename E>
struct Connection: private Handler<E>::Connection {
template<typename> friend class Emitter;
@ -95,9 +98,6 @@ public:
{ }
};
template<typename E>
using Listener = typename Handler<E>::Listener;
virtual ~Emitter() noexcept {
static_assert(std::is_base_of<Emitter<T>, T>::value, "!");
}

View File

@ -21,6 +21,7 @@ struct BaseEvent {
BaseEvent::~BaseEvent() noexcept { }
template<typename E>
struct Event: BaseEvent {
static std::size_t type() noexcept {
@ -30,29 +31,6 @@ struct Event: BaseEvent {
};
struct AsyncEvent: Event<AsyncEvent> { };
struct CheckEvent: Event<CheckEvent> { };
struct CloseEvent: Event<CloseEvent> { };
struct ConnectEvent: Event<ConnectEvent> { };
struct DataEvent: Event<DataEvent> {
explicit DataEvent(std::unique_ptr<const char[]> ptr, ssize_t l) noexcept
: dt{std::move(ptr)}, len{l}
{ }
const char * data() const noexcept { return dt.get(); }
ssize_t length() const noexcept { return len; }
private:
std::unique_ptr<const char[]> dt;
const ssize_t len;
};
struct EndEvent: Event<EndEvent> { };
struct ErrorEvent: Event<ErrorEvent> {
explicit ErrorEvent(int code = 0) noexcept: ec(code) { }
@ -64,72 +42,4 @@ private:
};
template<typename E>
struct FlagsEvent: Event<FlagsEvent<E>> {
explicit FlagsEvent(Flags<E> f) noexcept: flgs{std::move(f)} { }
Flags<E> flags() const noexcept { return flgs; }
private:
Flags<E> flgs;
};
struct FsPollEvent: Event<FsPollEvent> {
explicit FsPollEvent(const Stat &p, const Stat &c) noexcept
: prev(p), curr(c)
{ }
const Stat & previous() const noexcept { return prev; }
const Stat & current() const noexcept { return curr; }
private:
Stat prev;
Stat curr;
};
struct IdleEvent: Event<IdleEvent> { };
struct ListenEvent: Event<ListenEvent> { };
struct PrepareEvent: Event<PrepareEvent> { };
struct SendEvent: Event<SendEvent> { };
struct ShutdownEvent: Event<ShutdownEvent> { };
struct SignalEvent: Event<SignalEvent> {
explicit SignalEvent(int sig) noexcept: signum(sig) { }
int signal() const noexcept { return signum; }
private:
const int signum;
};
struct TimerEvent: Event<TimerEvent> { };
struct UDPDataEvent: Event<UDPDataEvent> {
explicit UDPDataEvent(Addr addr, std::unique_ptr<const char[]> ptr, ssize_t l, bool trunc) noexcept
: dt{std::move(ptr)}, len{l}, sndr{addr}, part{trunc}
{ }
const char * data() const noexcept { return dt.get(); }
ssize_t length() const noexcept { return len; }
Addr sender() const noexcept { return sndr; }
bool partial() const noexcept { return part; }
private:
std::unique_ptr<const char[]> dt;
const ssize_t len;
Addr sndr;
const bool part;
};
struct UninitializedEvent: Event<UninitializedEvent> { };
struct WorkEvent: Event<WorkEvent> { };
struct WriteEvent: Event<WriteEvent> { };
}

View File

@ -53,7 +53,6 @@ class Fs final: public Request<Fs, uv_fs_t> {
public:
using Time = std::chrono::seconds;
using Flags = int;
using Mode = int;
using Offset = int64_t;

78
src/uvw/fs_event.hpp Normal file
View File

@ -0,0 +1,78 @@
#pragma once
#include <utility>
#include <string>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "util.hpp"
namespace uvw {
namespace details {
enum class UVFsEventFlags: std::underlying_type_t<uv_fs_event_flags> {
WATCH_ENTRY = UV_FS_EVENT_WATCH_ENTRY,
STAT = UV_FS_EVENT_STAT,
RECURSIVE = UV_FS_EVENT_RECURSIVE
};
enum class UVFsEvent: std::underlying_type_t<uv_fs_event> {
RENAME = UV_RENAME,
CHANGE = UV_CHANGE
};
}
struct FsEventEvent: Event<FsEventEvent> {
FsEventEvent(std::string fPath, Flags<details::UVFsEvent> f)
: flgs{std::move(f)}, relPath{std::move(fPath)}
{ }
const char * filename() const noexcept { return relPath.data(); }
Flags<details::UVFsEvent> flags() const noexcept { return flgs; }
private:
Flags<details::UVFsEvent> flgs;
std::string relPath;
};
class FsEvent final: public Handle<FsEvent, uv_fs_event_t> {
static void startCallback(uv_fs_event_t *handle, const char *filename, int events, int status) {
FsEvent &fsEvent = *(static_cast<FsEvent*>(handle->data));
if(status) { fsEvent.publish(ErrorEvent{status}); }
else { fsEvent.publish(FsEventEvent{filename, static_cast<std::underlying_type_t<Event>>(events)}); }
}
using Handle::Handle;
public:
using Watch = details::UVFsEvent;
using Event = details::UVFsEventFlags;
template<typename... Args>
static std::shared_ptr<FsEvent> create(Args&&... args) {
return std::shared_ptr<FsEvent>{new FsEvent{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_fs_event_t>(&uv_fs_event_init); }
void start(std::string path, Flags<Watch> flags = Flags<Watch>{}) {
invoke(&uv_fs_event_start, get<uv_fs_event_t>(), &startCallback, path.data(), flags);
}
void stop() { invoke(&uv_fs_event_stop, get<uv_fs_event_t>()); }
std::string path() noexcept { return details::path(&uv_fs_event_getpath, get<uv_fs_event_t>()); }
};
}

View File

@ -13,6 +13,20 @@
namespace uvw {
struct FsPollEvent: Event<FsPollEvent> {
explicit FsPollEvent(const Stat &p, const Stat &c) noexcept
: prev(p), curr(c)
{ }
const Stat & previous() const noexcept { return prev; }
const Stat & current() const noexcept { return curr; }
private:
Stat prev;
Stat curr;
};
class FsPoll final: public Handle<FsPoll, uv_fs_poll_t> {
static void startCallback(uv_fs_poll_t *handle, int status, const uv_stat_t *prev, const uv_stat_t *curr) {
FsPoll &fsPoll = *(static_cast<FsPoll*>(handle->data));

View File

@ -11,6 +11,9 @@
namespace uvw {
struct CloseEvent: Event<CloseEvent> { };
template<typename T, typename U>
class Handle: public BaseHandle, public Resource<T, U>
{

View File

@ -12,6 +12,9 @@
namespace uvw {
struct IdleEvent: Event<IdleEvent> { };
class Idle final: public Handle<Idle, uv_idle_t> {
static void startCallback(uv_idle_t *handle) {
Idle &idle = *(static_cast<Idle*>(handle->data));

View File

@ -14,6 +14,17 @@
namespace uvw {
namespace details {
enum class UVLoopOption: std::underlying_type_t<uv_loop_option> {
BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL
};
}
class BaseHandle {
public:
virtual bool active() const noexcept = 0;
@ -37,10 +48,7 @@ class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop
public:
using Time = std::chrono::milliseconds;
enum class Configure: std::underlying_type_t<uv_loop_option> {
BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL
};
using Configure = details::UVLoopOption;
static std::shared_ptr<Loop> create() {
auto ptr = std::unique_ptr<uv_loop_t, Deleter>{new uv_loop_t, [](uv_loop_t *l){ delete l; }};

View File

@ -15,16 +15,25 @@
namespace uvw {
namespace details {
enum class UVHandleType: std::underlying_type_t<uv_handle_type> {
UNKNOWN = UV_UNKNOWN_HANDLE,
PIPE = UV_NAMED_PIPE,
TCP = UV_TCP,
UDP = UV_UDP
};
}
class Pipe final: public Stream<Pipe, uv_pipe_t> {
using Stream::Stream;
public:
enum class Pending: std::underlying_type_t<uv_handle_type> {
UNKNOWN = UV_UNKNOWN_HANDLE,
PIPE = UV_NAMED_PIPE,
TCP = UV_TCP,
UDP = UV_UDP
};
using Pending = details::UVHandleType;
template<typename... Args>
static std::shared_ptr<Pipe> create(Args&&... args) {
@ -42,7 +51,7 @@ public:
}
void connect(std::string name) {
auto listener = [ptr = this->shared_from_this()](const auto &event, details::Connect &) {
auto listener = [ptr = shared_from_this()](const auto &event, details::Connect &) {
ptr->publish(event);
};

View File

@ -13,21 +13,42 @@
namespace uvw {
namespace details {
enum class UVPollEvent: std::underlying_type_t<uv_poll_event> {
READABLE = UV_READABLE,
WRITABLE = UV_WRITABLE,
DISCONNECT = UV_DISCONNECT
};
}
struct PollEvent: Event<PollEvent> {
explicit PollEvent(Flags<details::UVPollEvent> f) noexcept
: flgs{std::move(f)}
{ }
Flags<details::UVPollEvent> flags() const noexcept { return flgs; }
private:
Flags<details::UVPollEvent> flgs;
};
class Poll final: public Handle<Poll, uv_poll_t> {
static void startCallback(uv_poll_t *handle, int status, int events) {
Poll &poll = *(static_cast<Poll*>(handle->data));
if(status) { poll.publish(ErrorEvent{status}); }
else { poll.publish(FlagsEvent<Event>{static_cast<std::underlying_type_t<Event>>(events)}); }
else { poll.publish(PollEvent{static_cast<std::underlying_type_t<Event>>(events)}); }
}
using Handle::Handle;
public:
enum class Event: std::underlying_type_t<uv_poll_event> {
READABLE = UV_READABLE,
WRITABLE = UV_WRITABLE,
DISCONNECT = UV_DISCONNECT
};
using Event = details::UVPollEvent;
template<typename... Args>
static std::shared_ptr<Poll> create(Args&&... args) {

View File

@ -12,6 +12,9 @@
namespace uvw {
struct PrepareEvent: Event<PrepareEvent> { };
class Prepare final: public Handle<Prepare, uv_prepare_t> {
static void startCallback(uv_prepare_t *handle) {
Prepare &prepare = *(static_cast<Prepare*>(handle->data));

View File

@ -12,6 +12,16 @@
namespace uvw {
struct SignalEvent: Event<SignalEvent> {
explicit SignalEvent(int sig) noexcept: signum(sig) { }
int signal() const noexcept { return signum; }
private:
const int signum;
};
class Signal final: public Handle<Signal, uv_signal_t> {
static void startCallback(uv_signal_t *handle, int signum) {
Signal &signal = *(static_cast<Signal*>(handle->data));

View File

@ -15,6 +15,27 @@
namespace uvw {
struct ConnectEvent: Event<ConnectEvent> { };
struct EndEvent: Event<EndEvent> { };
struct ListenEvent: Event<ListenEvent> { };
struct ShutdownEvent: Event<ShutdownEvent> { };
struct WriteEvent: Event<WriteEvent> { };
struct DataEvent: Event<DataEvent> {
explicit DataEvent(std::unique_ptr<const char[]> ptr, ssize_t l) noexcept
: dt{std::move(ptr)}, len{l}
{ }
const char * data() const noexcept { return dt.get(); }
ssize_t length() const noexcept { return len; }
private:
std::unique_ptr<const char[]> dt;
const ssize_t len;
};
namespace details {

View File

@ -16,19 +16,26 @@
namespace uvw {
namespace details {
enum class UVTcpFlags: std::underlying_type_t<uv_tcp_flags> {
IPV6ONLY = UV_TCP_IPV6ONLY
};
}
class Tcp final: public Stream<Tcp, uv_tcp_t> {
using Stream::Stream;
public:
using Time = std::chrono::seconds;
using Bind = details::UVTcpFlags;
using IPv4 = details::IPv4;
using IPv6 = details::IPv6;
enum class Bind: std::underlying_type_t<uv_tcp_flags> {
IPV6ONLY = UV_TCP_IPV6ONLY
};
template<typename... Args>
static std::shared_ptr<Tcp> create(Args&&... args) {
return std::shared_ptr<Tcp>{new Tcp{std::forward<Args>(args)...}};
@ -84,7 +91,7 @@ public:
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::AddrFunc(ip.data(), port, &addr);
auto listener = [ptr = this->shared_from_this()](const auto &event, details::Connect &) {
auto listener = [ptr = shared_from_this()](const auto &event, details::Connect &) {
ptr->publish(event);
};

View File

@ -13,6 +13,9 @@
namespace uvw {
struct TimerEvent: Event<TimerEvent> { };
class Timer final: public Handle<Timer, uv_timer_t> {
static void startCallback(uv_timer_t *handle) {
Timer &timer = *(static_cast<Timer*>(handle->data));

View File

@ -13,6 +13,19 @@
namespace uvw {
namespace details {
enum class UVTTYModeT: std::underlying_type_t<uv_tty_mode_t> {
NORMAL = UV_TTY_MODE_NORMAL,
RAW = UV_TTY_MODE_RAW,
IO = UV_TTY_MODE_IO
};
}
class TTY final: public Stream<TTY, uv_tty_t> {
explicit TTY(std::shared_ptr<Loop> ref,
FileHandle desc,
@ -23,11 +36,7 @@ class TTY final: public Stream<TTY, uv_tty_t> {
{ }
public:
enum class Mode: std::underlying_type_t<uv_tty_mode_t> {
NORMAL = UV_TTY_MODE_NORMAL,
RAW = UV_TTY_MODE_RAW,
IO = UV_TTY_MODE_IO
};
using Mode = details::UVTTYModeT;
template<typename... Args>
static std::shared_ptr<TTY> create(Args&&... args) {

View File

@ -15,9 +15,42 @@
namespace uvw {
struct SendEvent: Event<SendEvent> { };
struct UDPDataEvent: Event<UDPDataEvent> {
explicit UDPDataEvent(Addr addr, std::unique_ptr<const char[]> ptr, ssize_t l, bool trunc) noexcept
: dt{std::move(ptr)}, len{l}, sndr{addr}, part{trunc}
{ }
const char * data() const noexcept { return dt.get(); }
ssize_t length() const noexcept { return len; }
Addr sender() const noexcept { return sndr; }
bool partial() const noexcept { return part; }
private:
std::unique_ptr<const char[]> dt;
const ssize_t len;
Addr sndr;
const bool part;
};
namespace details {
enum class UVUdpFlags: std::underlying_type_t<uv_udp_flags> {
IPV6ONLY = UV_UDP_IPV6ONLY,
REUSEADDR = UV_UDP_REUSEADDR
};
enum class UVMembership: std::underlying_type_t<uv_membership> {
LEAVE_GROUP = UV_LEAVE_GROUP,
JOIN_GROUP = UV_JOIN_GROUP
};
class Send final: public Request<Send, uv_udp_send_t> {
using Request::Request;
@ -63,19 +96,11 @@ class Udp final: public Handle<Udp, uv_udp_t> {
}
public:
using Membership = details::UVMembership;
using Bind = details::UVUdpFlags;
using IPv4 = details::IPv4;
using IPv6 = details::IPv6;
enum class Bind: std::underlying_type_t<uv_udp_flags> {
IPV6ONLY = UV_UDP_IPV6ONLY,
REUSEADDR = UV_UDP_REUSEADDR
};
enum class Membership: std::underlying_type_t<uv_membership> {
LEAVE_GROUP = UV_LEAVE_GROUP,
JOIN_GROUP = UV_JOIN_GROUP
};
template<typename... Args>
static std::shared_ptr<Udp> create(Args&&... args) {
return std::shared_ptr<Udp>{new Udp{std::forward<Args>(args)...}};
@ -137,11 +162,11 @@ public:
uv_buf_t bufs[] = { uv_buf_init(data, len) };
auto listener = [ptr = this->shared_from_this()](const auto &event, details::Send &) {
auto listener = [ptr = shared_from_this()](const auto &event, details::Send &) {
ptr->publish(event);
};
auto send = this->loop().resource<details::Send>();
auto send = loop().resource<details::Send>();
send->once<ErrorEvent>(listener);
send->once<SendEvent>(listener);
send->send(get<uv_udp_t>(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));
@ -161,7 +186,7 @@ public:
auto bw = uv_udp_try_send(get<uv_udp_t>(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));
if(bw < 0) {
this->publish(ErrorEvent{bw});
publish(ErrorEvent{bw});
bw = 0;
}

View File

@ -13,6 +13,9 @@
namespace uvw {
struct WorkEvent: Event<WorkEvent> { };
class Work final: public Request<Work, uv_work_t> {
static void workCallback(uv_work_t *req) {
static_cast<Work*>(req->data)->task();