diff --git a/src/uvw.hpp b/src/uvw.hpp index e862dc79..82d68378 100644 --- a/src/uvw.hpp +++ b/src/uvw.hpp @@ -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" diff --git a/src/uvw/async.hpp b/src/uvw/async.hpp index 89ffeae1..b855cf10 100644 --- a/src/uvw/async.hpp +++ b/src/uvw/async.hpp @@ -12,6 +12,9 @@ namespace uvw { +struct AsyncEvent: Event { }; + + class Async final: public Handle { static void sendCallback(uv_async_t *handle) { Async &async = *(static_cast(handle->data)); diff --git a/src/uvw/check.hpp b/src/uvw/check.hpp index 6ec4477f..694a145d 100644 --- a/src/uvw/check.hpp +++ b/src/uvw/check.hpp @@ -12,6 +12,9 @@ namespace uvw { +struct CheckEvent: Event { }; + + class Check final: public Handle { static void startCallback(uv_check_t *handle) { Check &check = *(static_cast(handle->data)); diff --git a/src/uvw/emitter.hpp b/src/uvw/emitter.hpp index 010386c7..bf723584 100644 --- a/src/uvw/emitter.hpp +++ b/src/uvw/emitter.hpp @@ -87,6 +87,9 @@ protected: } public: + template + using Listener = typename Handler::Listener; + template struct Connection: private Handler::Connection { template friend class Emitter; @@ -95,9 +98,6 @@ public: { } }; - template - using Listener = typename Handler::Listener; - virtual ~Emitter() noexcept { static_assert(std::is_base_of, T>::value, "!"); } diff --git a/src/uvw/event.hpp b/src/uvw/event.hpp index df003f2d..9a11b5c1 100644 --- a/src/uvw/event.hpp +++ b/src/uvw/event.hpp @@ -21,6 +21,7 @@ struct BaseEvent { BaseEvent::~BaseEvent() noexcept { } + template struct Event: BaseEvent { static std::size_t type() noexcept { @@ -30,29 +31,6 @@ struct Event: BaseEvent { }; -struct AsyncEvent: Event { }; -struct CheckEvent: Event { }; -struct CloseEvent: Event { }; -struct ConnectEvent: Event { }; - - -struct DataEvent: Event { - explicit DataEvent(std::unique_ptr 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 dt; - const ssize_t len; -}; - - -struct EndEvent: Event { }; - - struct ErrorEvent: Event { explicit ErrorEvent(int code = 0) noexcept: ec(code) { } @@ -64,72 +42,4 @@ private: }; -template -struct FlagsEvent: Event> { - explicit FlagsEvent(Flags f) noexcept: flgs{std::move(f)} { } - - Flags flags() const noexcept { return flgs; } - -private: - Flags flgs; -}; - - -struct FsPollEvent: Event { - 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 { }; -struct ListenEvent: Event { }; -struct PrepareEvent: Event { }; -struct SendEvent: Event { }; -struct ShutdownEvent: Event { }; - - -struct SignalEvent: Event { - explicit SignalEvent(int sig) noexcept: signum(sig) { } - - int signal() const noexcept { return signum; } - -private: - const int signum; -}; - - -struct TimerEvent: Event { }; - - -struct UDPDataEvent: Event { - explicit UDPDataEvent(Addr addr, std::unique_ptr 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 dt; - const ssize_t len; - Addr sndr; - const bool part; -}; - - -struct UninitializedEvent: Event { }; -struct WorkEvent: Event { }; -struct WriteEvent: Event { }; - - } diff --git a/src/uvw/fs.hpp b/src/uvw/fs.hpp index 3ad46d3d..9cc16e53 100644 --- a/src/uvw/fs.hpp +++ b/src/uvw/fs.hpp @@ -53,7 +53,6 @@ class Fs final: public Request { public: using Time = std::chrono::seconds; - using Flags = int; using Mode = int; using Offset = int64_t; diff --git a/src/uvw/fs_event.hpp b/src/uvw/fs_event.hpp new file mode 100644 index 00000000..abd8b3a0 --- /dev/null +++ b/src/uvw/fs_event.hpp @@ -0,0 +1,78 @@ +#pragma once + + +#include +#include +#include +#include +#include "event.hpp" +#include "handle.hpp" +#include "util.hpp" + + +namespace uvw { + + +namespace details { + + +enum class UVFsEventFlags: std::underlying_type_t { + WATCH_ENTRY = UV_FS_EVENT_WATCH_ENTRY, + STAT = UV_FS_EVENT_STAT, + RECURSIVE = UV_FS_EVENT_RECURSIVE +}; + + +enum class UVFsEvent: std::underlying_type_t { + RENAME = UV_RENAME, + CHANGE = UV_CHANGE +}; + + +} + + +struct FsEventEvent: Event { + FsEventEvent(std::string fPath, Flags f) + : flgs{std::move(f)}, relPath{std::move(fPath)} + { } + + const char * filename() const noexcept { return relPath.data(); } + Flags flags() const noexcept { return flgs; } + +private: + Flags flgs; + std::string relPath; +}; + + +class FsEvent final: public Handle { + static void startCallback(uv_fs_event_t *handle, const char *filename, int events, int status) { + FsEvent &fsEvent = *(static_cast(handle->data)); + if(status) { fsEvent.publish(ErrorEvent{status}); } + else { fsEvent.publish(FsEventEvent{filename, static_cast>(events)}); } + } + + using Handle::Handle; + +public: + using Watch = details::UVFsEvent; + using Event = details::UVFsEventFlags; + + template + static std::shared_ptr create(Args&&... args) { + return std::shared_ptr{new FsEvent{std::forward(args)...}}; + } + + bool init() { return initialize(&uv_fs_event_init); } + + void start(std::string path, Flags flags = Flags{}) { + invoke(&uv_fs_event_start, get(), &startCallback, path.data(), flags); + } + + void stop() { invoke(&uv_fs_event_stop, get()); } + std::string path() noexcept { return details::path(&uv_fs_event_getpath, get()); } +}; + + +} diff --git a/src/uvw/fs_poll.hpp b/src/uvw/fs_poll.hpp index c34cad9b..130f12e0 100644 --- a/src/uvw/fs_poll.hpp +++ b/src/uvw/fs_poll.hpp @@ -13,6 +13,20 @@ namespace uvw { +struct FsPollEvent: Event { + 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 { static void startCallback(uv_fs_poll_t *handle, int status, const uv_stat_t *prev, const uv_stat_t *curr) { FsPoll &fsPoll = *(static_cast(handle->data)); diff --git a/src/uvw/handle.hpp b/src/uvw/handle.hpp index 17d563c6..2e54f226 100644 --- a/src/uvw/handle.hpp +++ b/src/uvw/handle.hpp @@ -11,6 +11,9 @@ namespace uvw { +struct CloseEvent: Event { }; + + template class Handle: public BaseHandle, public Resource { diff --git a/src/uvw/idle.hpp b/src/uvw/idle.hpp index 11d60cd8..aab33281 100644 --- a/src/uvw/idle.hpp +++ b/src/uvw/idle.hpp @@ -12,6 +12,9 @@ namespace uvw { +struct IdleEvent: Event { }; + + class Idle final: public Handle { static void startCallback(uv_idle_t *handle) { Idle &idle = *(static_cast(handle->data)); diff --git a/src/uvw/loop.hpp b/src/uvw/loop.hpp index 4af43055..e2f9baf0 100644 --- a/src/uvw/loop.hpp +++ b/src/uvw/loop.hpp @@ -14,6 +14,17 @@ namespace uvw { +namespace details { + + +enum class UVLoopOption: std::underlying_type_t { + BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL +}; + + +} + + class BaseHandle { public: virtual bool active() const noexcept = 0; @@ -37,10 +48,7 @@ class Loop final: public Emitter, public std::enable_shared_from_this { - BLOCK_SIGNAL = UV_LOOP_BLOCK_SIGNAL - }; + using Configure = details::UVLoopOption; static std::shared_ptr create() { auto ptr = std::unique_ptr{new uv_loop_t, [](uv_loop_t *l){ delete l; }}; diff --git a/src/uvw/pipe.hpp b/src/uvw/pipe.hpp index c52f466a..80c5d06b 100644 --- a/src/uvw/pipe.hpp +++ b/src/uvw/pipe.hpp @@ -15,16 +15,25 @@ namespace uvw { +namespace details { + + +enum class UVHandleType: std::underlying_type_t { + UNKNOWN = UV_UNKNOWN_HANDLE, + PIPE = UV_NAMED_PIPE, + TCP = UV_TCP, + UDP = UV_UDP +}; + + +} + + class Pipe final: public Stream { using Stream::Stream; public: - enum class Pending: std::underlying_type_t { - UNKNOWN = UV_UNKNOWN_HANDLE, - PIPE = UV_NAMED_PIPE, - TCP = UV_TCP, - UDP = UV_UDP - }; + using Pending = details::UVHandleType; template static std::shared_ptr 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); }; diff --git a/src/uvw/poll.hpp b/src/uvw/poll.hpp index 4f7a1170..ef93b0e8 100644 --- a/src/uvw/poll.hpp +++ b/src/uvw/poll.hpp @@ -13,21 +13,42 @@ namespace uvw { +namespace details { + + +enum class UVPollEvent: std::underlying_type_t { + READABLE = UV_READABLE, + WRITABLE = UV_WRITABLE, + DISCONNECT = UV_DISCONNECT +}; + + +} + + +struct PollEvent: Event { + explicit PollEvent(Flags f) noexcept + : flgs{std::move(f)} + { } + + Flags flags() const noexcept { return flgs; } + +private: + Flags flgs; +}; + + class Poll final: public Handle { static void startCallback(uv_poll_t *handle, int status, int events) { Poll &poll = *(static_cast(handle->data)); if(status) { poll.publish(ErrorEvent{status}); } - else { poll.publish(FlagsEvent{static_cast>(events)}); } + else { poll.publish(PollEvent{static_cast>(events)}); } } using Handle::Handle; public: - enum class Event: std::underlying_type_t { - READABLE = UV_READABLE, - WRITABLE = UV_WRITABLE, - DISCONNECT = UV_DISCONNECT - }; + using Event = details::UVPollEvent; template static std::shared_ptr create(Args&&... args) { diff --git a/src/uvw/prepare.hpp b/src/uvw/prepare.hpp index 05509bfa..3a50fb8a 100644 --- a/src/uvw/prepare.hpp +++ b/src/uvw/prepare.hpp @@ -12,6 +12,9 @@ namespace uvw { +struct PrepareEvent: Event { }; + + class Prepare final: public Handle { static void startCallback(uv_prepare_t *handle) { Prepare &prepare = *(static_cast(handle->data)); diff --git a/src/uvw/signal.hpp b/src/uvw/signal.hpp index 787c961f..b4f736ee 100644 --- a/src/uvw/signal.hpp +++ b/src/uvw/signal.hpp @@ -12,6 +12,16 @@ namespace uvw { +struct SignalEvent: Event { + explicit SignalEvent(int sig) noexcept: signum(sig) { } + + int signal() const noexcept { return signum; } + +private: + const int signum; +}; + + class Signal final: public Handle { static void startCallback(uv_signal_t *handle, int signum) { Signal &signal = *(static_cast(handle->data)); diff --git a/src/uvw/stream.hpp b/src/uvw/stream.hpp index 149ff743..8522b710 100644 --- a/src/uvw/stream.hpp +++ b/src/uvw/stream.hpp @@ -15,6 +15,27 @@ namespace uvw { +struct ConnectEvent: Event { }; +struct EndEvent: Event { }; +struct ListenEvent: Event { }; +struct ShutdownEvent: Event { }; +struct WriteEvent: Event { }; + + +struct DataEvent: Event { + explicit DataEvent(std::unique_ptr 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 dt; + const ssize_t len; +}; + + namespace details { diff --git a/src/uvw/tcp.hpp b/src/uvw/tcp.hpp index ced72481..e26a2c98 100644 --- a/src/uvw/tcp.hpp +++ b/src/uvw/tcp.hpp @@ -16,19 +16,26 @@ namespace uvw { +namespace details { + + +enum class UVTcpFlags: std::underlying_type_t { + IPV6ONLY = UV_TCP_IPV6ONLY +}; + + +} + + class Tcp final: public Stream { 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 { - IPV6ONLY = UV_TCP_IPV6ONLY - }; - template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new Tcp{std::forward(args)...}}; @@ -84,7 +91,7 @@ public: typename details::IpTraits::Type addr; details::IpTraits::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); }; diff --git a/src/uvw/timer.hpp b/src/uvw/timer.hpp index ecb8ddd5..21b72074 100644 --- a/src/uvw/timer.hpp +++ b/src/uvw/timer.hpp @@ -13,6 +13,9 @@ namespace uvw { +struct TimerEvent: Event { }; + + class Timer final: public Handle { static void startCallback(uv_timer_t *handle) { Timer &timer = *(static_cast(handle->data)); diff --git a/src/uvw/tty.hpp b/src/uvw/tty.hpp index 01ba39a9..c1e2102a 100644 --- a/src/uvw/tty.hpp +++ b/src/uvw/tty.hpp @@ -13,6 +13,19 @@ namespace uvw { +namespace details { + + +enum class UVTTYModeT: std::underlying_type_t { + NORMAL = UV_TTY_MODE_NORMAL, + RAW = UV_TTY_MODE_RAW, + IO = UV_TTY_MODE_IO +}; + + +} + + class TTY final: public Stream { explicit TTY(std::shared_ptr ref, FileHandle desc, @@ -23,11 +36,7 @@ class TTY final: public Stream { { } public: - enum class Mode: std::underlying_type_t { - NORMAL = UV_TTY_MODE_NORMAL, - RAW = UV_TTY_MODE_RAW, - IO = UV_TTY_MODE_IO - }; + using Mode = details::UVTTYModeT; template static std::shared_ptr create(Args&&... args) { diff --git a/src/uvw/udp.hpp b/src/uvw/udp.hpp index fd626234..1a61e163 100644 --- a/src/uvw/udp.hpp +++ b/src/uvw/udp.hpp @@ -15,9 +15,42 @@ namespace uvw { +struct SendEvent: Event { }; + + +struct UDPDataEvent: Event { + explicit UDPDataEvent(Addr addr, std::unique_ptr 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 dt; + const ssize_t len; + Addr sndr; + const bool part; +}; + + namespace details { +enum class UVUdpFlags: std::underlying_type_t { + IPV6ONLY = UV_UDP_IPV6ONLY, + REUSEADDR = UV_UDP_REUSEADDR +}; + + +enum class UVMembership: std::underlying_type_t { + LEAVE_GROUP = UV_LEAVE_GROUP, + JOIN_GROUP = UV_JOIN_GROUP +}; + + class Send final: public Request { using Request::Request; @@ -63,19 +96,11 @@ class Udp final: public Handle { } public: + using Membership = details::UVMembership; + using Bind = details::UVUdpFlags; using IPv4 = details::IPv4; using IPv6 = details::IPv6; - enum class Bind: std::underlying_type_t { - IPV6ONLY = UV_UDP_IPV6ONLY, - REUSEADDR = UV_UDP_REUSEADDR - }; - - enum class Membership: std::underlying_type_t { - LEAVE_GROUP = UV_LEAVE_GROUP, - JOIN_GROUP = UV_JOIN_GROUP - }; - template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new Udp{std::forward(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(); + auto send = loop().resource(); send->once(listener); send->once(listener); send->send(get(), bufs, 1, reinterpret_cast(&addr)); @@ -161,7 +186,7 @@ public: auto bw = uv_udp_try_send(get(), bufs, 1, reinterpret_cast(&addr)); if(bw < 0) { - this->publish(ErrorEvent{bw}); + publish(ErrorEvent{bw}); bw = 0; } diff --git a/src/uvw/work.hpp b/src/uvw/work.hpp index 372377c9..93324682 100644 --- a/src/uvw/work.hpp +++ b/src/uvw/work.hpp @@ -13,6 +13,9 @@ namespace uvw { +struct WorkEvent: Event { }; + + class Work final: public Request { static void workCallback(uv_work_t *req) { static_cast(req->data)->task();