Merge pull request #33 from cynnyx/master

review Fs* + added ProcessHandle + AOB
This commit is contained in:
Michele Caini 2016-07-29 11:39:11 +02:00 committed by GitHub
commit 1f34323202
22 changed files with 530 additions and 212 deletions

View File

@ -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"

View File

@ -29,9 +29,13 @@ public:
return std::shared_ptr<AsyncHandle>{new AsyncHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_async_t>(&uv_async_init, &sendCallback); }
bool init() {
return initialize<uv_async_t>(&uv_async_init, &sendCallback);
}
void send() { invoke(&uv_async_send, get<uv_async_t>()); }
void send() {
invoke(&uv_async_send, get<uv_async_t>());
}
};

View File

@ -29,10 +29,17 @@ public:
return std::shared_ptr<CheckHandle>{new CheckHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_check_t>(&uv_check_init); }
bool init() {
return initialize<uv_check_t>(&uv_check_init);
}
void start() { invoke(&uv_check_start, get<uv_check_t>(), &startCallback); }
void stop() { invoke(&uv_check_stop, get<uv_check_t>()); }
void start() {
invoke(&uv_check_start, get<uv_check_t>(), &startCallback);
}
void stop() {
invoke(&uv_check_stop, get<uv_check_t>());
}
};

View File

