review (thanks to Tushar for the suggestion)

This commit is contained in:
Michele Caini 2016-11-24 17:02:23 +01:00
parent 68bf6c8449
commit af5dc89dec
23 changed files with 163 additions and 316 deletions

View File

@ -25,6 +25,8 @@ struct AsyncEvent: Event<AsyncEvent> { };
*
* Async handles allow the user to _wakeup_ the event loop and get an event
* emitted from another thread.
*
* To create an `AsyncHandle` through a `Loop`, no arguments are required.
*/
class AsyncHandle final: public Handle<AsyncHandle, uv_async_t> {
static void sendCallback(uv_async_t *handle) {
@ -32,17 +34,8 @@ class AsyncHandle final: public Handle<AsyncHandle, uv_async_t> {
async.publish(AsyncEvent{});
}
using Handle::Handle;
public:
/**
* @brief Creates a new async handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<AsyncHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<AsyncHandle>{new AsyncHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Initializes the handle.

View File

@ -16,6 +16,8 @@ namespace uvw {
* @brief CheckEvent event.
*
* It will be emitted by CheckHandle according with its functionalities.
*
* To create a `CheckHandle` through a `Loop`, no arguments are required.
*/
struct CheckEvent: Event<CheckEvent> { };
@ -32,17 +34,8 @@ class CheckHandle final: public Handle<CheckHandle, uv_check_t> {
check.publish(CheckEvent{});
}
using Handle::Handle;
public:
/**
* @brief Creates a new check handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<CheckHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<CheckHandle>{new CheckHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Initializes the handle.

View File

@ -69,6 +69,8 @@ struct NameInfoEvent: Event<NameInfoEvent> {
*
* Wrapper for [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).<br/>
* It offers either asynchronous and synchronous access methods.
*
* To create a `GetAddrInfoReq` through a `Loop`, no arguments are required.
*/
class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
static void getAddrInfoCallback(uv_getaddrinfo_t *req, int status, addrinfo *res) {
@ -84,8 +86,6 @@ class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
}
}
using Request::Request;
void getNodeAddrInfo(const char *node, const char *service, addrinfo *hints = nullptr) {
invoke(&uv_getaddrinfo, parent(), get(), &getAddrInfoCallback, node, service, hints);
}
@ -100,14 +100,7 @@ class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
public:
using Deleter = void(*)(addrinfo *);
/**
* @brief Creates a new `getaddrinfo` wrapper request.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<GetAddrInfoReq> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<GetAddrInfoReq>{new GetAddrInfoReq{std::move(loop)}};
}
using Request::Request;
/**
* @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
@ -196,6 +189,8 @@ public:
*
* Wrapper for [getnameinfo](http://linux.die.net/man/3/getnameinfo).<br/>
* It offers either asynchronous and synchronous access methods.
*
* To create a `GetNameInfoReq` through a `Loop`, no arguments are required.
*/
class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
static void getNameInfoCallback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service) {
@ -204,17 +199,8 @@ class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
else { ptr->publish(NameInfoEvent{hostname, service}); }
}
using Request::Request;
public:
/**
* @brief Creates a new `getnameinfo` wrapper request.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<GetNameInfoReq> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<GetNameInfoReq>{new GetNameInfoReq{std::move(loop)}};
}
using Request::Request;
/**
* @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).

View File

@ -194,7 +194,7 @@ public:
/**
* @brief Disconnects all the listeners.
*/
void clearAll() noexcept {
void clear() noexcept {
std::for_each(handlers.begin(), handlers.end(),
[](auto &&handler){ if(handler) { handler->clear(); } });
}

View File

@ -301,8 +301,6 @@ protected:
else { ptr->publish(FsEvent<e>{req->path, req->statbuf}); }
}
using Request<T, uv_fs_t>::Request;
template<typename... Args>
void cleanupAndInvoke(Args&&... args) {
uv_fs_req_cleanup(this->get());
@ -320,6 +318,8 @@ public:
using Type = details::UVFsType;
using EntryType = details::UVDirentTypeT;
using Entry = std::pair<EntryType, std::string>;
using Request<T, uv_fs_t>::Request;
};
@ -329,6 +329,8 @@ public:
* Cross-platform sync and async filesystem operations.<br/>
* All file operations are run on the threadpool.
*
* To create a `FileReq` through a `Loop`, no arguments are required.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/fs.html)
* for further details.
@ -364,17 +366,8 @@ class FileReq final: public FsRequest<FileReq> {
else { ptr->publish(FsEvent<Type::READ>{req->path, std::move(ptr->data), req->result}); }
}
using FsRequest::FsRequest;
public:
/**
* @brief Creates a new file request.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created request.
*/
static std::shared_ptr<FileReq> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<FileReq>{new FileReq{std::move(loop)}};
}
using FsRequest::FsRequest;
~FileReq() noexcept {
uv_fs_req_cleanup(get());
@ -722,6 +715,8 @@ private:
* Cross-platform sync and async filesystem operations.<br/>
* All file operations are run on the threadpool.
*
* To create a `FsReq` through a `Loop`, no arguments are required.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/fs.html)
* for further details.
@ -733,17 +728,8 @@ class FsReq final: public FsRequest<FsReq> {
else { ptr->publish(FsEvent<Type::READLINK>{req->path, static_cast<char *>(req->ptr), req->result}); }
}
using FsRequest::FsRequest;
public:
/**
* @brief Creates a new file request.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created request.
*/
static std::shared_ptr<FsReq> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<FsReq>{new FsReq{std::move(loop)}};
}
using FsRequest::FsRequest;
~FsReq() noexcept {
uv_fs_req_cleanup(get());

View File

@ -70,6 +70,8 @@ struct FsEventEvent: Event<FsEventEvent> {
* example, if the file was renamed or there was a generic change in it. The
* best backend for the job on each platform is chosen by the handle.
*
* To create a `FsEventHandle` through a `Loop`, no arguments are required.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/fs_event.html)
* for further details.
@ -81,20 +83,11 @@ class FsEventHandle final: public Handle<FsEventHandle, uv_fs_event_t> {
else { fsEvent.publish(FsEventEvent{filename, static_cast<std::underlying_type_t<Event>>(events)}); }
}
using Handle::Handle;
public:
using Watch = details::UVFsEvent;
using Event = details::UVFsEventFlags;
/**
* @brief Creates a new fs event handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<FsEventHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<FsEventHandle>{new FsEventHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Initializes the handle.

View File

@ -35,6 +35,8 @@ struct FsPollEvent: Event<FsPollEvent> {
* It allows the user to monitor a given path for changes. Unlike FsEventHandle
* handles, FsPollHandle handles use stat to detect when a file has changed so
* they can work on file systems where FsEventHandle handles cant.
*
* To create a `FsPollHandle` through a `Loop`, no arguments are required.
*/
class FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
static void startCallback(uv_fs_poll_t *handle, int status, const uv_stat_t *prev, const uv_stat_t *curr) {
@ -43,17 +45,8 @@ class FsPollHandle final: public Handle<FsPollHandle, uv_fs_poll_t> {
else { fsPoll.publish(FsPollEvent{ *prev, *curr }); }
}
using Handle::Handle;
public:
/**
* @brief Creates a new fs poll handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<FsPollHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<FsPollHandle>{new FsPollHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Initializes the handle.

View File

@ -37,8 +37,6 @@ class Handle: public BaseHandle, public Resource<T, U>
}
protected:
using Resource<T, U>::Resource;
static void allocCallback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
*buf = uv_buf_init(new char[suggested], suggested);
}
@ -66,6 +64,8 @@ protected:
}
public:
using Resource<T, U>::Resource;
/**
* @brief Checks if the handle is active.
*

View File

@ -32,6 +32,8 @@ struct IdleEvent: Event<IdleEvent> { };
*
* **Note**: despite the name, idle handles will emit events on every loop
* iteration, not when the loop is actually _idle_.
*
* To create an `IdleHandle` through a `Loop`, no arguments are required.
*/
class IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
static void startCallback(uv_idle_t *handle) {
@ -39,17 +41,8 @@ class IdleHandle final: public Handle<IdleHandle, uv_idle_t> {
idle.publish(IdleEvent{});
}
using Handle::Handle;
public:
/**
* @brief Creates a new check handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<IdleHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<IdleHandle>{new IdleHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Initializes the handle.

View File

@ -21,23 +21,17 @@ namespace uvw {
*
* Pipe handles provide an abstraction over local domain sockets on Unix and
* named pipes on Windows.
*
* To create a `PipeHandle` through a `Loop`, arguments follow:
*
* * An optional boolean value that indicates if this pipe will be used for
* handle passing between processes.
*/
class PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
explicit PipeHandle(std::shared_ptr<Loop> ref, bool pass = false)
: StreamHandle{std::move(ref)}, ipc{pass}
{ }
public:
/**
* @brief Creates a new poll handle.
* @param loop A pointer to the loop from which the handle generated.
* @param pass An optional boolean value (_ipc_) that indicates if this pipe
* will be used for handle passing between processes.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<PipeHandle> create(std::shared_ptr<Loop> loop, bool pass) {
return std::shared_ptr<PipeHandle>{new PipeHandle{std::move(loop), pass}};
}
explicit PipeHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, bool pass = false)
: StreamHandle{std::move(ca), std::move(ref)}, ipc{pass}
{ }
/**
* @brief Initializes the handle.

View File

@ -55,6 +55,12 @@ struct PollEvent: Event<PollEvent> {
* Poll handles are used to watch file descriptors for readability, writability
* and disconnection.
*
* To create a `PollHandle` through a `Loop`, arguments follow:
*
* * A descriptor that can be:
* * either an `int` file descriptor
* * or a `OSSocketHandle` socket descriptor
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/poll.html)
* for further details.
@ -66,36 +72,16 @@ class PollHandle final: public Handle<PollHandle, uv_poll_t> {
else { poll.publish(PollEvent{static_cast<std::underlying_type_t<Event>>(events)}); }
}
explicit PollHandle(std::shared_ptr<Loop> ref, int desc)
: Handle{std::move(ref)}, tag{FD}, fd{desc}
{ }
explicit PollHandle(std::shared_ptr<Loop> ref, OSSocketHandle sock)
: Handle{std::move(ref)}, tag{SOCKET}, socket{sock}
{ }
public:
using Event = details::UVPollEvent;
/**
* @brief Creates a new poll handle.
* @param args
*
* * A pointer to the loop from which the handle generated.
* * A descriptor that can be:
* * either an `int` file descriptor
* * or a `OSSocketHandle` socket descriptor
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/poll.html)
* for further details.
*
* @return A pointer to the newly created handle.
*/
template<typename... Args>
static std::shared_ptr<PollHandle> create(Args&&... args) {
return std::shared_ptr<PollHandle>{new PollHandle{std::forward<Args>(args)...}};
}
explicit PollHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, int desc)
: Handle{std::move(ca), std::move(ref)}, tag{FD}, fd{desc}
{ }
explicit PollHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, OSSocketHandle sock)
: Handle{std::move(ca), std::move(ref)}, tag{SOCKET}, socket{sock}
{ }
/**
* @brief Initializes the handle.

View File

@ -16,6 +16,8 @@ namespace uvw {
* @brief PrepareEvent event.
*
* It will be emitted by PrepareHandle according with its functionalities.
*
* To create a `PrepareHandle` through a `Loop`, no arguments are required.
*/
struct PrepareEvent: Event<PrepareEvent> { };
@ -32,17 +34,8 @@ class PrepareHandle final: public Handle<PrepareHandle, uv_prepare_t> {
prepare.publish(PrepareEvent{});
}
using Handle::Handle;
public:
/**
* @brief Creates a new check handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<PrepareHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<PrepareHandle>{new PrepareHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Initializes the handle.

View File

@ -60,20 +60,11 @@ class ProcessHandle final: public Handle<ProcessHandle, uv_process_t> {
process.publish(ExitEvent{});
}
using Handle::Handle;
public:
using Process = details::UVProcessFlags;
using StdIO = details::UVStdIOFlags;
/**
* @brief Creates a new check handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<ProcessHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<ProcessHandle>{new ProcessHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Disables inheritance for file descriptors/handles.

View File

@ -14,8 +14,6 @@ namespace uvw {
template<typename T, typename U>
class Request: public Resource<T, U> {
protected:
using Resource<T, U>::Resource;
static auto reserve(U *req) {
auto ptr = static_cast<T*>(req->data)->shared_from_this();
ptr->reset();
@ -46,6 +44,8 @@ protected:
}
public:
using Resource<T, U>::Resource;
/**
* @brief Cancels a pending request.
*

View File

@ -23,14 +23,7 @@ class Resource: public Emitter<T>, public std::enable_shared_from_this<T> {
friend class Resource;
protected:
explicit Resource(std::shared_ptr<Loop> ref)
: Emitter<T>{},
std::enable_shared_from_this<T>{},
pLoop{std::move(ref)},
resource{}
{
resource.data = static_cast<T*>(this);
}
struct ConstructorAccess { explicit ConstructorAccess(int) {} };
auto parent() const noexcept {
return pLoop->loop.get();
@ -69,6 +62,15 @@ protected:
}
public:
explicit Resource(ConstructorAccess, std::shared_ptr<Loop> ref)
: Emitter<T>{},
std::enable_shared_from_this<T>{},
pLoop{std::move(ref)},
resource{}
{
resource.data = static_cast<T*>(this);
}
Resource(const Resource &) = delete;
Resource(Resource &&) = delete;
@ -79,6 +81,17 @@ public:
Resource& operator=(const Resource &) = delete;
Resource& operator=(Resource &&) = delete;
/**
* @brief Creates a new resource of the given type.
* @param loop A pointer to the loop from which the handle generated.
* @param args Arguments to be forwarded to the actual constructor (if any).
* @return A pointer to the newly created resource.
*/
template<typename... Args>
static std::shared_ptr<T> create(std::shared_ptr<Loop> loop, Args&&... args) {
return std::make_shared<T>(ConstructorAccess{0}, std::move(loop), std::forward<Args>(args)...);
}
/**
* @brief Gets the loop from which the resource was originated.
* @return A reference to a loop instance.

View File

@ -31,6 +31,8 @@ struct SignalEvent: Event<SignalEvent> {
* bases.<br/>
* Reception of some signals is emulated on Windows.
*
* To create a `SignalHandle` through a `Loop`, no arguments are required.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/signal.html)
* for further details.
@ -41,17 +43,8 @@ class SignalHandle final: public Handle<SignalHandle, uv_signal_t> {
signal.publish(SignalEvent{signum});
}
using Handle::Handle;
public:
/**
* @brief Creates a new signal handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<SignalHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<SignalHandle>{new SignalHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Initializes the handle.

View File

@ -74,14 +74,9 @@ struct DataEvent: Event<DataEvent> {
namespace details {
class ConnectReq final: public Request<ConnectReq, uv_connect_t> {
struct ConnectReq final: public Request<ConnectReq, uv_connect_t> {
using Request::Request;
public:
static std::shared_ptr<ConnectReq> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<ConnectReq>{new ConnectReq{std::move(loop)}};
}
template<typename F, typename... Args>
void connect(F &&f, Args... args) {
invoke(std::forward<F>(f), get(), std::forward<Args>(args)..., &defaultCallback<ConnectEvent>);
@ -89,14 +84,9 @@ public:
};
class ShutdownReq final: public Request<ShutdownReq, uv_shutdown_t> {
struct ShutdownReq final: public Request<ShutdownReq, uv_shutdown_t> {
using Request::Request;
public:
static std::shared_ptr<ShutdownReq> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<ShutdownReq>{new ShutdownReq{std::move(loop)}};
}
void shutdown(uv_stream_t *handle) {
invoke(&uv_shutdown, get(), handle, &defaultCallback<ShutdownEvent>);
}
@ -112,21 +102,16 @@ class WriteReq final: public Request<WriteReq, uv_write_t> {
delete[] bufs;
}
public:
template<std::size_t N>
WriteReq(std::shared_ptr<Loop> loop, const uv_buf_t (&arr)[N])
: Request<WriteReq, uv_write_t>{std::move(loop)},
WriteReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, const uv_buf_t (&arr)[N])
: Request<WriteReq, uv_write_t>{std::move(ca), std::move(loop)},
bufs{new uv_buf_t[N], &deleter<N>},
nbufs{N}
{
std::copy_n(std::begin(arr), N, bufs.get());
}
public:
template<typename... Args>
static std::shared_ptr<WriteReq> create(Args&&... args) {
return std::shared_ptr<WriteReq>{new WriteReq{std::forward<Args>(args)...}};
}
void write(uv_stream_t *handle) {
invoke(&uv_write, get(), handle, bufs.get(), nbufs, &defaultCallback<WriteEvent>);
}
@ -178,16 +163,15 @@ class StreamHandle: public Handle<T, U> {
else { ref.publish(ListenEvent{}); }
}
protected:
public:
#ifdef _WIN32
StreamHandle(std::shared_ptr<Loop> ref)
: Handle{std::move(ref)}
StreamHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref)
: Handle{std::move(ca), std::move(ref)}
{ }
#else
using Handle<T, U>::Handle;
#endif
public:
/**
* @brief Shutdowns the outgoing (write) side of a duplex stream.
*

View File

@ -33,39 +33,30 @@ enum class UVTcpFlags: std::underlying_type_t<uv_tcp_flags> {
* TCP handles are used to represent both TCP streams and servers.<br/>
* By default, _IPv4_ is used as a template parameter. The handle already
* supports _IPv6_ out-of-the-box by using `uvw::IPv6`.
*
* To create a `TcpHandle` through a `Loop`, arguments follow:
*
* * An optional integer value that indicates the flags used to initialize
* the socket.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_init_ex)
* for further details.
*/
class TcpHandle final: public StreamHandle<TcpHandle, uv_tcp_t> {
explicit TcpHandle(std::shared_ptr<Loop> ref)
: StreamHandle{std::move(ref)}, tag{DEFAULT}, flags{}
{ }
explicit TcpHandle(std::shared_ptr<Loop> ref, unsigned int f)
: StreamHandle{std::move(ref)}, tag{FLAGS}, flags{f}
{ }
public:
using Time = std::chrono::seconds;
using Bind = details::UVTcpFlags;
using IPv4 = uvw::IPv4;
using IPv6 = uvw::IPv6;
/**
* @brief Creates a new tcp handle.
* @param args
*
* * A pointer to the loop from which the handle generated.
* * An optional integer value (_flags_) that indicates optional flags used
* to initialize the socket.<br/>
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_init_ex)
* for further details.
*
* @return A pointer to the newly created handle.
*/
template<typename... Args>
static std::shared_ptr<TcpHandle> create(Args&&... args) {
return std::shared_ptr<TcpHandle>{new TcpHandle{std::forward<Args>(args)...}};
}
explicit TcpHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref)
: StreamHandle{std::move(ca), std::move(ref)}, tag{DEFAULT}, flags{}
{ }
explicit TcpHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int f)
: StreamHandle{std::move(ca), std::move(ref)}, tag{FLAGS}, flags{f}
{ }
/**
* @brief Initializes the handle. No socket is created as of yet.

View File

@ -25,6 +25,8 @@ struct TimerEvent: Event<TimerEvent> { };
* @brief The TimerHandle handle.
*
* Timer handles are used to schedule events to be emitted in the future.
*
* To create a `TimerHandle` through a `Loop`, no arguments are required.
*/
class TimerHandle final: public Handle<TimerHandle, uv_timer_t> {
static void startCallback(uv_timer_t *handle) {
@ -32,19 +34,10 @@ class TimerHandle final: public Handle<TimerHandle, uv_timer_t> {
timer.publish(TimerEvent{});
}
using Handle::Handle;
public:
using Time = std::chrono::milliseconds;
/**
* @brief Creates a new check handle.
* @param loop A pointer to the loop from which the handle generated.
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<TimerHandle> create(std::shared_ptr<Loop> loop) {
return std::shared_ptr<TimerHandle>{new TimerHandle{std::move(loop)}};
}
using Handle::Handle;
/**
* @brief Initializes the handle.

View File

@ -37,44 +37,37 @@ enum class UVTTYModeT: std::underlying_type_t<uv_tty_mode_t> {
* @brief The TTYHandle handle.
*
* TTY handles represent a stream for the console.
*
* To create a `TTYHandle` through a `Loop`, arguments follow:
*
* * A valid FileHandle. Usually the file descriptor will be:
* * `0` = `stdin`
* * `1` = `stdout`
* * `2` = `stderr`
* * A boolean value that specifies the plan on calling `read()` with this
* stream. Remember that `stdin` is readable, `stdout` is not.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_init)
* for further details.
*/
class TTYHandle final: public StreamHandle<TTYHandle, uv_tty_t> {
explicit TTYHandle(std::shared_ptr<Loop> ref,
FileHandle desc,
bool readable,
std::shared_ptr<details::ResetModeMemo> rmm)
: StreamHandle{std::move(ref)},
memo{std::move(rmm)},
fd{desc},
rw{readable}
{ }
static auto resetModeMemo() {
static std::weak_ptr<details::ResetModeMemo> weak;
auto shared = weak.lock();
if(!shared) { weak = shared = std::make_shared<details::ResetModeMemo>(); }
return shared;
}
public:
using Mode = details::UVTTYModeT;
/**
* @brief Creates a new tty handle.
* @param loop A pointer to the loop from which the handle generated.
* @param desc A valid FileHandle. Usually the file descriptor will be:
* * `0` = `stdin`
* * `1` = `stdout`
* * `2` = `stderr`
* @param readable A boolean value (_readable_) that specifies the plan on
* calling `read()` with this stream. Remember that `stdin` is readable,
* `stdout` is not.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_init)
* for further details.
*
* @return A pointer to the newly created handle.
*/
static std::shared_ptr<TTYHandle> create(std::shared_ptr<Loop> loop, FileHandle desc, bool readable) {
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::move(loop), std::move(desc), readable, ptr}};
}
explicit TTYHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, FileHandle desc, bool readable)
: StreamHandle{std::move(ca), std::move(ref)},
memo{resetModeMemo()},
fd{desc},
rw{readable}
{ }
/**
* @brief Initializes the handle.

View File

@ -67,21 +67,16 @@ class SendReq final: public Request<SendReq, uv_udp_send_t> {
delete[] bufs;
}
public:
template<std::size_t N>
SendReq(std::shared_ptr<Loop> loop, const uv_buf_t (&arr)[N])
: Request<SendReq, uv_udp_send_t>{std::move(loop)},
SendReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, const uv_buf_t (&arr)[N])
: Request<SendReq, uv_udp_send_t>{std::move(ca), std::move(loop)},
bufs{new uv_buf_t[N], &deleter<N>},
nbufs{N}
{
std::copy_n(std::begin(arr), N, bufs.get());
}
public:
template<typename... Args>
static std::shared_ptr<SendReq> create(Args&&... args) {
return std::shared_ptr<SendReq>{new SendReq{std::forward<Args>(args)...}};
}
void send(uv_udp_t *handle, const struct sockaddr* addr) {
invoke(&uv_udp_send, get(), handle, bufs.get(), nbufs, addr, &defaultCallback<SendEvent>);
}
@ -101,6 +96,15 @@ private:
* UDP handles encapsulate UDP communication for both clients and servers.<br/>
* By default, _IPv4_ is used as a template parameter. The handle already
* supports _IPv6_ out-of-the-box by using `uvw::IPv6`.
*
* To create an `UDPHandle` through a `Loop`, arguments follow:
*
* * An optional integer value that indicates optional flags used to initialize
* the socket.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_init_ex)
* for further details.
*/
class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
template<typename I>
@ -125,37 +129,19 @@ class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
}
}
explicit UDPHandle(std::shared_ptr<Loop> ref)
: Handle{std::move(ref)}, tag{DEFAULT}, flags{}
{ }
explicit UDPHandle(std::shared_ptr<Loop> ref, unsigned int f)
: Handle{std::move(ref)}, tag{FLAGS}, flags{f}
{ }
public:
using Membership = details::UVMembership;
using Bind = details::UVUdpFlags;
using IPv4 = uvw::IPv4;
using IPv6 = uvw::IPv6;
/**
* @brief Creates a new udp handle.
* @param args
*
* * A pointer to the loop from which the handle generated.
* * An optional integer value (_flags_) that indicates optional flags used
* to initialize the socket.<br/>
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_init_ex)
* for further details.
*
* @return A pointer to the newly created handle.
*/
template<typename... Args>
static std::shared_ptr<UDPHandle> create(Args&&... args) {
return std::shared_ptr<UDPHandle>{new UDPHandle{std::forward<Args>(args)...}};
}
explicit UDPHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref)
: Handle{std::move(ca), std::move(ref)}, tag{DEFAULT}, flags{}
{ }
explicit UDPHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int f)
: Handle{std::move(ca), std::move(ref)}, tag{FLAGS}, flags{f}
{ }
/**
* @brief Initializes the handle. The actual socket is created lazily.

View File

@ -27,6 +27,10 @@ struct WorkEvent: Event<WorkEvent> { };
* It runs user code using a thread from the threadpool and gets notified in the
* loop thread by means of an event.
*
* To create a `WorkReq` through a `Loop`, arguments follow:
*
* * A valid instance of a `Task`, that is of type `std::function<void(void)>`.
*
* See the official
* [documentation](http://docs.libuv.org/en/v1.x/threadpool.html)
* for further details.
@ -38,23 +42,12 @@ class WorkReq final: public Request<WorkReq, uv_work_t> {
static_cast<WorkReq*>(req->data)->task();
}
explicit WorkReq(std::shared_ptr<Loop> ref, InternalTask t)
: Request{std::move(ref)}, task{t}
{ }
public:
using Task = InternalTask;
/**
* @brief Creates a new work request.
* @param loop A pointer to the loop from which the handle generated.
* @param task A valid instance of a `Task`, that is of type
* `std::function<void(void)>`.
* @return A pointer to the newly created request.
*/
static std::shared_ptr<WorkReq> create(std::shared_ptr<Loop> loop, Task task) {
return std::shared_ptr<WorkReq>{new WorkReq{std::move(loop), std::move(task)}};
}
explicit WorkReq(ConstructorAccess ca, std::shared_ptr<Loop> ref, InternalTask t)
: Request{std::move(ca), std::move(ref)}, task{t}
{ }
/**
* @brief Runs the given task in a separate thread.

View File

@ -10,7 +10,7 @@ struct TestEmitter: uvw::Emitter<TestEmitter> {
};
TEST(Emitter, ClearAndClearAll) {
TEST(Emitter, ClearAndClear) {
TestEmitter emitter{};
ASSERT_TRUE(emitter.empty());
@ -40,7 +40,7 @@ TEST(Emitter, ClearAndClearAll) {
ASSERT_FALSE(emitter.empty<uvw::ErrorEvent>());
ASSERT_FALSE(emitter.empty<FakeEvent>());
emitter.clearAll();
emitter.clear();
ASSERT_TRUE(emitter.empty());
ASSERT_TRUE(emitter.empty<uvw::ErrorEvent>());