diff --git a/src/uvw/event.hpp b/src/uvw/event.hpp index 7ae29444..300e186b 100644 --- a/src/uvw/event.hpp +++ b/src/uvw/event.hpp @@ -34,6 +34,9 @@ struct Event: BaseEvent { struct ErrorEvent: Event { explicit ErrorEvent(int code = 0) noexcept: ec(code) { } + template::value>> + explicit ErrorEvent(U val) noexcept: ec{static_cast(val)} { } + const char * what() const noexcept { return uv_strerror(ec); } int code() const noexcept { return ec; } diff --git a/src/uvw/fs.hpp b/src/uvw/fs.hpp index 9689e1e0..ff8f8eff 100644 --- a/src/uvw/fs.hpp +++ b/src/uvw/fs.hpp @@ -70,8 +70,48 @@ template struct TypedEvent : Event> { - using Type = details::UVFsType; - static constexpr details::UVFsType value = e; + TypedEvent(const char *p) noexcept + : rPath{p} + { } + + const char * path() const noexcept { return rPath; } + +private: + const char *rPath; +}; + + +template<> +struct TypedEvent + : Event> +{ + TypedEvent(const char *p, ssize_t s) noexcept + : rPath{p}, sz{s} + { } + + const char * path() const noexcept { return rPath; } + ssize_t amount() const noexcept { return sz; } + +private: + const char *rPath; + const ssize_t sz; +}; + + +template<> +struct TypedEvent + : Event> +{ + TypedEvent(const char *p, ssize_t s) noexcept + : rPath{p}, sz{s} + { } + + const char * path() const noexcept { return rPath; } + ssize_t amount() const noexcept { return sz; } + +private: + const char *rPath; + const ssize_t sz; }; @@ -79,14 +119,15 @@ template<> struct TypedEvent : Event> { - using Type = details::UVFsType; - static constexpr details::UVFsType value = details::UVFsType::STAT; - - TypedEvent(const Stat &s): fsStat{s} { } + TypedEvent(const char *p, const Stat &s) noexcept + : rPath{p}, fsStat{s} + { } + const char * path() const noexcept { return rPath; } const Stat & stat() const noexcept { return fsStat; } private: + const char *rPath; Stat fsStat; }; @@ -95,14 +136,15 @@ template<> struct TypedEvent : Event> { - using Type = details::UVFsType; - static constexpr details::UVFsType value = details::UVFsType::FSTAT; - - TypedEvent(const Stat &s): fsStat{s} { } + TypedEvent(const char *p, const Stat &s) noexcept + : rPath{p}, fsStat{s} + { } + const char * path() const noexcept { return rPath; } const Stat & stat() const noexcept { return fsStat; } private: + const char *rPath; Stat fsStat; }; @@ -111,71 +153,129 @@ template<> struct TypedEvent : Event> { - using Type = details::UVFsType; - static constexpr details::UVFsType value = details::UVFsType::LSTAT; - - TypedEvent(const Stat &s): fsStat{s} { } + TypedEvent(const char *p, const Stat &s) noexcept + : rPath{p}, fsStat{s} + { } + const char * path() const noexcept { return rPath; } const Stat & stat() const noexcept { return fsStat; } private: + const char *rPath; Stat fsStat; }; +template<> +struct TypedEvent + : Event> +{ + TypedEvent(const char *p, ssize_t s) noexcept + : rPath{p}, sz{s} + { } + + const char * path() const noexcept { return rPath; } + ssize_t amount() const noexcept { return sz; } + +private: + const char *rPath; + const ssize_t sz; +}; + + +template<> +struct TypedEvent + : Event> +{ + explicit TypedEvent(const char *p, const char *d, ssize_t l) noexcept + : rPath{p}, dt{d}, len{l} + { } + + const char * path() const noexcept { return rPath; } + const char * data() const noexcept { return dt; } + ssize_t length() const noexcept { return len; } + +private: + const char *rPath; + const char *dt; + const ssize_t len; +}; + + template using FsEvent = TypedEvent; class Fs final: public Request { - template - static void fsGenericCallback(uv_fs_t *req) { - Fs &fs = *(static_cast(req->data)); + static constexpr int BAD_FD = -1; - auto ptr = fs.shared_from_this(); - (void)ptr; - - fs.reset(); + static void fsCloseCallback(uv_fs_t *req) { + auto ptr = reserve(reinterpret_cast(req)); if(req->result) { - int err = req->result; - fs.publish(ErrorEvent{err}); + ptr->publish(ErrorEvent{req->result}); } else { - fs.publish(FsEvent{}); + ptr->file = BAD_FD; + ptr->publish(FsEvent{req->path}); } } + 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 = req->result; + ptr->publish(FsEvent{req->path}); + } + } + + template + static void fsGenericCallback(uv_fs_t *req) { + auto ptr = reserve(reinterpret_cast(req)); + if(req->result) { ptr->publish(ErrorEvent{req->result}); } + else { ptr->publish(FsEvent{req->path}); } + } + static void fsReadCallback(uv_fs_t *req) { // TODO - uv_fs_read callback } - static void fsWriteCallback(uv_fs_t *req) { - // TODO - uv_fs_write callback + template + static void fsResultCallback(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, req->result}); } } template static void fsStatCallback(uv_fs_t *req) { - Fs &fs = *(static_cast(req->data)); - - auto ptr = fs.shared_from_this(); - (void)ptr; - - fs.reset(); - - if(req->result) { - int err = req->result; - fs.publish(ErrorEvent{err}); - } else { - fs.publish(FsEvent{req->statbuf}); - } + auto ptr = reserve(reinterpret_cast(req)); + if(req->result) { ptr->publish(ErrorEvent{req->result}); } + else { ptr->publish(FsEvent{req->path, req->statbuf}); } } static void fsReadlinkCallback(uv_fs_t *req) { - // TODO - uv_fs_readlink callback + 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; + template + void cleanupAndInvoke(Args&&... args) { + uv_fs_req_cleanup(get()); + invoke(std::forward(args)...); + } + + template + void cleanupAndInvokeSync(F &&f, Args&&... args) { + uv_fs_req_cleanup(get()); + std::forward(f)(std::forward(args)...); + } + public: using Time = std::chrono::seconds; using Type = details::UVFsType; @@ -191,86 +291,99 @@ public: uv_fs_req_cleanup(get()); } - void close(FileHandle file) { - invoke(&uv_fs_close, parent(), get(), file, &fsGenericCallback); + void close() { + cleanupAndInvoke(&uv_fs_close, parent(), get(), file, &fsCloseCallback); } - auto closeSync(FileHandle file) { - auto err = uv_fs_close(parent(), get(), file, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto closeSync() { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_close, parent(), req, file, nullptr); + if(!req->result) { file = BAD_FD; } + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void open(std::string path, int flags, int mode) { - invoke(&uv_fs_open, parent(), get(), path.data(), flags, mode, &fsGenericCallback); + cleanupAndInvoke(&uv_fs_open, parent(), get(), path.data(), flags, mode, &fsOpenCallback); } auto openSync(std::string path, int flags, int mode) { - auto err = uv_fs_open(parent(), get(), path.data(), flags, mode, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_open, parent(), req, path.data(), flags, mode, nullptr); + auto fd = req->result; + if(fd >= 0) { file = fd; } + return std::make_pair(ErrorEvent{fd < 0 ? fd : 0}, FsEvent{req->path}); } - // TODO uv_fs_read (sync (cb null)/async) + void read(int64_t offset, unsigned int len) { + // TODO uv_fs_read (async) + } + + auto readSync(int64_t offset, unsigned int len) { + // TODO uv_fs_read (sync (cb null)) + } void unlink(std::string path) { - invoke(&uv_fs_unlink, parent(), get(), path.data(), &fsGenericCallback); + cleanupAndInvoke(&uv_fs_unlink, parent(), get(), path.data(), &fsGenericCallback); } auto unlinkSync(std::string path) { - auto err = uv_fs_unlink(parent(), get(), path.data(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_unlink, parent(), req, path.data(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void write(FileHandle file, char *data, ssize_t len, int64_t offset) { - uv_buf_t bufs[] = { uv_buf_init(data, len) }; - invoke(&uv_fs_write, parent(), get(), file, bufs, 1, offset, &fsWriteCallback); + 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); } - void write(FileHandle file, std::unique_ptr data, ssize_t len, int64_t offset) { - write(file, data.get(), len, offset); - } - - auto writeSync(FileHandle file, char *data, ssize_t len, int64_t offset) { - // TODO uv_fs_write (sync (cb null)) - } - - auto writeSync(FileHandle file, std::unique_ptr data, ssize_t len, int64_t offset) { - // TODO uv_fs_write (sync (cb null)) + 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, nullptr); + auto bw = req->result; + return std::make_pair(ErrorEvent{bw < 0 ? bw : 0}, FsEvent{req->path, bw}); } void mkdir(std::string path, int mode) { - invoke(&uv_fs_mkdir, parent(), get(), path.data(), mode, &fsGenericCallback); + cleanupAndInvoke(&uv_fs_mkdir, parent(), get(), path.data(), mode, &fsGenericCallback); } auto mkdirSync(std::string path, int mode) { - auto err = uv_fs_mkdir(parent(), get(), path.data(), mode, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_mkdir, parent(), req, path.data(), mode, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void mkdtemp(std::string tpl) { - invoke(&uv_fs_mkdtemp, parent(), get(), tpl.data(), &fsGenericCallback); + cleanupAndInvoke(&uv_fs_mkdtemp, parent(), get(), tpl.data(), &fsGenericCallback); } auto mkdtempSync(std::string tpl) { - auto err = uv_fs_mkdtemp(parent(), get(), tpl.data(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_mkdtemp, parent(), req, tpl.data(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void rmdir(std::string path) { - invoke(&uv_fs_rmdir, parent(), get(), path.data(), &fsGenericCallback); + cleanupAndInvoke(&uv_fs_rmdir, parent(), get(), path.data(), &fsGenericCallback); } auto rmdirSync(std::string path) { - auto err = uv_fs_rmdir(parent(), get(), path.data(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_rmdir, parent(), req, path.data(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void scandir(std::string path, int flags) { - invoke(&uv_fs_scandir, parent(), get(), path.data(), flags, &fsGenericCallback); + cleanupAndInvoke(&uv_fs_scandir, parent(), get(), path.data(), flags, &fsResultCallback); } auto scandirSync(std::string path, int flags) { - auto err = uv_fs_scandir(parent(), get(), path.data(), flags, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_scandir, parent(), req, path.data(), flags, nullptr); + auto sz = req->result; + return std::make_pair(ErrorEvent{sz < 0 ? sz : 0}, FsEvent{req->path, sz}); } std::pair scandirNext() { @@ -288,172 +401,201 @@ public: } void stat(std::string path) { - invoke(&uv_fs_stat, parent(), get(), path.data(), &fsStatCallback); + cleanupAndInvoke(&uv_fs_stat, parent(), get(), path.data(), &fsStatCallback); } auto statSync(std::string path) { - auto err = uv_fs_stat(parent(), get(), path.data(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{get()->statbuf}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_stat, parent(), req, path.data(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->statbuf}); } - void fstat(FileHandle file) { - invoke(&uv_fs_fstat, parent(), get(), file, &fsStatCallback); + void fstat() { + cleanupAndInvoke(&uv_fs_fstat, parent(), get(), file, &fsStatCallback); } - auto fstatSync(FileHandle file) { - auto err = uv_fs_fstat(parent(), get(), file, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{get()->statbuf}); + auto fstatSync() { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fstat, parent(), req, file, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->statbuf}); } void lstat(std::string path) { - invoke(&uv_fs_lstat, parent(), get(), path.data(), &fsStatCallback); + cleanupAndInvoke(&uv_fs_lstat, parent(), get(), path.data(), &fsStatCallback); } auto lstatSync(std::string path) { - auto err = uv_fs_lstat(parent(), get(), path.data(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{get()->statbuf}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_lstat, parent(), req, path.data(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path, req->statbuf}); } void rename(std::string old, std::string path) { - invoke(&uv_fs_rename, parent(), get(), old.data(), path.data(), &fsGenericCallback); + cleanupAndInvoke(&uv_fs_rename, parent(), get(), old.data(), path.data(), &fsGenericCallback); } auto renameSync(std::string old, std::string path) { - auto err = uv_fs_rename(parent(), get(), old.data(), path.data(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_rename, parent(), req, old.data(), path.data(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void fsync(FileHandle file) { - invoke(&uv_fs_fsync, parent(), get(), file, &fsGenericCallback); + void fsync() { + cleanupAndInvoke(&uv_fs_fsync, parent(), get(), file, &fsGenericCallback); } - auto fsyncSync(FileHandle file) { - auto err = uv_fs_fsync(parent(), get(), file, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto fsyncSync() { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fsync, parent(), req, file, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void fdatasync(FileHandle file) { - invoke(&uv_fs_fdatasync, parent(), get(), file, &fsGenericCallback); + void fdatasync() { + cleanupAndInvoke(&uv_fs_fdatasync, parent(), get(), file, &fsGenericCallback); } - auto fdatasyncSync(FileHandle file) { - auto err = uv_fs_fdatasync(parent(), get(), file, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto fdatasyncSync() { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fdatasync, parent(), req, file, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void ftruncate(FileHandle file, int64_t offset) { - invoke(&uv_fs_ftruncate, parent(), get(), file, offset, &fsGenericCallback); + void ftruncate(int64_t offset) { + cleanupAndInvoke(&uv_fs_ftruncate, parent(), get(), file, offset, &fsGenericCallback); } - auto ftruncateSync(FileHandle file, int64_t offset) { - auto err = uv_fs_ftruncate(parent(), get(), file, offset, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto ftruncateSync(int64_t offset) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_ftruncate, parent(), req, file, offset, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void sendfile(FileHandle out, FileHandle in, int64_t offset, size_t length) { - invoke(&uv_fs_sendfile, parent(), get(), out, in, offset, length, &fsGenericCallback); + 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, FileHandle in, int64_t offset, size_t length) { - auto err = uv_fs_sendfile(parent(), get(), out, in, offset, length, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto sendfileSync(FileHandle out, int64_t offset, size_t length) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_sendfile, parent(), req, out, file, offset, length, nullptr); + auto bw = req->result; + return std::make_pair(ErrorEvent{bw < 0 ? bw : 0}, FsEvent{req->path, bw}); } void access(std::string path, int mode) { - invoke(&uv_fs_access, parent(), get(), path.data(), mode, &fsGenericCallback); + cleanupAndInvoke(&uv_fs_access, parent(), get(), path.data(), mode, &fsGenericCallback); } auto accessSync(std::string path, int mode) { - auto err = uv_fs_access(parent(), get(), path.data(), mode, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_access, parent(), req, path.data(), mode, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void chmod(std::string path, int mode) { - invoke(&uv_fs_chmod, parent(), get(), path.data(), mode, &fsGenericCallback); + cleanupAndInvoke(&uv_fs_chmod, parent(), get(), path.data(), mode, &fsGenericCallback); } auto chmodSync(std::string path, int mode) { - auto err = uv_fs_chmod(parent(), get(), path.data(), mode, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_chmod, parent(), req, path.data(), mode, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void fchmod(FileHandle file, int mode) { - invoke(&uv_fs_fchmod, parent(), get(), file, mode, &fsGenericCallback); + void fchmod(int mode) { + cleanupAndInvoke(&uv_fs_fchmod, parent(), get(), file, mode, &fsGenericCallback); } - auto fchmodSync(FileHandle file, int mode) { - auto err = uv_fs_fchmod(parent(), get(), file, mode, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto fchmodSync(int mode) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fchmod, parent(), req, file, mode, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void utime(std::string path, Time atime, Time mtime) { - invoke(&uv_fs_utime, parent(), get(), path.data(), atime.count(), mtime.count(), &fsGenericCallback); + cleanupAndInvoke(&uv_fs_utime, parent(), get(), path.data(), atime.count(), mtime.count(), &fsGenericCallback); } auto utimeSync(std::string path, Time atime, Time mtime) { - auto err = uv_fs_utime(parent(), get(), path.data(), atime.count(), mtime.count(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_utime, parent(), req, path.data(), atime.count(), mtime.count(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void futime(FileHandle file, Time atime, Time mtime) { - invoke(&uv_fs_futime, parent(), get(), file, atime.count(), mtime.count(), &fsGenericCallback); + void futime(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 err = uv_fs_futime(parent(), get(), file, atime.count(), mtime.count(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto futimeSync(Time atime, Time mtime) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_futime, parent(), req, file, atime.count(), mtime.count(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void link(std::string old, std::string path) { - invoke(&uv_fs_link, parent(), get(), old.data(), path.data(), &fsGenericCallback); + cleanupAndInvoke(&uv_fs_link, parent(), get(), old.data(), path.data(), &fsGenericCallback); } auto linkSync(std::string old, std::string path) { - auto err = uv_fs_link(parent(), get(), old.data(), path.data(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_link, parent(), req, old.data(), path.data(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void symlink(std::string old, std::string path, int flags) { - invoke(&uv_fs_symlink, parent(), get(), old.data(), path.data(), flags, &fsGenericCallback); + cleanupAndInvoke(&uv_fs_symlink, parent(), get(), old.data(), path.data(), flags, &fsGenericCallback); } auto symlinkSync(std::string old, std::string path, int flags) { - auto err = uv_fs_symlink(parent(), get(), old.data(), path.data(), flags, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_symlink, parent(), req, old.data(), path.data(), flags, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void readlink(std::string path) { - invoke(&uv_fs_readlink, parent(), get(), path.data(), &fsReadlinkCallback); + cleanupAndInvoke(&uv_fs_readlink, parent(), get(), path.data(), &fsReadlinkCallback); } - // TODO uv_fs_readlink (sync (cb null)) + auto readlinkSync(std::string path) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_readlink, parent(), req, path.data(), nullptr); + auto bw = req->result; + return std::make_pair(ErrorEvent{bw < 0 ? bw : 0}, FsEvent{req->path, static_cast(req->ptr), bw}); + } void realpath(std::string path) { - invoke(&uv_fs_realpath, parent(), get(), path.data(), &fsGenericCallback); + cleanupAndInvoke(&uv_fs_realpath, parent(), get(), path.data(), &fsGenericCallback); } auto realpathSync(std::string path) { - auto err = uv_fs_realpath(parent(), get(), path.data(), nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_realpath, parent(), req, path.data(), nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } void chown(std::string path, Uid uid, Gid gid) { - invoke(&uv_fs_chown, parent(), get(), path.data(), uid, gid, &fsGenericCallback); + cleanupAndInvoke(&uv_fs_chown, parent(), get(), path.data(), uid, gid, &fsGenericCallback); } auto chownSync(std::string path, Uid uid, Gid gid) { - auto err = uv_fs_chown(parent(), get(), path.data(), uid, gid, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto req = get(); + cleanupAndInvokeSync(&uv_fs_chown, parent(), req, path.data(), uid, gid, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } - void fchown(FileHandle file, Uid uid, Gid gid) { - invoke(&uv_fs_fchown, parent(), get(), file, uid, gid, &fsGenericCallback); + void fchown(Uid uid, Gid gid) { + cleanupAndInvoke(&uv_fs_fchown, parent(), get(), file, uid, gid, &fsGenericCallback); } - auto fchownSync(FileHandle file, Uid uid, Gid gid) { - auto err = uv_fs_fchown(parent(), get(), file, uid, gid, nullptr); - return std::make_pair(ErrorEvent{err}, FsEvent{}); + auto fchownSync(Uid uid, Gid gid) { + auto req = get(); + cleanupAndInvokeSync(&uv_fs_fchown, parent(), req, file, uid, gid, nullptr); + return std::make_pair(ErrorEvent{req->result}, FsEvent{req->path}); } + + operator FileHandle() const noexcept { return file; } + +private: + uv_file file{BAD_FD}; }; diff --git a/src/uvw/handle.hpp b/src/uvw/handle.hpp index 2e54f226..48e4d3de 100644 --- a/src/uvw/handle.hpp +++ b/src/uvw/handle.hpp @@ -63,6 +63,13 @@ protected: return this->self(); } + template + auto invoke(F &&f, Args&&... args) { + auto err = std::forward(f)(std::forward(args)...); + if(err) { Emitter::publish(ErrorEvent{err}); } + return err; + } + public: bool active() const noexcept override { return !(uv_is_active(this->template get()) == 0); diff --git a/src/uvw/request.hpp b/src/uvw/request.hpp index 11569f52..4c062836 100644 --- a/src/uvw/request.hpp +++ b/src/uvw/request.hpp @@ -13,43 +13,42 @@ namespace uvw { template class Request: public Resource { - template - static void execCallback(R *req, int status) { - T &res = *(static_cast(req->data)); - - auto ptr = res.shared_from_this(); - (void)ptr; - - res.reset(); - - if(status) { - res.publish(ErrorEvent{status}); - } else { - res.publish(E{}); - } - } - protected: using Resource::Resource; - template - auto exec(F &&f, Args&&... args) - -> std::enable_if_t))>>::value, int> { - auto ret = this->invoke(std::forward(f), std::forward(args)..., &execCallback); - if(0 == ret) { this->leak(); } - return ret; + static auto reserve(uv_req_t *req) { + auto ptr = static_cast(req->data)->shared_from_this(); + ptr->reset(); + return ptr; } - template - auto exec(F &&f, Args&&... args) - -> std::enable_if_t))>>::value> { - std::forward(f)(std::forward(args)..., &execCallback); + template + static void defaultCallback(R *req, int status) { + auto ptr = reserve(reinterpret_cast(req)); + if(status) { ptr->publish(ErrorEvent{status}); } + else { ptr->publish(E{}); } + } + + template + auto invoke(F &&f, Args&&... args) + -> std::enable_if_t>::value, int> { + auto err = std::forward(f)(std::forward(args)...); + if(err) { Emitter::publish(ErrorEvent{err}); } + else { this->leak(); } + return err; + } + + template + auto invoke(F &&f, Args&&... args) + -> std::enable_if_t>::value> { + std::forward(f)(std::forward(args)...); this->leak(); } public: void cancel() { - this->invoke(&uv_cancel, this->template get()); + auto err = uv_cancel(this->template get()); + if(err) { Emitter::publish(ErrorEvent{err}); } } std::size_t size() const noexcept { diff --git a/src/uvw/resource.hpp b/src/uvw/resource.hpp index d92ad1ee..c614cb4e 100644 --- a/src/uvw/resource.hpp +++ b/src/uvw/resource.hpp @@ -35,13 +35,6 @@ protected: template auto get() const noexcept { return reinterpret_cast(&resource); } - template - auto invoke(F &&f, Args&&... args) { - auto err = std::forward(f)(std::forward(args)...); - if(err) { Emitter::publish(ErrorEvent{err}); } - return err; - } - public: Resource(const Resource &) = delete; Resource(Resource &&) = delete; diff --git a/src/uvw/stream.hpp b/src/uvw/stream.hpp index 8522b710..bd26d1ae 100644 --- a/src/uvw/stream.hpp +++ b/src/uvw/stream.hpp @@ -50,7 +50,7 @@ public: template void connect(F &&f, Args... args) { - exec(std::forward(f), get(), std::forward(args)...); + invoke(std::forward(f), get(), std::forward(args)..., &defaultCallback); } }; @@ -65,7 +65,7 @@ public: } void shutdown(uv_stream_t *handle) { - exec(&uv_shutdown, get(), handle); + invoke(&uv_shutdown, get(), handle, &defaultCallback); } }; @@ -80,11 +80,11 @@ public: } void write(uv_stream_t *handle, const uv_buf_t bufs[], unsigned int nbufs) { - exec(&uv_write, get(), handle, bufs, nbufs); + invoke(&uv_write, get(), handle, bufs, nbufs, &defaultCallback); } void write(uv_stream_t *handle, const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t *send) { - exec(&uv_write2, get(), handle, bufs, nbufs, send); + invoke(&uv_write2, get(), handle, bufs, nbufs, send, &defaultCallback); } }; @@ -155,8 +155,8 @@ public: this->invoke(&uv_read_stop, this->template get()); } - void write(char *data, ssize_t len) { - uv_buf_t bufs[] = { uv_buf_init(data, len) }; + void write(std::unique_ptr data, ssize_t len) { + uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; auto listener = [ptr = this->shared_from_this()](const auto &event, details::Write &) { ptr->publish(event); @@ -168,13 +168,9 @@ public: write->write(this->template get(), bufs, 1); } - void write(std::unique_ptr data, ssize_t len) { - write(data.get(), len); - } - template - void write(S &send, char *data, ssize_t len) { - uv_buf_t bufs[] = { uv_buf_init(data, len) }; + void write(S &send, std::unique_ptr data, ssize_t len) { + uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; auto listener = [ptr = this->shared_from_this()](const auto &event, details::Write &) { ptr->publish(event); @@ -186,13 +182,8 @@ public: write->write(this->template get(), bufs, 1, send.template get()); } - template - void write(S &send, std::unique_ptr data, ssize_t len) { - write(send, data.get(), len); - } - - int tryWrite(char *data, ssize_t len) { - uv_buf_t bufs[] = { uv_buf_init(data, len) }; + int tryWrite(std::unique_ptr data, ssize_t len) { + uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; auto bw = uv_try_write(this->template get(), bufs, 1); if(bw < 0) { @@ -203,10 +194,6 @@ public: return bw; } - int tryWrite(std::unique_ptr data, ssize_t len) { - return tryWrite(data.get(), len); - } - bool readable() const noexcept { return (uv_is_readable(this->template get()) == 1); } diff --git a/src/uvw/tty.hpp b/src/uvw/tty.hpp index c1e2102a..636e006a 100644 --- a/src/uvw/tty.hpp +++ b/src/uvw/tty.hpp @@ -30,9 +30,7 @@ class TTY final: public Stream { explicit TTY(std::shared_ptr ref, FileHandle desc, bool readable) - : Stream{std::move(ref)}, - fd{static_cast(desc)}, - rw{readable} + : Stream{std::move(ref)}, fd{desc}, rw{readable} { } public: diff --git a/src/uvw/udp.hpp b/src/uvw/udp.hpp index 1a61e163..c279efaa 100644 --- a/src/uvw/udp.hpp +++ b/src/uvw/udp.hpp @@ -61,7 +61,7 @@ public: } void send(uv_udp_t *handle, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr* addr) { - exec(&uv_udp_send, get(), handle, bufs, nbufs, addr); + invoke(&uv_udp_send, get(), handle, bufs, nbufs, addr, &defaultCallback); } }; @@ -156,11 +156,11 @@ public: void ttl(int val) { invoke(&uv_udp_set_ttl, get(), val > 255 ? 255 : val); } template - void send(std::string ip, unsigned int port, char *data, ssize_t len) { + void send(std::string ip, unsigned int port, std::unique_ptr data, ssize_t len) { typename details::IpTraits::Type addr; details::IpTraits::AddrFunc(ip.data(), port, &addr); - uv_buf_t bufs[] = { uv_buf_init(data, len) }; + uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; auto listener = [ptr = shared_from_this()](const auto &event, details::Send &) { ptr->publish(event); @@ -173,16 +173,11 @@ public: } template - void send(std::string ip, unsigned int port, std::unique_ptr data, ssize_t len) { - send(ip, port, data.get(), len); - } - - template - int trySend(std::string ip, unsigned int port, char *data, ssize_t len) { + int trySend(std::string ip, unsigned int port, std::unique_ptr data, ssize_t len) { typename details::IpTraits::Type addr; details::IpTraits::AddrFunc(ip.data(), port, &addr); - uv_buf_t bufs[] = { uv_buf_init(data, len) }; + uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; auto bw = uv_udp_try_send(get(), bufs, 1, reinterpret_cast(&addr)); if(bw < 0) { @@ -193,11 +188,6 @@ public: return bw; } - template - int trySend(std::string ip, unsigned int port, std::unique_ptr data, ssize_t len) { - return trySend(ip, port, data.get(), len); - } - template void recv() { invoke(&uv_udp_recv_start, get(), &allocCallback, &recvCallback); diff --git a/src/uvw/work.hpp b/src/uvw/work.hpp index 93324682..6450378b 100644 --- a/src/uvw/work.hpp +++ b/src/uvw/work.hpp @@ -32,7 +32,7 @@ public: } void queue(Task t) { - if(0 == exec(&uv_queue_work, parent(), get(), &workCallback)) { + if(0 == invoke(&uv_queue_work, parent(), get(), &workCallback, &defaultCallback)) { task = std::move(t); } }