@ -18,7 +18,7 @@ namespace uvw {
template<typename T>
class Emitter {
struct BaseHandler {
virtual ~BaseHandler() = default;
virtual ~BaseHandler() noexcept = default;
virtual bool empty() const noexcept = 0;
};

View File

@ -81,23 +81,6 @@ private:
};
template<>
struct TypedEvent<details::UVFsType, details::UVFsType::OPEN>
: Event<TypedEvent<details::UVFsType, details::UVFsType::OPEN>>
{
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<details::UVFsType, details::UVFsType::READ>
: Event<TypedEvent<details::UVFsType, details::UVFsType::READ>>
@ -242,57 +225,41 @@ template<details::UVFsType e>
using FsEvent = TypedEvent<details::UVFsType, e>;
class FsReq final: public Request<FsReq, uv_fs_t> {
static void fsOpenCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); }
else { ptr->publish(FsEvent<Type::OPEN>{req->path, static_cast<uv_file>(req->result)}); }
}
static void fsReadCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); }
else { ptr->publish(FsEvent<Type::READ>{req->path, std::move(ptr->data), req->result}); }
}
template<typename T>
class FsRequest: public Request<T, uv_fs_t> {
protected:
template<details::UVFsType e>
static void fsGenericCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
auto ptr = Request<T, uv_fs_t>::reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); }
else { ptr->publish(FsEvent<e>{req->path}); }
}
template<details::UVFsType e>
static void fsResultCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
auto ptr = Request<T, uv_fs_t>::reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); }
else { ptr->publish(FsEvent<e>{req->path, req->result}); }
}
template<details::UVFsType e>
static void fsStatCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
auto ptr = Request<T, uv_fs_t>::reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); }
else { ptr->publish(FsEvent<e>{req->path, req->statbuf}); }
}
static void fsReadlinkCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); }
else { ptr->publish(FsEvent<Type::READLINK>{req->path, static_cast<char *>(req->ptr), req->result}); }
}
using Request::Request;
using Request<T, uv_fs_t>::Request;
template<typename... Args>
void cleanupAndInvoke(Args&&... args) {
uv_fs_req_cleanup(get<uv_fs_t>());
invoke(std::forward<Args>(args)...);
uv_fs_req_cleanup(this->template get<uv_fs_t>());
this->invoke(std::forward<Args>(args)...);
}
template<typename F, typename... Args>
void cleanupAndInvokeSync(F &&f, Args&&... args) {
uv_fs_req_cleanup(get<uv_fs_t>());
uv_fs_req_cleanup(this->template get<uv_fs_t>());
std::forward<F>(f)(std::forward<Args>(args)..., nullptr);
}
@ -301,23 +268,60 @@ public:
using Type = details::UVFsType;
using EntryType = details::UVDirentTypeT;
using Entry = std::pair<EntryType, std::string>;
};
template<typename... Args>
static std::shared_ptr<FsReq> create(Args&&... args) {
return std::shared_ptr<FsReq>{new FsReq{std::forward<Args>(args)...}};
class FileReq final: public FsRequest<FileReq> {
static constexpr uv_file BAD_FD = -1;
static void fsOpenCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) {
ptr->publish(ErrorEvent{req->result});
} else {
ptr->file = static_cast<uv_file>(req->result);
ptr->publish(FsEvent<Type::OPEN>{req->path});
}
}
~FsReq() {
static void fsCloseCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) {
ptr->publish(ErrorEvent{req->result});
} else {
ptr->file = BAD_FD;
ptr->publish(FsEvent<Type::CLOSE>{req->path});
}
}
static void fsReadCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); }
else { ptr->publish(FsEvent<Type::READ>{req->path, std::move(ptr->data), req->result}); }
}
using FsRequest::FsRequest;
public:
template<typename... Args>
static std::shared_ptr<FileReq> create(Args&&... args) {
return std::shared_ptr<FileReq>{new FileReq{std::forward<Args>(args)...}};
}
~FileReq() noexcept {
uv_fs_req_cleanup(get<uv_fs_t>());
}
void close(FileHandle file) {
cleanupAndInvoke(&uv_fs_close, parent(), get<uv_fs_t>(), file, &fsGenericCallback<Type::CLOSE>);
void close() {
cleanupAndInvoke(&uv_fs_close, parent(), get<uv_fs_t>(), file, &fsCloseCallback);
}
auto closeSync(FileHandle file) {
auto closeSync() {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_close, parent(), req, file);
if(req->result >= 0) { file = BAD_FD; }
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::CLOSE>{req->path});
}
@ -328,17 +332,18 @@ public:
auto openSync(std::string path, int flags, int mode) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_open, parent(), req, path.data(), flags, mode);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::OPEN>{req->path, static_cast<uv_file>(req->result)});
if(req->result >= 0) { file = static_cast<uv_file>(req->result); }
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::OPEN>{req->path});
}
void read(FileHandle file, int64_t offset, unsigned int len) {
void read(int64_t offset, unsigned int len) {
data = std::unique_ptr<char[]>{new char[len]};
buffer = uv_buf_init(data.get(), len);
uv_buf_t bufs[] = { buffer };
cleanupAndInvoke(&uv_fs_read, parent(), get<uv_fs_t>(), 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<char[]>{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<Type::READ>{req->path, std::move(data), req->result});
}
void write(std::unique_ptr<char[]> data, ssize_t len, int64_t offset) {
uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
cleanupAndInvoke(&uv_fs_write, parent(), get<uv_fs_t>(), file, bufs, 1, offset, &fsResultCallback<Type::WRITE>);
}
auto writeSync(std::unique_ptr<char[]> data, ssize_t len, int64_t offset) {
uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_write, parent(), get<uv_fs_t>(), file, bufs, 1, offset);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::WRITE>{req->path, req->result});
}
void fstat() {
cleanupAndInvoke(&uv_fs_fstat, parent(), get<uv_fs_t>(), file, &fsStatCallback<Type::FSTAT>);
}
auto fstatSync() {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fstat, parent(), req, file);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FSTAT>{req->path, req->statbuf});
}
void fsync() {
cleanupAndInvoke(&uv_fs_fsync, parent(), get<uv_fs_t>(), file, &fsGenericCallback<Type::FSYNC>);
}
auto fsyncSync() {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fsync, parent(), req, file);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FSYNC>{req->path});
}
void fdatasync() {
cleanupAndInvoke(&uv_fs_fdatasync, parent(), get<uv_fs_t>(), file, &fsGenericCallback<Type::FDATASYNC>);
}
auto fdatasyncSync() {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fdatasync, parent(), req, file);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FDATASYNC>{req->path});
}
void ftruncate(int64_t offset) {
cleanupAndInvoke(&uv_fs_ftruncate, parent(), get<uv_fs_t>(), file, offset, &fsGenericCallback<Type::FTRUNCATE>);
}
auto ftruncateSync(int64_t offset) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_ftruncate, parent(), req, file, offset);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FTRUNCATE>{req->path});
}
void sendfile(FileHandle out, int64_t offset, size_t length) {
cleanupAndInvoke(&uv_fs_sendfile, parent(), get<uv_fs_t>(), out, file, offset, length, &fsResultCallback<Type::SENDFILE>);
}
auto sendfileSync(FileHandle out, int64_t offset, size_t length) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_sendfile, parent(), req, out, file, offset, length);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::SENDFILE>{req->path, req->result});
}
void fchmod(int mode) {
cleanupAndInvoke(&uv_fs_fchmod, parent(), get<uv_fs_t>(), file, mode, &fsGenericCallback<Type::FCHMOD>);
}
auto fchmodSync(int mode) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fchmod, parent(), req, file, mode);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FCHMOD>{req->path});
}
void futime(Time atime, Time mtime) {
cleanupAndInvoke(&uv_fs_futime, parent(), get<uv_fs_t>(), file, atime.count(), mtime.count(), &fsGenericCallback<Type::FUTIME>);
}
auto futimeSync(Time atime, Time mtime) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_futime, parent(), req, file, atime.count(), mtime.count());
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FUTIME>{req->path});
}
void fchown(Uid uid, Gid gid) {
cleanupAndInvoke(&uv_fs_fchown, parent(), get<uv_fs_t>(), file, uid, gid, &fsGenericCallback<Type::FCHOWN>);
}
auto fchownSync(Uid uid, Gid gid) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fchown, parent(), req, file, uid, gid);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FCHOWN>{req->path});
}
operator FileHandle() const noexcept { return file; }
private:
std::unique_ptr<char[]> data{nullptr};
uv_buf_t buffer{};
uv_file file{BAD_FD};
};
class FsReq final: public FsRequest<FsReq> {
using FsRequest::FsRequest;
static void fsReadlinkCallback(uv_fs_t *req) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
if(req->result < 0) { ptr->publish(ErrorEvent{req->result}); }
else { ptr->publish(FsEvent<Type::READLINK>{req->path, static_cast<char *>(req->ptr), req->result}); }
}
public:
template<typename... Args>
static std::shared_ptr<FsReq> create(Args&&... args) {
return std::shared_ptr<FsReq>{new FsReq{std::forward<Args>(args)...}};
}
~FsReq() noexcept {
uv_fs_req_cleanup(get<uv_fs_t>());
}
void unlink(std::string path) {
cleanupAndInvoke(&uv_fs_unlink, parent(), get<uv_fs_t>(), path.data(), &fsGenericCallback<Type::UNLINK>);
}
@ -357,18 +482,6 @@ public:
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::UNLINK>{req->path});
}
void write(FileHandle file, std::unique_ptr<char[]> data, ssize_t len, int64_t offset) {
uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
cleanupAndInvoke(&uv_fs_write, parent(), get<uv_fs_t>(), file, bufs, 1, offset, &fsResultCallback<Type::WRITE>);
}
auto writeSync(FileHandle file, std::unique_ptr<char[]> data, ssize_t len, int64_t offset) {
uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_write, parent(), get<uv_fs_t>(), file, bufs, 1, offset);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::WRITE>{req->path, req->result});
}
void mkdir(std::string path, int mode) {
cleanupAndInvoke(&uv_fs_mkdir, parent(), get<uv_fs_t>(), path.data(), mode, &fsGenericCallback<Type::MKDIR>);
}
@ -433,16 +546,6 @@ public:
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::STAT>{req->path, req->statbuf});
}
void fstat(FileHandle file) {
cleanupAndInvoke(&uv_fs_fstat, parent(), get<uv_fs_t>(), file, &fsStatCallback<Type::FSTAT>);
}
auto fstatSync(FileHandle file) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fstat, parent(), req, file);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FSTAT>{req->path, req->statbuf});
}
void lstat(std::string path) {
cleanupAndInvoke(&uv_fs_lstat, parent(), get<uv_fs_t>(), path.data(), &fsStatCallback<Type::LSTAT>);
}
@ -463,46 +566,6 @@ public:
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::RENAME>{req->path});
}
void fsync(FileHandle file) {
cleanupAndInvoke(&uv_fs_fsync, parent(), get<uv_fs_t>(), file, &fsGenericCallback<Type::FSYNC>);
}
auto fsyncSync(FileHandle file) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fsync, parent(), req, file);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FSYNC>{req->path});
}
void fdatasync(FileHandle file) {
cleanupAndInvoke(&uv_fs_fdatasync, parent(), get<uv_fs_t>(), file, &fsGenericCallback<Type::FDATASYNC>);
}
auto fdatasyncSync(FileHandle file) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fdatasync, parent(), req, file);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FDATASYNC>{req->path});
}
void ftruncate(FileHandle file, int64_t offset) {
cleanupAndInvoke(&uv_fs_ftruncate, parent(), get<uv_fs_t>(), file, offset, &fsGenericCallback<Type::FTRUNCATE>);
}
auto ftruncateSync(FileHandle file, int64_t offset) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_ftruncate, parent(), req, file, offset);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FTRUNCATE>{req->path});
}
void sendfile(FileHandle out, FileHandle in, int64_t offset, size_t length) {
cleanupAndInvoke(&uv_fs_sendfile, parent(), get<uv_fs_t>(), out, in, offset, length, &fsResultCallback<Type::SENDFILE>);
}
auto sendfileSync(FileHandle out, FileHandle in, int64_t offset, size_t length) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_sendfile, parent(), req, out, in, offset, length);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::SENDFILE>{req->path, req->result});
}
void access(std::string path, int mode) {
cleanupAndInvoke(&uv_fs_access, parent(), get<uv_fs_t>(), path.data(), mode, &fsGenericCallback<Type::ACCESS>);
}
@ -523,16 +586,6 @@ public:
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::CHMOD>{req->path});
}
void fchmod(FileHandle file, int mode) {
cleanupAndInvoke(&uv_fs_fchmod, parent(), get<uv_fs_t>(), file, mode, &fsGenericCallback<Type::FCHMOD>);
}
auto fchmodSync(FileHandle file, int mode) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fchmod, parent(), req, file, mode);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FCHMOD>{req->path});
}
void utime(std::string path, Time atime, Time mtime) {
cleanupAndInvoke(&uv_fs_utime, parent(), get<uv_fs_t>(), path.data(), atime.count(), mtime.count(), &fsGenericCallback<Type::UTIME>);
}
@ -543,16 +596,6 @@ public:
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::UTIME>{req->path});
}
void futime(FileHandle file, Time atime, Time mtime) {
cleanupAndInvoke(&uv_fs_futime, parent(), get<uv_fs_t>(), file, atime.count(), mtime.count(), &fsGenericCallback<Type::FUTIME>);
}
auto futimeSync(FileHandle file, Time atime, Time mtime) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_futime, parent(), req, file, atime.count(), mtime.count());
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FUTIME>{req->path});
}
void link(std::string old, std::string path) {
cleanupAndInvoke(&uv_fs_link, parent(), get<uv_fs_t>(), old.data(), path.data(), &fsGenericCallback<Type::LINK>);
}
@ -602,20 +645,6 @@ public:
cleanupAndInvokeSync(&uv_fs_chown, parent(), req, path.data(), uid, gid);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::CHOWN>{req->path});
}
void fchown(FileHandle file, Uid uid, Gid gid) {
cleanupAndInvoke(&uv_fs_fchown, parent(), get<uv_fs_t>(), file, uid, gid, &fsGenericCallback<Type::FCHOWN>);
}
auto fchownSync(FileHandle file, Uid uid, Gid gid) {
auto req = get<uv_fs_t>();
cleanupAndInvokeSync(&uv_fs_fchown, parent(), req, file, uid, gid);
return std::make_pair(ErrorEvent{req->result}, FsEvent<Type::FCHOWN>{req->path});
}
private:
std::unique_ptr<char[]> data;
uv_buf_t buffer;
};

