From 184dc33aa5cdca7a6d9852e906b849c52b45a0d8 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Thu, 28 Jul 2016 15:50:29 +0200 Subject: [PATCH 1/6] noexcept specifiers on destructors --- src/uvw/emitter.hpp | 2 +- src/uvw/fs.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uvw/emitter.hpp b/src/uvw/emitter.hpp index bf723584..38dfc05a 100644 --- a/src/uvw/emitter.hpp +++ b/src/uvw/emitter.hpp @@ -18,7 +18,7 @@ namespace uvw { template class Emitter { struct BaseHandler { - virtual ~BaseHandler() = default; + virtual ~BaseHandler() noexcept = default; virtual bool empty() const noexcept = 0; }; diff --git a/src/uvw/fs.hpp b/src/uvw/fs.hpp index a4c18d76..aadf88f1 100644 --- a/src/uvw/fs.hpp +++ b/src/uvw/fs.hpp @@ -307,7 +307,7 @@ public: return std::shared_ptr{new FsReq{std::forward(args)...}}; } - ~FsReq() { + ~FsReq() noexcept { uv_fs_req_cleanup(get()); } From b466f00c464534dd55f03e7cc8704b2d91cab5cc Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Thu, 28 Jul 2016 15:50:49 +0200 Subject: [PATCH 2/6] TTY review --- src/uvw/tty.hpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/uvw/tty.hpp b/src/uvw/tty.hpp index fd9e4e92..9750a093 100644 --- a/src/uvw/tty.hpp +++ b/src/uvw/tty.hpp @@ -16,6 +16,13 @@ namespace uvw { namespace details { +struct ResetModeMemo { + ~ResetModeMemo() { + uv_tty_reset_mode(); + } +}; + + enum class UVTTYModeT: std::underlying_type_t { NORMAL = UV_TTY_MODE_NORMAL, RAW = UV_TTY_MODE_RAW, @@ -29,8 +36,12 @@ enum class UVTTYModeT: std::underlying_type_t { class TTYHandle final: public StreamHandle { explicit TTYHandle(std::shared_ptr ref, FileHandle desc, - bool readable) - : StreamHandle{std::move(ref)}, fd{desc}, rw{readable} + bool readable, + std::shared_ptr rmm) + : StreamHandle{std::move(ref)}, + memo{std::move(rmm)}, + fd{desc}, + rw{readable} { } public: @@ -38,7 +49,10 @@ public: template static std::shared_ptr create(Args&&... args) { - return std::shared_ptr{new TTYHandle{std::forward(args)...}}; + static std::weak_ptr rmm; + auto ptr = rmm.lock(); + if(!ptr) { rmm = ptr = std::make_shared(); } + return std::shared_ptr{new TTYHandle{std::forward(args)..., ptr}}; } bool init() { return initialize(&uv_tty_init, fd, rw); } @@ -50,7 +64,7 @@ public: }, get(), static_cast>(m)); } - void reset() { invoke(&uv_tty_reset_mode); } + void reset() noexcept { invoke(&uv_tty_reset_mode); } WinSize getWinSize() { std::pair size{0, 0}; @@ -70,6 +84,7 @@ public: } private: + std::shared_ptr memo; FileHandle::Type fd; int rw; }; From 8973f55bea39d82645ce5a8e1c2327ad650a189b Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Thu, 28 Jul 2016 16:04:20 +0200 Subject: [PATCH 3/6] formatting --- src/uvw/async.hpp | 8 ++++++-- src/uvw/check.hpp | 13 ++++++++++--- src/uvw/fs_event.hpp | 13 ++++++++++--- src/uvw/fs_poll.hpp | 13 ++++++++++--- src/uvw/idle.hpp | 13 ++++++++++--- src/uvw/pipe.hpp | 22 +++++++++++++++++----- src/uvw/poll.hpp | 18 ++++++++++++++---- src/uvw/prepare.hpp | 13 ++++++++++--- src/uvw/resource.hpp | 12 +++++++++--- src/uvw/self.hpp | 14 +++++++++++--- src/uvw/signal.hpp | 17 +++++++++++++---- src/uvw/tcp.hpp | 8 ++++++-- src/uvw/timer.hpp | 27 +++++++++++++++++++++------ src/uvw/tty.hpp | 8 ++++++-- src/uvw/udp.hpp | 17 +++++++++++++---- 15 files changed, 166 insertions(+), 50 deletions(-) diff --git a/src/uvw/async.hpp b/src/uvw/async.hpp index 2079d20c..6e6baa03 100644 --- a/src/uvw/async.hpp +++ b/src/uvw/async.hpp @@ -29,9 +29,13 @@ public: return std::shared_ptr{new AsyncHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_async_init, &sendCallback); } + bool init() { + return initialize(&uv_async_init, &sendCallback); + } - void send() { invoke(&uv_async_send, get()); } + void send() { + invoke(&uv_async_send, get()); + } }; diff --git a/src/uvw/check.hpp b/src/uvw/check.hpp index 86c538fa..379bf17f 100644 --- a/src/uvw/check.hpp +++ b/src/uvw/check.hpp @@ -29,10 +29,17 @@ public: return std::shared_ptr{new CheckHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_check_init); } + bool init() { + return initialize(&uv_check_init); + } - void start() { invoke(&uv_check_start, get(), &startCallback); } - void stop() { invoke(&uv_check_stop, get()); } + void start() { + invoke(&uv_check_start, get(), &startCallback); + } + + void stop() { + invoke(&uv_check_stop, get()); + } }; diff --git a/src/uvw/fs_event.hpp b/src/uvw/fs_event.hpp index 6451b3c1..3c908cdf 100644 --- a/src/uvw/fs_event.hpp +++ b/src/uvw/fs_event.hpp @@ -64,14 +64,21 @@ public: return std::shared_ptr{new FsEventHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_fs_event_init); } + 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()); } + 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 41c24f18..514d29df 100644 --- a/src/uvw/fs_poll.hpp +++ b/src/uvw/fs_poll.hpp @@ -42,14 +42,21 @@ public: return std::shared_ptr{new FsPollHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_fs_poll_init); } + bool init() { + return initialize(&uv_fs_poll_init); + } void start(std::string file, unsigned int interval) { invoke(&uv_fs_poll_start, get(), &startCallback, file.data(), interval); } - void stop() { invoke(&uv_fs_poll_stop, get()); } - std::string path() noexcept { return details::path(&uv_fs_poll_getpath, get()); } + void stop() { + invoke(&uv_fs_poll_stop, get()); + } + + std::string path() noexcept { + return details::path(&uv_fs_poll_getpath, get()); + } }; diff --git a/src/uvw/idle.hpp b/src/uvw/idle.hpp index 513206da..6de40b0b 100644 --- a/src/uvw/idle.hpp +++ b/src/uvw/idle.hpp @@ -29,10 +29,17 @@ public: return std::shared_ptr{new IdleHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_idle_init); } + bool init() { + return initialize(&uv_idle_init); + } - void start() { invoke(&uv_idle_start, get(), &startCallback); } - void stop() { invoke(&uv_idle_stop, get()); } + void start() { + invoke(&uv_idle_start, get(), &startCallback); + } + + void stop() { + invoke(&uv_idle_stop, get()); + } }; diff --git a/src/uvw/pipe.hpp b/src/uvw/pipe.hpp index e549ab9c..7fe49314 100644 --- a/src/uvw/pipe.hpp +++ b/src/uvw/pipe.hpp @@ -40,7 +40,9 @@ public: return std::shared_ptr{new PipeHandle{std::forward(args)...}}; } - bool init(bool ipc = false) { return initialize(&uv_pipe_init, ipc); } + bool init(bool ipc = false) { + return initialize(&uv_pipe_init, ipc); + } void open(FileHandle file) { invoke(&uv_pipe_open, get(), file); @@ -61,11 +63,21 @@ public: connect->connect(&uv_pipe_connect, get(), name.data()); } - std::string sock() const noexcept { return details::path(&uv_pipe_getsockname, get()); } - std::string peer() const noexcept { return details::path(&uv_pipe_getpeername, get()); } + std::string sock() const noexcept { + return details::path(&uv_pipe_getsockname, get()); + } - void pending(int count) noexcept { uv_pipe_pending_instances(get(), count); } - int pending() noexcept { return uv_pipe_pending_count(get()); } + std::string peer() const noexcept { + return details::path(&uv_pipe_getpeername, get()); + } + + void pending(int count) noexcept { + uv_pipe_pending_instances(get(), count); + } + + int pending() noexcept { + return uv_pipe_pending_count(get()); + } Pending receive() noexcept { auto type = uv_pipe_pending_type(get()); diff --git a/src/uvw/poll.hpp b/src/uvw/poll.hpp index d0765a46..1809a1ac 100644 --- a/src/uvw/poll.hpp +++ b/src/uvw/poll.hpp @@ -55,11 +55,21 @@ public: return std::shared_ptr{new PollHandle{std::forward(args)...}}; } - bool init(int fd) { return initialize(&uv_poll_init, fd); } + bool init(int fd) { + return initialize(&uv_poll_init, fd); + } - void start(Flags flags) { invoke(&uv_poll_start, get(), flags, &startCallback); } - void start(Event event) { start(Flags{event}); } - void stop() { invoke(&uv_poll_stop, get()); } + void start(Flags flags) { + invoke(&uv_poll_start, get(), flags, &startCallback); + } + + void start(Event event) { + start(Flags{event}); + } + + void stop() { + invoke(&uv_poll_stop, get()); + } }; diff --git a/src/uvw/prepare.hpp b/src/uvw/prepare.hpp index 06807ad7..63efea0a 100644 --- a/src/uvw/prepare.hpp +++ b/src/uvw/prepare.hpp @@ -29,10 +29,17 @@ public: return std::shared_ptr{new PrepareHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_prepare_init); } + bool init() { + return initialize(&uv_prepare_init); + } - void start() { invoke(&uv_prepare_start, get(), &startCallback); } - void stop() { invoke(&uv_prepare_stop, get()); } + void start() { + invoke(&uv_prepare_start, get(), &startCallback); + } + + void stop() { + invoke(&uv_prepare_stop, get()); + } }; diff --git a/src/uvw/resource.hpp b/src/uvw/resource.hpp index c614cb4e..d6b7d786 100644 --- a/src/uvw/resource.hpp +++ b/src/uvw/resource.hpp @@ -27,13 +27,19 @@ protected: this->template get()->data = static_cast(this); } - auto parent() const noexcept { return pLoop->loop.get(); } + auto parent() const noexcept { + return pLoop->loop.get(); + } template - auto get() noexcept { return reinterpret_cast(&resource); } + auto get() noexcept { + return reinterpret_cast(&resource); + } template - auto get() const noexcept { return reinterpret_cast(&resource); } + auto get() const noexcept { + return reinterpret_cast(&resource); + } public: Resource(const Resource &) = delete; diff --git a/src/uvw/self.hpp b/src/uvw/self.hpp index aff2e3d1..c924a79f 100644 --- a/src/uvw/self.hpp +++ b/src/uvw/self.hpp @@ -9,9 +9,17 @@ namespace uvw { template struct Self: std::enable_shared_from_this { - void leak() noexcept { ptr = this->shared_from_this(); } - void reset() noexcept { ptr.reset(); } - bool self() const noexcept { return static_cast(ptr); } + void leak() noexcept { + ptr = this->shared_from_this(); + } + + void reset() noexcept { + ptr.reset(); + } + + bool self() const noexcept { + return static_cast(ptr); + } private: std::shared_ptr ptr{nullptr}; diff --git a/src/uvw/signal.hpp b/src/uvw/signal.hpp index 5906d162..d6b2fcf3 100644 --- a/src/uvw/signal.hpp +++ b/src/uvw/signal.hpp @@ -36,12 +36,21 @@ public: return std::shared_ptr{new SignalHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_signal_init); } + bool init() { + return initialize(&uv_signal_init); + } - void start(int signum) { invoke(&uv_signal_start, get(), &startCallback, signum); } - void stop() { invoke(&uv_signal_stop, get()); } + void start(int signum) { + invoke(&uv_signal_start, get(), &startCallback, signum); + } - int signal() const noexcept { return get()->signum; } + void stop() { + invoke(&uv_signal_stop, get()); + } + + int signal() const noexcept { + return get()->signum; + } }; diff --git a/src/uvw/tcp.hpp b/src/uvw/tcp.hpp index 4e4a800b..f572dc0f 100644 --- a/src/uvw/tcp.hpp +++ b/src/uvw/tcp.hpp @@ -41,7 +41,9 @@ public: return std::shared_ptr{new TcpHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_tcp_init); } + bool init() { + return initialize(&uv_tcp_init); + } template bool init(T&& t, Args&&... args) { @@ -102,7 +104,9 @@ public: } template - void connect(Addr addr) { connect(addr.ip, addr.port); } + void connect(Addr addr) { + connect(addr.ip, addr.port); + } }; diff --git a/src/uvw/timer.hpp b/src/uvw/timer.hpp index c76cf7af..0c22260b 100644 --- a/src/uvw/timer.hpp +++ b/src/uvw/timer.hpp @@ -32,14 +32,29 @@ public: return std::shared_ptr{new TimerHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_timer_init); } + bool init() { + return initialize(&uv_timer_init); + } - void start(Time timeout, Time repeat) { invoke(&uv_timer_start, get(), &startCallback, timeout.count(), repeat.count()); } - void stop() { invoke(&uv_timer_stop, get()); } - void again() { invoke(&uv_timer_again, get()); } + void start(Time timeout, Time repeat) { + invoke(&uv_timer_start, get(), &startCallback, timeout.count(), repeat.count()); + } - void repeat(Time repeat) { uv_timer_set_repeat(get(), repeat.count()); } - Time repeat() { return Time{uv_timer_get_repeat(get())}; } + void stop() { + invoke(&uv_timer_stop, get()); + } + + void again() { + invoke(&uv_timer_again, get()); + } + + void repeat(Time repeat) { + uv_timer_set_repeat(get(), repeat.count()); + } + + Time repeat() { + return Time{uv_timer_get_repeat(get())}; + } }; diff --git a/src/uvw/tty.hpp b/src/uvw/tty.hpp index 9750a093..e10045cd 100644 --- a/src/uvw/tty.hpp +++ b/src/uvw/tty.hpp @@ -55,7 +55,9 @@ public: return std::shared_ptr{new TTYHandle{std::forward(args)..., ptr}}; } - bool init() { return initialize(&uv_tty_init, fd, rw); } + bool init() { + return initialize(&uv_tty_init, fd, rw); + } void mode(Mode m) { // uv_tty_set_mode is inline, it cannot be used with invoke directly @@ -64,7 +66,9 @@ public: }, get(), static_cast>(m)); } - void reset() noexcept { invoke(&uv_tty_reset_mode); } + void reset() noexcept { + invoke(&uv_tty_reset_mode); + } WinSize getWinSize() { std::pair size{0, 0}; diff --git a/src/uvw/udp.hpp b/src/uvw/udp.hpp index 0eff5b95..eb3e157e 100644 --- a/src/uvw/udp.hpp +++ b/src/uvw/udp.hpp @@ -106,7 +106,9 @@ public: return std::shared_ptr{new UdpHandle{std::forward(args)...}}; } - bool init() { return initialize(&uv_udp_init); } + bool init() { + return initialize(&uv_udp_init); + } template bool init(T&& t, Args&&... args) { @@ -152,8 +154,13 @@ public: invoke(&uv_udp_set_multicast_interface, get(), interface.data()); } - void broadcast(bool enable = false) { invoke(&uv_udp_set_broadcast, get(), enable); } - void ttl(int val) { invoke(&uv_udp_set_ttl, get(), val > 255 ? 255 : val); } + void broadcast(bool enable = false) { + invoke(&uv_udp_set_broadcast, get(), enable); + } + + void ttl(int val) { + invoke(&uv_udp_set_ttl, get(), val > 255 ? 255 : val); + } template void send(std::string ip, unsigned int port, std::unique_ptr data, ssize_t len) { @@ -193,7 +200,9 @@ public: invoke(&uv_udp_recv_start, get(), &allocCallback, &recvCallback); } - void stop() { invoke(&uv_udp_recv_stop, get()); } + void stop() { + invoke(&uv_udp_recv_stop, get()); + } }; From a6e67f061dedbede62994cdbdd555c3ea421510e Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Thu, 28 Jul 2016 18:12:35 +0200 Subject: [PATCH 4/6] WorkReq review --- src/uvw/work.hpp | 14 ++++++++------ test/uvw/loop.cpp | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/uvw/work.hpp b/src/uvw/work.hpp index 0b011f88..f1c5b242 100644 --- a/src/uvw/work.hpp +++ b/src/uvw/work.hpp @@ -17,24 +17,26 @@ struct WorkEvent: Event { }; class WorkReq final: public Request { + using InternalTask = std::function; + static void workCallback(uv_work_t *req) { static_cast(req->data)->task(); } - using Request::Request; + explicit WorkReq(std::shared_ptr ref, InternalTask t) + : Request{std::move(ref)}, task{t} + { } public: - using Task = std::function; + using Task = InternalTask; template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new WorkReq{std::forward(args)...}}; } - void queue(Task t) { - if(0 == invoke(&uv_queue_work, parent(), get(), &workCallback, &defaultCallback)) { - task = std::move(t); - } + void queue() { + invoke(&uv_queue_work, parent(), get(), &workCallback, &defaultCallback); } private: diff --git a/test/uvw/loop.cpp b/test/uvw/loop.cpp index f33462e6..1a6f3812 100644 --- a/test/uvw/loop.cpp +++ b/test/uvw/loop.cpp @@ -15,7 +15,7 @@ TEST(Loop, Basics) { auto loop = uvw::Loop::create(); auto handle = loop->resource(); - auto req = loop->resource(); + auto req = loop->resource([](){}); auto err = [](uvw::ErrorEvent, auto &) { ASSERT_TRUE(false); }; From 06111761bb08b3f7074a26ef811a423e546f62c9 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Thu, 28 Jul 2016 18:13:03 +0200 Subject: [PATCH 5/6] Fs review --- src/uvw/fs.hpp | 327 +++++++++++++++++++++++++++---------------------- 1 file changed, 178 insertions(+), 149 deletions(-) diff --git a/src/uvw/fs.hpp b/src/uvw/fs.hpp index aadf88f1..69deffdd 100644 --- a/src/uvw/fs.hpp +++ b/src/uvw/fs.hpp @@ -81,23 +81,6 @@ private: }; -template<> -struct TypedEvent - : Event> -{ - TypedEvent(const char *p, uv_file desc) noexcept - : rPath{p}, fd{desc} - { } - - const char * path() const noexcept { return rPath; } - FileHandle descriptor() const noexcept { return fd; } - -private: - const char *rPath; - uv_file fd; -}; - - template<> struct TypedEvent : Event> @@ -242,57 +225,41 @@ template using FsEvent = TypedEvent; -class FsReq final: public Request { - static void fsOpenCallback(uv_fs_t *req) { - auto ptr = reserve(reinterpret_cast(req)); - if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); } - else { ptr->publish(FsEvent{req->path, static_cast(req->result)}); } - } - - static void fsReadCallback(uv_fs_t *req) { - auto ptr = reserve(reinterpret_cast(req)); - if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); } - else { ptr->publish(FsEvent{req->path, std::move(ptr->data), req->result}); } - } - +template +class FsRequest: public Request { +protected: template static void fsGenericCallback(uv_fs_t *req) { - auto ptr = reserve(reinterpret_cast(req)); + auto ptr = Request::reserve(reinterpret_cast(req)); if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); } else { ptr->publish(FsEvent{req->path}); } } template static void fsResultCallback(uv_fs_t *req) { - auto ptr = reserve(reinterpret_cast(req)); + auto ptr = Request::reserve(reinterpret_cast(req)); if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); } else { ptr->publish(FsEvent{req->path, req->result}); } } template static void fsStatCallback(uv_fs_t *req) { - auto ptr = reserve(reinterpret_cast(req)); + auto ptr = Request::reserve(reinterpret_cast(req)); if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); } else { ptr->publish(FsEvent{req->path, req->statbuf}); } } - static void fsReadlinkCallback(uv_fs_t *req) { - auto ptr = reserve(reinterpret_cast(req)); - if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); } - else { ptr->publish(FsEvent{req->path, static_cast(req->ptr), req->result}); } - } - - using Request::Request; + using Request::Request; template void cleanupAndInvoke(Args&&... args) { - uv_fs_req_cleanup(get()); - invoke(std::forward(args)...); + uv_fs_req_cleanup(this->template get()); + this->invoke(std::forward(args)...); } template void cleanupAndInvokeSync(F &&f, Args&&... args) { - uv_fs_req_cleanup(get()); + uv_fs_req_cleanup(this->template get()); std::forward(f)(std::forward(args)..., nullptr); } @@ -301,23 +268,60 @@ public: using Type = details::UVFsType; using EntryType = details::UVDirentTypeT; using Entry = std::pair; +}; - template - static std::shared_ptr create(Args&&... args) { - return std::shared_ptr{new FsReq{std::forward(args)...}}; + +class FileReq final: public FsRequest { + static constexpr uv_file BAD_FD = -1; + + static void fsOpenCallback(uv_fs_t *req) { + auto ptr = reserve(reinterpret_cast(req)); + + if(req->result < 0) { + ptr->publish(ErrorEvent{req->result}); + } else { + ptr->file = static_cast(req->result); + ptr->publish(FsEvent{req->path}); + } } - ~FsReq() noexcept { + static void fsCloseCallback(uv_fs_t *req) { + auto ptr = reserve(reinterpret_cast(req)); + + if(req->result < 0) { + ptr->publish(ErrorEvent{req->result}); + } else { + ptr->file = BAD_FD; + ptr->publish(FsEvent{req->path}); + } + } + + static void fsReadCallback(uv_fs_t *req) { + auto ptr = reserve(reinterpret_cast(req)); + if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); } + else { ptr->publish(FsEvent{req->path, std::move(ptr->data), req->result}); } + } + + using FsRequest::FsRequest; + +public: + template + static std::shared_ptr create(Args&&... args) { + return std::shared_ptr{new FileReq{std::forward(args)...}}; + } + + ~FileReq() noexcept { uv_fs_req_cleanup(get()); } - void close(FileHandle file) { - cleanupAndInvoke(&uv_fs_close, parent(), get(), file, &fsGenericCallback); + void close() { + cleanupAndInvoke(&uv_fs_close, parent(), get(), file, &fsCloseCallback); } - auto closeSync(FileHandle file) { + auto closeSync() { auto req = get(); cleanupAndInvokeSync(&uv_fs_close, parent(), req, file); + if(req->result >= 0) { file = BAD_FD; } return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } @@ -328,17 +332,18 @@ public: auto openSync(std::string path, int flags, int mode) { auto req = get(); cleanupAndInvokeSync(&uv_fs_open, parent(), req, path.data(), flags, mode); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, static_cast(req->result)}); + if(req->result >= 0) { file = static_cast(req->result); } + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void read(FileHandle file, int64_t offset, unsigned int len) { + void read(int64_t offset, unsigned int len) { data = std::unique_ptr{new char[len]}; buffer = uv_buf_init(data.get(), len); uv_buf_t bufs[] = { buffer }; cleanupAndInvoke(&uv_fs_read, parent(), get(), file, bufs, 1, offset, &fsReadCallback); } - auto readSync(FileHandle file, int64_t offset, unsigned int len) { + auto readSync(int64_t offset, unsigned int len) { data = std::unique_ptr{new char[len]}; buffer = uv_buf_init(data.get(), len); uv_buf_t bufs[] = { buffer }; @@ -347,6 +352,126 @@ public: return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, std::move(data), req->result}); } + void write(std::unique_ptr data, ssize_t len, int64_t offset) { + uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; + cleanupAndInvoke(&uv_fs_write, parent(), get(), file, bufs, 1, offset, &fsResultCallback); + } + + auto writeSync(std::unique_ptr data, ssize_t len, int64_t offset) { + uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; + auto req = get(); + cleanupAndInvokeSync(&uv_fs_write, parent(), get(), file, bufs, 1, offset); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->result}); + } + + void fstat() { + cleanupAndInvoke(&uv_fs_fstat, parent(), get(), file, &fsStatCallback); + } + + auto fstatSync() { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fstat, parent(), req, file); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->statbuf}); + } + + void fsync() { + cleanupAndInvoke(&uv_fs_fsync, parent(), get(), file, &fsGenericCallback); + } + + auto fsyncSync() { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fsync, parent(), req, file); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); + } + + void fdatasync() { + cleanupAndInvoke(&uv_fs_fdatasync, parent(), get(), file, &fsGenericCallback); + } + + auto fdatasyncSync() { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fdatasync, parent(), req, file); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); + } + + void ftruncate(int64_t offset) { + cleanupAndInvoke(&uv_fs_ftruncate, parent(), get(), file, offset, &fsGenericCallback); + } + + auto ftruncateSync(int64_t offset) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_ftruncate, parent(), req, file, offset); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); + } + + void sendfile(FileHandle out, int64_t offset, size_t length) { + cleanupAndInvoke(&uv_fs_sendfile, parent(), get(), out, file, offset, length, &fsResultCallback); + } + + auto sendfileSync(FileHandle out, int64_t offset, size_t length) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_sendfile, parent(), req, out, file, offset, length); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->result}); + } + + void fchmod(int mode) { + cleanupAndInvoke(&uv_fs_fchmod, parent(), get(), file, mode, &fsGenericCallback); + } + + auto fchmodSync(int mode) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fchmod, parent(), req, file, mode); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); + } + + void futime(Time atime, Time mtime) { + cleanupAndInvoke(&uv_fs_futime, parent(), get(), file, atime.count(), mtime.count(), &fsGenericCallback); + } + + auto futimeSync(Time atime, Time mtime) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_futime, parent(), req, file, atime.count(), mtime.count()); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); + } + + void fchown(Uid uid, Gid gid) { + cleanupAndInvoke(&uv_fs_fchown, parent(), get(), file, uid, gid, &fsGenericCallback); + } + + auto fchownSync(Uid uid, Gid gid) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fchown, parent(), req, file, uid, gid); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); + } + + operator FileHandle() const noexcept { return file; } + +private: + std::unique_ptr data{nullptr}; + uv_buf_t buffer{}; + uv_file file{BAD_FD}; +}; + + +class FsReq final: public FsRequest { + using FsRequest::FsRequest; + + static void fsReadlinkCallback(uv_fs_t *req) { + auto ptr = reserve(reinterpret_cast(req)); + if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); } + else { ptr->publish(FsEvent{req->path, static_cast(req->ptr), req->result}); } + } + +public: + template + static std::shared_ptr create(Args&&... args) { + return std::shared_ptr{new FsReq{std::forward(args)...}}; + } + + ~FsReq() noexcept { + uv_fs_req_cleanup(get()); + } + void unlink(std::string path) { cleanupAndInvoke(&uv_fs_unlink, parent(), get(), path.data(), &fsGenericCallback); } @@ -357,18 +482,6 @@ public: return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void write(FileHandle file, std::unique_ptr data, ssize_t len, int64_t offset) { - uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; - cleanupAndInvoke(&uv_fs_write, parent(), get(), file, bufs, 1, offset, &fsResultCallback); - } - - auto writeSync(FileHandle file, std::unique_ptr data, ssize_t len, int64_t offset) { - uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; - auto req = get(); - cleanupAndInvokeSync(&uv_fs_write, parent(), get(), file, bufs, 1, offset); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->result}); - } - void mkdir(std::string path, int mode) { cleanupAndInvoke(&uv_fs_mkdir, parent(), get(), path.data(), mode, &fsGenericCallback); } @@ -433,16 +546,6 @@ public: return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->statbuf}); } - void fstat(FileHandle file) { - cleanupAndInvoke(&uv_fs_fstat, parent(), get(), file, &fsStatCallback); - } - - auto fstatSync(FileHandle file) { - auto req = get(); - cleanupAndInvokeSync(&uv_fs_fstat, parent(), req, file); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->statbuf}); - } - void lstat(std::string path) { cleanupAndInvoke(&uv_fs_lstat, parent(), get(), path.data(), &fsStatCallback); } @@ -463,46 +566,6 @@ public: return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void fsync(FileHandle file) { - cleanupAndInvoke(&uv_fs_fsync, parent(), get(), file, &fsGenericCallback); - } - - auto fsyncSync(FileHandle file) { - auto req = get(); - cleanupAndInvokeSync(&uv_fs_fsync, parent(), req, file); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); - } - - void fdatasync(FileHandle file) { - cleanupAndInvoke(&uv_fs_fdatasync, parent(), get(), file, &fsGenericCallback); - } - - auto fdatasyncSync(FileHandle file) { - auto req = get(); - cleanupAndInvokeSync(&uv_fs_fdatasync, parent(), req, file); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); - } - - void ftruncate(FileHandle file, int64_t offset) { - cleanupAndInvoke(&uv_fs_ftruncate, parent(), get(), file, offset, &fsGenericCallback); - } - - auto ftruncateSync(FileHandle file, int64_t offset) { - auto req = get(); - cleanupAndInvokeSync(&uv_fs_ftruncate, parent(), req, file, offset); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); - } - - void sendfile(FileHandle out, FileHandle in, int64_t offset, size_t length) { - cleanupAndInvoke(&uv_fs_sendfile, parent(), get(), out, in, offset, length, &fsResultCallback); - } - - auto sendfileSync(FileHandle out, FileHandle in, int64_t offset, size_t length) { - auto req = get(); - cleanupAndInvokeSync(&uv_fs_sendfile, parent(), req, out, in, offset, length); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->result}); - } - void access(std::string path, int mode) { cleanupAndInvoke(&uv_fs_access, parent(), get(), path.data(), mode, &fsGenericCallback); } @@ -523,16 +586,6 @@ public: return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void fchmod(FileHandle file, int mode) { - cleanupAndInvoke(&uv_fs_fchmod, parent(), get(), file, mode, &fsGenericCallback); - } - - auto fchmodSync(FileHandle file, int mode) { - auto req = get(); - cleanupAndInvokeSync(&uv_fs_fchmod, parent(), req, file, mode); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); - } - void utime(std::string path, Time atime, Time mtime) { cleanupAndInvoke(&uv_fs_utime, parent(), get(), path.data(), atime.count(), mtime.count(), &fsGenericCallback); } @@ -543,16 +596,6 @@ public: return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void futime(FileHandle file, Time atime, Time mtime) { - cleanupAndInvoke(&uv_fs_futime, parent(), get(), file, atime.count(), mtime.count(), &fsGenericCallback); - } - - auto futimeSync(FileHandle file, Time atime, Time mtime) { - auto req = get(); - cleanupAndInvokeSync(&uv_fs_futime, parent(), req, file, atime.count(), mtime.count()); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); - } - void link(std::string old, std::string path) { cleanupAndInvoke(&uv_fs_link, parent(), get(), old.data(), path.data(), &fsGenericCallback); } @@ -602,20 +645,6 @@ public: cleanupAndInvokeSync(&uv_fs_chown, parent(), req, path.data(), uid, gid); return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - - void fchown(FileHandle file, Uid uid, Gid gid) { - cleanupAndInvoke(&uv_fs_fchown, parent(), get(), file, uid, gid, &fsGenericCallback); - } - - auto fchownSync(FileHandle file, Uid uid, Gid gid) { - auto req = get(); - cleanupAndInvokeSync(&uv_fs_fchown, parent(), req, file, uid, gid); - return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); - } - -private: - std::unique_ptr data; - uv_buf_t buffer; }; From 7e1acb91418e62222e195bae20e3c46544b6e607 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Fri, 29 Jul 2016 11:36:12 +0200 Subject: [PATCH 6/6] added ProcessHandle --- src/uvw.hpp | 1 + src/uvw/process.hpp | 145 ++++++++++++++++++++++++++++++++++++++++++++ src/uvw/util.hpp | 14 ++++- 3 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 src/uvw/process.hpp diff --git a/src/uvw.hpp b/src/uvw.hpp index 82d68378..15994e58 100644 --- a/src/uvw.hpp +++ b/src/uvw.hpp @@ -10,6 +10,7 @@ #include "uvw/pipe.hpp" #include "uvw/poll.hpp" #include "uvw/prepare.hpp" +#include "uvw/process.hpp" #include "uvw/signal.hpp" #include "uvw/tcp.hpp" #include "uvw/timer.hpp" diff --git a/src/uvw/process.hpp b/src/uvw/process.hpp new file mode 100644 index 00000000..e04c557a --- /dev/null +++ b/src/uvw/process.hpp @@ -0,0 +1,145 @@ +#pragma once + + +#include +#include +#include +#include "event.hpp" +#include "handle.hpp" +#include "stream.hpp" +#include "util.hpp" + + +namespace uvw { + + +namespace details { + + +enum class UVProcessFlags: std::underlying_type_t { + PROCESS_SETUID = UV_PROCESS_SETUID, + PROCESS_SETGID = UV_PROCESS_SETGID, + PROCESS_WINDOWS_VERBATIM_ARGUMENTS = UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, + PROCESS_DETACHED = UV_PROCESS_DETACHED, + PROCESS_WINDOWS_HIDE = UV_PROCESS_WINDOWS_HIDE +}; + + +enum class UVStdIOFlags: std::underlying_type_t { + IGNORE = UV_IGNORE, + CREATE_PIPE = UV_CREATE_PIPE, + INHERIT_FD = UV_INHERIT_FD, + INHERIT_STREAM = UV_INHERIT_STREAM, + READABLE_PIPE = UV_READABLE_PIPE, + WRITABLE_PIPE = UV_WRITABLE_PIPE +}; + + +} + + +struct ExitEvent: Event { }; + + +class ProcessHandle final: public Handle { + static void exitCallback(uv_process_t *handle, int64_t exitStatus, int termSignal) { + ProcessHandle &process = *(static_cast(handle->data)); + process.publish(ExitEvent{}); + } + + using Handle::Handle; + +public: + using Process = details::UVProcessFlags; + using StdIO = details::UVStdIOFlags; + + template + static std::shared_ptr create(Args&&... args) { + return std::shared_ptr{new ProcessHandle{std::forward(args)...}}; + } + + static void disableStdIOInheritance() noexcept { + uv_disable_stdio_inheritance(); + } + + bool init() const noexcept { return true; } + + void spawn(const char *file, char **args, char **env = nullptr) { + uv_process_options_t po; + + po.exit_cb = &exitCallback; + + po.file = file; + po.args = args; + po.env = env; + + po.cwd = poCwd.data(); + po.flags = poFlags; + po.stdio_count = poStdio.size(); + po.stdio = poStdio.data(); + po.uid = poUid; + po.gid = poGid; + + invoke(&uv_spawn, parent(), get(), &po); + } + + void kill(int signum) { + invoke(&uv_process_kill, get(), signum); + } + + static bool kill(int pid, int signum) noexcept { + return (0 == uv_kill(pid, signum)); + } + + int pid() noexcept { + return get()->pid; + } + + ProcessHandle& cwd(std::string &path) noexcept { + poCwd = path; + return *this; + } + + ProcessHandle& flags(Flags flags) noexcept { + poFlags = flags; + return *this; + } + + template + ProcessHandle& stdio(Flags flags, StreamHandle &stream) { + uv_stdio_container_t container; + container.flags = flags; + container.data.stream = stream.get(); + poStdio.push_back(std::move(container)); + return *this; + } + + template + ProcessHandle& stdio(Flags flags, FileHandle fd) { + uv_stdio_container_t container; + container.flags = flags; + container.data.fd = fd; + poStdio.push_back(std::move(container)); + return *this; + } + + ProcessHandle& uid(Uid id) { + poUid = id; + return *this; + } + + ProcessHandle& gid(Gid id) { + poGid = id; + return *this; + } + +private: + std::string poCwd; + Flags poFlags; + std::vector poStdio; + Uid poUid; + Gid poGid; +}; + + +} diff --git a/src/uvw/util.hpp b/src/uvw/util.hpp index c8a7cfde..d57b673d 100644 --- a/src/uvw/util.hpp +++ b/src/uvw/util.hpp @@ -30,10 +30,20 @@ public: ~Flags() noexcept { static_assert(std::is_enum::value, "!"); } - constexpr Flags operator|(const Flags& f) const noexcept { return Flags(flags | f.flags); } + constexpr Flags& operator=(const Flags &f) noexcept { + flags = f.flags; + return *this; + } + + constexpr Flags& operator=(Flags &&f) noexcept { + flags = std::move(f.flags); + return *this; + } + + constexpr Flags operator|(const Flags &f) const noexcept { return Flags(flags | f.flags); } constexpr Flags operator|(E flag) const noexcept { return Flags(flags | toInnerType(flag)); } - constexpr Flags operator&(const Flags& f) const noexcept { return Flags(flags & f.flags); } + constexpr Flags operator&(const Flags &f) const noexcept { return Flags(flags & f.flags); } constexpr Flags operator&(E flag) const noexcept { return Flags(flags & toInnerType(flag)); } explicit constexpr operator bool() const noexcept { return !(flags == InnerType{}); }