View File

@ -64,14 +64,21 @@ public:
return std::shared_ptr<FsEventHandle>{new FsEventHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_fs_event_t>(&uv_fs_event_init); }
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>()); }
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

@ -42,14 +42,21 @@ public:
return std::shared_ptr<FsPollHandle>{new FsPollHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_fs_poll_t>(&uv_fs_poll_init); }
bool init() {
return initialize<uv_fs_poll_t>(&uv_fs_poll_init);
}
void start(std::string file, unsigned int interval) {
invoke(&uv_fs_poll_start, get<uv_fs_poll_t>(), &startCallback, file.data(), interval);
}
void stop() { invoke(&uv_fs_poll_stop, get<uv_fs_poll_t>()); }
std::string path() noexcept { return details::path(&uv_fs_poll_getpath, get<uv_fs_poll_t>()); }
void stop() {
invoke(&uv_fs_poll_stop, get<uv_fs_poll_t>());
}
std::string path() noexcept {
return details::path(&uv_fs_poll_getpath, get<uv_fs_poll_t>());
}
};

View File

@ -29,10 +29,17 @@ public:
return std::shared_ptr<IdleHandle>{new IdleHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_idle_t>(&uv_idle_init); }
bool init() {
return initialize<uv_idle_t>(&uv_idle_init);
}
void start() { invoke(&uv_idle_start, get<uv_idle_t>(), &startCallback); }
void stop() { invoke(&uv_idle_stop, get<uv_idle_t>()); }
void start() {
invoke(&uv_idle_start, get<uv_idle_t>(), &startCallback);
}
void stop() {
invoke(&uv_idle_stop, get<uv_idle_t>());
}
};

View File

@ -40,7 +40,9 @@ public:
return std::shared_ptr<PipeHandle>{new PipeHandle{std::forward<Args>(args)...}};
}
bool init(bool ipc = false) { return initialize<uv_pipe_t>(&uv_pipe_init, ipc); }
bool init(bool ipc = false) {
return initialize<uv_pipe_t>(&uv_pipe_init, ipc);
}
void open(FileHandle file) {
invoke(&uv_pipe_open, get<uv_pipe_t>(), file);
@ -61,11 +63,21 @@ public:
connect->connect(&uv_pipe_connect, get<uv_pipe_t>(), name.data());
}
std::string sock() const noexcept { return details::path(&uv_pipe_getsockname, get<uv_pipe_t>()); }
std::string peer() const noexcept { return details::path(&uv_pipe_getpeername, get<uv_pipe_t>()); }
std::string sock() const noexcept {
return details::path(&uv_pipe_getsockname, get<uv_pipe_t>());
}
void pending(int count) noexcept { uv_pipe_pending_instances(get<uv_pipe_t>(), count); }
int pending() noexcept { return uv_pipe_pending_count(get<uv_pipe_t>()); }
std::string peer() const noexcept {
return details::path(&uv_pipe_getpeername, get<uv_pipe_t>());
}
void pending(int count) noexcept {
uv_pipe_pending_instances(get<uv_pipe_t>(), count);
}
int pending() noexcept {
return uv_pipe_pending_count(get<uv_pipe_t>());
}
Pending receive() noexcept {
auto type = uv_pipe_pending_type(get<uv_pipe_t>());

View File

@ -55,11 +55,21 @@ public:
return std::shared_ptr<PollHandle>{new PollHandle{std::forward<Args>(args)...}};
}
bool init(int fd) { return initialize<uv_poll_t>(&uv_poll_init, fd); }
bool init(int fd) {
return initialize<uv_poll_t>(&uv_poll_init, fd);
}
void start(Flags<Event> flags) { invoke(&uv_poll_start, get<uv_poll_t>(), flags, &startCallback); }
void start(Event event) { start(Flags<Event>{event}); }
void stop() { invoke(&uv_poll_stop, get<uv_poll_t>()); }
void start(Flags<Event> flags) {
invoke(&uv_poll_start, get<uv_poll_t>(), flags, &startCallback);
}
void start(Event event) {
start(Flags<Event>{event});
}
void stop() {
invoke(&uv_poll_stop, get<uv_poll_t>());
}
};

View File

@ -29,10 +29,17 @@ public:
return std::shared_ptr<PrepareHandle>{new PrepareHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_prepare_t>(&uv_prepare_init); }
bool init() {
return initialize<uv_prepare_t>(&uv_prepare_init);
}
void start() { invoke(&uv_prepare_start, get<uv_prepare_t>(), &startCallback); }
void stop() { invoke(&uv_prepare_stop, get<uv_prepare_t>()); }
void start() {
invoke(&uv_prepare_start, get<uv_prepare_t>(), &startCallback);
}
void stop() {
invoke(&uv_prepare_stop, get<uv_prepare_t>());
}
};

145
src/uvw/process.hpp Normal file
View File

@ -0,0 +1,145 @@
#pragma once
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "stream.hpp"
#include "util.hpp"
namespace uvw {
namespace details {
enum class UVProcessFlags: std::underlying_type_t<uv_process_flags> {
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<uv_stdio_flags> {
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<ExitEvent> { };
class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
static void exitCallback(uv_process_t *handle, int64_t exitStatus, int termSignal) {
ProcessHandle &process = *(static_cast<ProcessHandle*>(handle->data));
process.publish(ExitEvent{});
}
using Handle::Handle;
public:
using Process = details::UVProcessFlags;
using StdIO = details::UVStdIOFlags;
template<typename... Args>
static std::shared_ptr<ProcessHandle> create(Args&&... args) {
return std::shared_ptr<ProcessHandle>{new ProcessHandle{std::forward<Args>(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<uv_process_t>(), &po);
}
void kill(int signum) {
invoke(&uv_process_kill, get<uv_process_t>(), signum);
}
static bool kill(int pid, int signum) noexcept {
return (0 == uv_kill(pid, signum));
}
int pid() noexcept {
return get<uv_process_t>()->pid;
}
ProcessHandle& cwd(std::string &path) noexcept {
poCwd = path;
return *this;
}
ProcessHandle& flags(Flags<Process> flags) noexcept {
poFlags = flags;
return *this;
}
template<typename T, typename U>
ProcessHandle& stdio(Flags<StdIO> flags, StreamHandle<T, U> &stream) {
uv_stdio_container_t container;
container.flags = flags;
container.data.stream = stream.get<uv_stream_t>();
poStdio.push_back(std::move(container));
return *this;
}
template<typename T>
ProcessHandle& stdio(Flags<StdIO> 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<Process> poFlags;
std::vector<uv_stdio_container_t> poStdio;
Uid poUid;
Gid poGid;
};
}

View File

@ -27,13 +27,19 @@ protected:
this->template get<U>()->data = static_cast<T*>(this);
}
auto parent() const noexcept { return pLoop->loop.get(); }
auto parent() const noexcept {
return pLoop->loop.get();
}
template<typename R>
auto get() noexcept { return reinterpret_cast<R*>(&resource); }
auto get() noexcept {
return reinterpret_cast<R*>(&resource);
}
template<typename R>
auto get() const noexcept { return reinterpret_cast<const R*>(&resource); }
auto get() const noexcept {
return reinterpret_cast<const R*>(&resource);
}
public:
Resource(const Resource &) = delete;

View File

@ -9,9 +9,17 @@ namespace uvw {
template<typename T>
struct Self: std::enable_shared_from_this<T> {
void leak() noexcept { ptr = this->shared_from_this(); }
void reset() noexcept { ptr.reset(); }
bool self() const noexcept { return static_cast<bool>(ptr); }
void leak() noexcept {
ptr = this->shared_from_this();
}
void reset() noexcept {
ptr.reset();
}
bool self() const noexcept {
return static_cast<bool>(ptr);
}
private:
std::shared_ptr<void> ptr{nullptr};

View File

@ -36,12 +36,21 @@ public:
return std::shared_ptr<SignalHandle>{new SignalHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_signal_t>(&uv_signal_init); }
bool init() {
return initialize<uv_signal_t>(&uv_signal_init);
}
void start(int signum) { invoke(&uv_signal_start, get<uv_signal_t>(), &startCallback, signum); }
void stop() { invoke(&uv_signal_stop, get<uv_signal_t>()); }
void start(int signum) {
invoke(&uv_signal_start, get<uv_signal_t>(), &startCallback, signum);
}
int signal() const noexcept { return get<uv_signal_t>()->signum; }
void stop() {
invoke(&uv_signal_stop, get<uv_signal_t>());
}
int signal() const noexcept {
return get<uv_signal_t>()->signum;
}
};

View File

@ -41,7 +41,9 @@ public:
return std::shared_ptr<TcpHandle>{new TcpHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_tcp_t>(&uv_tcp_init); }
bool init() {
return initialize<uv_tcp_t>(&uv_tcp_init);
}
template<typename T, typename... Args>
bool init(T&& t, Args&&... args) {
@ -102,7 +104,9 @@ public:
}
template<typename I = IPv4>
void connect(Addr addr) { connect<I>(addr.ip, addr.port); }
void connect(Addr addr) {
connect<I>(addr.ip, addr.port);
}
};

View File

@ -32,14 +32,29 @@ public:
return std::shared_ptr<TimerHandle>{new TimerHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_timer_t>(&uv_timer_init); }
bool init() {
return initialize<uv_timer_t>(&uv_timer_init);
}
void start(Time timeout, Time repeat) { invoke(&uv_timer_start, get<uv_timer_t>(), &startCallback, timeout.count(), repeat.count()); }
void stop() { invoke(&uv_timer_stop, get<uv_timer_t>()); }
void again() { invoke(&uv_timer_again, get<uv_timer_t>()); }
void start(Time timeout, Time repeat) {
invoke(&uv_timer_start, get<uv_timer_t>(), &startCallback, timeout.count(), repeat.count());
}
void repeat(Time repeat) { uv_timer_set_repeat(get<uv_timer_t>(), repeat.count()); }
Time repeat() { return Time{uv_timer_get_repeat(get<uv_timer_t>())}; }
void stop() {
invoke(&uv_timer_stop, get<uv_timer_t>());
}
void again() {
invoke(&uv_timer_again, get<uv_timer_t>());
}
void repeat(Time repeat) {
uv_timer_set_repeat(get<uv_timer_t>(), repeat.count());
}
Time repeat() {
return Time{uv_timer_get_repeat(get<uv_timer_t>())};
}
};

View File

@ -16,6 +16,13 @@ namespace uvw {
namespace details {
struct ResetModeMemo {
~ResetModeMemo() {
uv_tty_reset_mode();
}
};
enum class UVTTYModeT: std::underlying_type_t<uv_tty_mode_t> {
NORMAL = UV_TTY_MODE_NORMAL,
RAW = UV_TTY_MODE_RAW,
@ -29,8 +36,12 @@ enum class UVTTYModeT: std::underlying_type_t<uv_tty_mode_t> {
class TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> {
explicit TTYHandle(std::shared_ptr<Loop> ref,
FileHandle desc,
bool readable)
: StreamHandle{std::move(ref)}, fd{desc}, rw{readable}
bool readable,
std::shared_ptr<details::ResetModeMemo> rmm)
: StreamHandle{std::move(ref)},
memo{std::move(rmm)},
fd{desc},
rw{readable}
{ }
public:
@ -38,10 +49,15 @@ public:
template<typename... Args>
static std::shared_ptr<TTYHandle> create(Args&&... args) {
return std::shared_ptr<TTYHandle>{new TTYHandle{std::forward<Args>(args)...}};
static std::weak_ptr<details::ResetModeMemo> rmm;
auto ptr = rmm.lock();
if(!ptr) { rmm = ptr = std::make_shared<details::ResetModeMemo>(); }
return std::shared_ptr<TTYHandle>{new TTYHandle{std::forward<Args>(args)..., ptr}};
}
bool init() { return initialize<uv_tty_t>(&uv_tty_init, fd, rw); }
bool init() {
return initialize<uv_tty_t>(&uv_tty_init, fd, rw);
}
void mode(Mode m) {
// uv_tty_set_mode is inline, it cannot be used with invoke directly
@ -50,7 +66,9 @@ public:
}, get<uv_tty_t>(), static_cast<std::underlying_type_t<Mode>>(m));
}
void reset() { invoke(&uv_tty_reset_mode); }
void reset() noexcept {
invoke(&uv_tty_reset_mode);
}
WinSize getWinSize() {
std::pair<int, int> size{0, 0};
@ -70,6 +88,7 @@ public:
}
private:
std::shared_ptr<details::ResetModeMemo> memo;
FileHandle::Type fd;
int rw;
};

View File

@ -106,7 +106,9 @@ public:
return std::shared_ptr<UdpHandle>{new UdpHandle{std::forward<Args>(args)...}};
}
bool init() { return initialize<uv_udp_t>(&uv_udp_init); }
bool init() {
return initialize<uv_udp_t>(&uv_udp_init);
}
template<typename T, typename... Args>
bool init(T&& t, Args&&... args) {
@ -152,8 +154,13 @@ public:
invoke(&uv_udp_set_multicast_interface, get<uv_udp_t>(), interface.data());
}
void broadcast(bool enable = false) { invoke(&uv_udp_set_broadcast, get<uv_udp_t>(), enable); }
void ttl(int val) { invoke(&uv_udp_set_ttl, get<uv_udp_t>(), val > 255 ? 255 : val); }
void broadcast(bool enable = false) {
invoke(&uv_udp_set_broadcast, get<uv_udp_t>(), enable);
}
void ttl(int val) {
invoke(&uv_udp_set_ttl, get<uv_udp_t>(), val > 255 ? 255 : val);
}
template<typename I = IPv4>
void send(std::string ip, unsigned int port, std::unique_ptr<char[]> data, ssize_t len) {
@ -193,7 +200,9 @@ public:
invoke(&uv_udp_recv_start, get<uv_udp_t>(), &allocCallback, &recvCallback<I>);
}
void stop() { invoke(&uv_udp_recv_stop, get<uv_udp_t>()); }
void stop() {
invoke(&uv_udp_recv_stop, get<uv_udp_t>());
}
};

View File

@ -30,10 +30,20 @@ public:
~Flags() noexcept { static_assert(std::is_enum<E>::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{}); }

View File

@ -17,24 +17,26 @@ struct WorkEvent: Event<WorkEvent> { };
class WorkReq final: public Request<WorkReq, uv_work_t> {
using InternalTask = std::function<void(void)>;
static void workCallback(uv_work_t *req) {
static_cast<WorkReq*>(req->data)->task();
}
using Request::Request;
explicit WorkReq(std::shared_ptr<Loop> ref, InternalTask t)
: Request{std::move(ref)}, task{t}
{ }
public:
using Task = std::function<void(void)>;
using Task = InternalTask;
template<typename... Args>
static std::shared_ptr<WorkReq> create(Args&&... args) {
return std::shared_ptr<WorkReq>{new WorkReq{std::forward<Args>(args)...}};
}
void queue(Task t) {
if(0 == invoke(&uv_queue_work, parent(), get<uv_work_t>(), &workCallback, &defaultCallback<uv_work_t, WorkEvent>)) {
task = std::move(t);
}
void queue() {
invoke(&uv_queue_work, parent(), get<uv_work_t>(), &workCallback, &defaultCallback<uv_work_t, WorkEvent>);
}
private:

View File

@ -15,7 +15,7 @@ TEST(Loop, Basics) {
auto loop = uvw::Loop::create();
auto handle = loop->resource<uvw::PrepareHandle>();
auto req = loop->resource<uvw::WorkReq>();
auto req = loop->resource<uvw::WorkReq>([](){});
auto err = [](uvw::ErrorEvent, auto &) { ASSERT_TRUE(false); };