This commit is contained in:
parent
a10844d4bf
commit
0b329720bf
@ -27,248 +27,248 @@ struct CloseEvent {};
|
|||||||
* Base type for all `uvw` handle types.
|
* Base type for all `uvw` handle types.
|
||||||
*/
|
*/
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
class Handle: public Resource<T, U>, public BaseHandle {
|
class Handle: public Resource<T, U> {
|
||||||
protected:
|
protected:
|
||||||
static void closeCallback(uv_handle_t *handle) {
|
static void closeCallback(uv_handle_t *handle) {
|
||||||
Handle<T, U> &ref = *(static_cast<T*>(handle->data));
|
Handle<T, U> &ref = *(static_cast<T*>(handle->data));
|
||||||
auto ptr = ref.shared_from_this();
|
auto ptr = ref.shared_from_this();
|
||||||
(void)ptr;
|
(void)ptr;
|
||||||
ref.reset();
|
ref.reset();
|
||||||
ref.publish(CloseEvent{});
|
ref.publish(CloseEvent{});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void allocCallback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
|
static void allocCallback(uv_handle_t *, std::size_t suggested, uv_buf_t *buf) {
|
||||||
auto size = static_cast<unsigned int>(suggested);
|
auto size = static_cast<unsigned int>(suggested);
|
||||||
*buf = uv_buf_init(new char[size], size);
|
*buf = uv_buf_init(new char[size], size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F, typename... Args>
|
template<typename F, typename... Args>
|
||||||
bool initialize(F &&f, Args&&... args) {
|
bool initialize(F &&f, Args&&... args) {
|
||||||
if(!this->self()) {
|
if(!this->self()) {
|
||||||
auto err = std::forward<F>(f)(this->parent(), this->get(), std::forward<Args>(args)...);
|
auto err = std::forward<F>(f)(this->parent(), this->get(), std::forward<Args>(args)...);
|
||||||
|
|
||||||
if(err) {
|
if(err) {
|
||||||
this->publish(ErrorEvent{err});
|
this->publish(ErrorEvent{err});
|
||||||
} else {
|
} else {
|
||||||
this->leak();
|
this->leak();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->self();
|
return this->self();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F, typename... Args>
|
template<typename F, typename... Args>
|
||||||
void invoke(F &&f, Args&&... args) {
|
void invoke(F &&f, Args&&... args) {
|
||||||
auto err = std::forward<F>(f)(std::forward<Args>(args)...);
|
auto err = std::forward<F>(f)(std::forward<Args>(args)...);
|
||||||
if(err) { Emitter<T>::publish(ErrorEvent{err}); }
|
if(err) { Emitter<T>::publish(ErrorEvent{err}); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Resource<T, U>::Resource;
|
using Resource<T, U>::Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the category of the handle.
|
* @brief Gets the category of the handle.
|
||||||
*
|
*
|
||||||
* A base handle offers no functionality to promote it to the actual handle
|
* A base handle offers no functionality to promote it to the actual handle
|
||||||
* type. By means of this function, an opaque value that identifies the
|
* type. By means of this function, an opaque value that identifies the
|
||||||
* category of the handle is made available to the users.
|
* category of the handle is made available to the users.
|
||||||
*
|
*
|
||||||
* @return The actual category of the handle.
|
* @return The actual category of the handle.
|
||||||
*/
|
*/
|
||||||
HandleCategory category() const noexcept override {
|
HandleCategory category() const noexcept {
|
||||||
return HandleCategory{this->template get<uv_handle_t>()->type};
|
return HandleCategory{this->template get<uv_handle_t>()->type};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the type of the handle.
|
* @brief Gets the type of the handle.
|
||||||
*
|
*
|
||||||
* A base handle offers no functionality to promote it to the actual handle
|
* A base handle offers no functionality to promote it to the actual handle
|
||||||
* type. By means of this function, the type of the underlying handle as
|
* type. By means of this function, the type of the underlying handle as
|
||||||
* specified by HandleType is made available to the users.
|
* specified by HandleType is made available to the users.
|
||||||
*
|
*
|
||||||
* @return The actual type of the handle.
|
* @return The actual type of the handle.
|
||||||
*/
|
*/
|
||||||
HandleType type() const noexcept override {
|
HandleType type() const noexcept {
|
||||||
return Utilities::guessHandle(category());
|
return Utilities::guessHandle(category());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if the handle is active.
|
* @brief Checks if the handle is active.
|
||||||
*
|
*
|
||||||
* What _active_ means depends on the type of handle:
|
* What _active_ means depends on the type of handle:
|
||||||
*
|
*
|
||||||
* * An AsyncHandle handle is always active and cannot be deactivated,
|
* * An AsyncHandle handle is always active and cannot be deactivated,
|
||||||
* except by closing it with uv_close().
|
* except by closing it with uv_close().
|
||||||
* * A PipeHandle, TCPHandle, UDPHandle, etc. handle - basically any handle
|
* * A PipeHandle, TCPHandle, UDPHandle, etc. handle - basically any handle
|
||||||
* that deals with I/O - is active when it is doing something that involves
|
* that deals with I/O - is active when it is doing something that involves
|
||||||
* I/O, like reading, writing, connecting, accepting new connections, etc.
|
* I/O, like reading, writing, connecting, accepting new connections, etc.
|
||||||
* * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
|
* * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
|
||||||
* has been started with a call to `start()`.
|
* has been started with a call to `start()`.
|
||||||
*
|
*
|
||||||
* Rule of thumb: if a handle of type `FooHandle` has a `start()` member
|
* Rule of thumb: if a handle of type `FooHandle` has a `start()` member
|
||||||
* method, then it’s active from the moment that method is called. Likewise,
|
* method, then it’s active from the moment that method is called. Likewise,
|
||||||
* `stop()` deactivates the handle again.
|
* `stop()` deactivates the handle again.
|
||||||
*
|
*
|
||||||
* @return True if the handle is active, false otherwise.
|
* @return True if the handle is active, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool active() const noexcept override {
|
bool active() const noexcept {
|
||||||
return !(uv_is_active(this->template get<uv_handle_t>()) == 0);
|
return !(uv_is_active(this->template get<uv_handle_t>()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if a handle is closing or closed.
|
* @brief Checks if a handle is closing or closed.
|
||||||
*
|
*
|
||||||
* This function should only be used between the initialization of the
|
* This function should only be used between the initialization of the
|
||||||
* handle and the arrival of the close callback.
|
* handle and the arrival of the close callback.
|
||||||
*
|
*
|
||||||
* @return True if the handle is closing or closed, false otherwise.
|
* @return True if the handle is closing or closed, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool closing() const noexcept override {
|
bool closing() const noexcept {
|
||||||
return !(uv_is_closing(this->template get<uv_handle_t>()) == 0);
|
return !(uv_is_closing(this->template get<uv_handle_t>()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Request handle to be closed.
|
* @brief Request handle to be closed.
|
||||||
*
|
*
|
||||||
* This **must** be called on each handle before memory is released.<br/>
|
* This **must** be called on each handle before memory is released.<br/>
|
||||||
* In-progress requests are cancelled and this can result in an ErrorEvent
|
* In-progress requests are cancelled and this can result in an ErrorEvent
|
||||||
* emitted.
|
* emitted.
|
||||||
*
|
*
|
||||||
* The handle will emit a CloseEvent when finished.
|
* The handle will emit a CloseEvent when finished.
|
||||||
*/
|
*/
|
||||||
void close() noexcept override {
|
void close() noexcept {
|
||||||
if(!closing()) {
|
if(!closing()) {
|
||||||
uv_close(this->template get<uv_handle_t>(), &Handle<T, U>::closeCallback);
|
uv_close(this->template get<uv_handle_t>(), &Handle<T, U>::closeCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reference the given handle.
|
* @brief Reference the given handle.
|
||||||
*
|
*
|
||||||
* References are idempotent, that is, if a handle is already referenced
|
* References are idempotent, that is, if a handle is already referenced
|
||||||
* calling this function again will have no effect.
|
* calling this function again will have no effect.
|
||||||
*/
|
*/
|
||||||
void reference() noexcept override {
|
void reference() noexcept {
|
||||||
uv_ref(this->template get<uv_handle_t>());
|
uv_ref(this->template get<uv_handle_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Unreference the given handle.
|
* @brief Unreference the given handle.
|
||||||
*
|
*
|
||||||
* References are idempotent, that is, if a handle is not referenced calling
|
* References are idempotent, that is, if a handle is not referenced calling
|
||||||
* this function again will have no effect.
|
* this function again will have no effect.
|
||||||
*/
|
*/
|
||||||
void unreference() noexcept override {
|
void unreference() noexcept {
|
||||||
uv_unref(this->template get<uv_handle_t>());
|
uv_unref(this->template get<uv_handle_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if the given handle referenced.
|
* @brief Checks if the given handle referenced.
|
||||||
* @return True if the handle referenced, false otherwise.
|
* @return True if the handle referenced, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool referenced() const noexcept override {
|
bool referenced() const noexcept {
|
||||||
return !(uv_has_ref(this->template get<uv_handle_t>()) == 0);
|
return !(uv_has_ref(this->template get<uv_handle_t>()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the size of the underlying handle type.
|
* @brief Returns the size of the underlying handle type.
|
||||||
* @return The size of the underlying handle type.
|
* @return The size of the underlying handle type.
|
||||||
*/
|
*/
|
||||||
std::size_t size() const noexcept {
|
std::size_t size() const noexcept {
|
||||||
return uv_handle_size(this->template get<uv_handle_t>()->type);
|
return uv_handle_size(this->template get<uv_handle_t>()->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the size of the send buffer used for the socket.
|
* @brief Gets the size of the send buffer used for the socket.
|
||||||
*
|
*
|
||||||
* Gets the size of the send buffer that the operating system uses for the
|
* Gets the size of the send buffer that the operating system uses for the
|
||||||
* socket.<br/>
|
* socket.<br/>
|
||||||
* This function works for TCPHandle, PipeHandle and UDPHandle handles on
|
* This function works for TCPHandle, PipeHandle and UDPHandle handles on
|
||||||
* Unix and for TCPHandle and UDPHandle handles on Windows.<br/>
|
* Unix and for TCPHandle and UDPHandle handles on Windows.<br/>
|
||||||
* Note that Linux will return double the size of the original set value.
|
* Note that Linux will return double the size of the original set value.
|
||||||
*
|
*
|
||||||
* @return The size of the send buffer, 0 in case of errors.
|
* @return The size of the send buffer, 0 in case of errors.
|
||||||
*/
|
*/
|
||||||
int sendBufferSize() {
|
int sendBufferSize() {
|
||||||
int value = 0;
|
int value = 0;
|
||||||
auto err = uv_send_buffer_size(this->template get<uv_handle_t>(), &value);
|
auto err = uv_send_buffer_size(this->template get<uv_handle_t>(), &value);
|
||||||
return err ? 0 : value;
|
return err ? 0 : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the size of the send buffer used for the socket.
|
* @brief Sets the size of the send buffer used for the socket.
|
||||||
*
|
*
|
||||||
* Sets the size of the send buffer that the operating system uses for the
|
* Sets the size of the send buffer that the operating system uses for the
|
||||||
* socket.<br/>
|
* socket.<br/>
|
||||||
* This function works for TCPHandle, PipeHandle and UDPHandle handles on
|
* This function works for TCPHandle, PipeHandle and UDPHandle handles on
|
||||||
* Unix and for TCPHandle and UDPHandle handles on Windows.<br/>
|
* Unix and for TCPHandle and UDPHandle handles on Windows.<br/>
|
||||||
* Note that Linux will set double the size.
|
* Note that Linux will set double the size.
|
||||||
*
|
*
|
||||||
* @return True in case of success, false otherwise.
|
* @return True in case of success, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool sendBufferSize(int value) {
|
bool sendBufferSize(int value) {
|
||||||
return (0 == uv_send_buffer_size(this->template get<uv_handle_t>(), &value));
|
return (0 == uv_send_buffer_size(this->template get<uv_handle_t>(), &value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the size of the receive buffer used for the socket.
|
* @brief Gets the size of the receive buffer used for the socket.
|
||||||
*
|
*
|
||||||
* Gets the size of the receive buffer that the operating system uses for
|
* Gets the size of the receive buffer that the operating system uses for
|
||||||
* the socket.<br/>
|
* the socket.<br/>
|
||||||
* This function works for TCPHandle, PipeHandle and UDPHandle handles on
|
* This function works for TCPHandle, PipeHandle and UDPHandle handles on
|
||||||
* Unix and for TCPHandle and UDPHandle handles on Windows.<br/>
|
* Unix and for TCPHandle and UDPHandle handles on Windows.<br/>
|
||||||
* Note that Linux will return double the size of the original set value.
|
* Note that Linux will return double the size of the original set value.
|
||||||
*
|
*
|
||||||
* @return The size of the receive buffer, 0 in case of errors.
|
* @return The size of the receive buffer, 0 in case of errors.
|
||||||
*/
|
*/
|
||||||
int recvBufferSize() {
|
int recvBufferSize() {
|
||||||
int value = 0;
|
int value = 0;
|
||||||
auto err = uv_recv_buffer_size(this->template get<uv_handle_t>(), &value);
|
auto err = uv_recv_buffer_size(this->template get<uv_handle_t>(), &value);
|
||||||
return err ? 0 : value;
|
return err ? 0 : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the size of the receive buffer used for the socket.
|
* @brief Sets the size of the receive buffer used for the socket.
|
||||||
*
|
*
|
||||||
* Sets the size of the receive buffer that the operating system uses for
|
* Sets the size of the receive buffer that the operating system uses for
|
||||||
* the socket.<br/>
|
* the socket.<br/>
|
||||||
* This function works for TCPHandle, PipeHandle and UDPHandle handles on
|
* This function works for TCPHandle, PipeHandle and UDPHandle handles on
|
||||||
* Unix and for TCPHandle and UDPHandle handles on Windows.<br/>
|
* Unix and for TCPHandle and UDPHandle handles on Windows.<br/>
|
||||||
* Note that Linux will set double the size.
|
* Note that Linux will set double the size.
|
||||||
*
|
*
|
||||||
* @return True in case of success, false otherwise.
|
* @return True in case of success, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool recvBufferSize(int value) {
|
bool recvBufferSize(int value) {
|
||||||
return (0 == uv_recv_buffer_size(this->template get<uv_handle_t>(), &value));
|
return (0 == uv_recv_buffer_size(this->template get<uv_handle_t>(), &value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the platform dependent file descriptor equivalent.
|
* @brief Gets the platform dependent file descriptor equivalent.
|
||||||
*
|
*
|
||||||
* Supported handles:
|
* Supported handles:
|
||||||
*
|
*
|
||||||
* * TCPHandle
|
* * TCPHandle
|
||||||
* * PipeHandle
|
* * PipeHandle
|
||||||
* * TTYHandle
|
* * TTYHandle
|
||||||
* * UDPHandle
|
* * UDPHandle
|
||||||
* * PollHandle
|
* * PollHandle
|
||||||
*
|
*
|
||||||
* It will emit an ErrorEvent event if invoked on any other handle.<br/>
|
* It will emit an ErrorEvent event if invoked on any other handle.<br/>
|
||||||
* If a handle doesn’t have an attached file descriptor yet or the handle
|
* If a handle doesn’t have an attached file descriptor yet or the handle
|
||||||
* itself has been closed, an ErrorEvent event will be emitted.
|
* itself has been closed, an ErrorEvent event will be emitted.
|
||||||
*
|
*
|
||||||
* See the official
|
* See the official
|
||||||
* [documentation](http://docs.libuv.org/en/v1.x/handle.html#c.uv_fileno)
|
* [documentation](http://docs.libuv.org/en/v1.x/handle.html#c.uv_fileno)
|
||||||
* for further details.
|
* for further details.
|
||||||
*
|
*
|
||||||
* @return The file descriptor attached to the hande or a negative value in
|
* @return The file descriptor attached to the hande or a negative value in
|
||||||
* case of errors.
|
* case of errors.
|
||||||
*/
|
*/
|
||||||
OSFileDescriptor fd() const {
|
OSFileDescriptor fd() const {
|
||||||
uv_os_fd_t fd;
|
uv_os_fd_t fd;
|
||||||
uv_fileno(this->template get<uv_handle_t>(), &fd);
|
uv_fileno(this->template get<uv_handle_t>(), &fd);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -107,16 +107,6 @@ UVW_INLINE void Loop::update() const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UVW_INLINE void Loop::walk(std::function<void(BaseHandle &)> callback) {
|
|
||||||
// remember: non-capturing lambdas decay to pointers to functions
|
|
||||||
uv_walk(loop.get(), [](uv_handle_t *handle, void *func) {
|
|
||||||
BaseHandle &ref = *static_cast<BaseHandle *>(handle->data);
|
|
||||||
std::function<void(BaseHandle &)> &f = *static_cast<std::function<void(BaseHandle &)> *>(func);
|
|
||||||
f(ref);
|
|
||||||
}, &callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
UVW_INLINE void Loop::fork() noexcept {
|
UVW_INLINE void Loop::fork() noexcept {
|
||||||
auto err = uv_loop_fork(loop.get());
|
auto err = uv_loop_fork(loop.get());
|
||||||
|
|
||||||
|
|||||||
189
src/uvw/loop.h
189
src/uvw/loop.h
@ -19,6 +19,22 @@
|
|||||||
namespace uvw {
|
namespace uvw {
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncHandle;
|
||||||
|
class CheckHandle;
|
||||||
|
class FsEventHandle;
|
||||||
|
class FsPollHandle;
|
||||||
|
class IdleHandle;
|
||||||
|
class PipeHandle;
|
||||||
|
class PollHandle;
|
||||||
|
class PrepareHandle;
|
||||||
|
class ProcessHandle;
|
||||||
|
class SignalHandle;
|
||||||
|
class TCPHandle;
|
||||||
|
class TimerHandle;
|
||||||
|
class TTYHandle;
|
||||||
|
class UDPHandle;
|
||||||
|
|
||||||
|
|
||||||
namespace details {
|
namespace details {
|
||||||
|
|
||||||
|
|
||||||
@ -37,102 +53,6 @@ enum class UVRunMode: std::underlying_type_t<uv_run_mode> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Untyped handle class
|
|
||||||
*
|
|
||||||
* Handles' types are unknown from the point of view of the loop.<br/>
|
|
||||||
* Anyway, a loop maintains a list of all the associated handles and let the
|
|
||||||
* users walk them as untyped instances.<br/>
|
|
||||||
* This can help to end all the pending requests by closing the handles.
|
|
||||||
*/
|
|
||||||
struct BaseHandle {
|
|
||||||
virtual ~BaseHandle() = default;
|
|
||||||
/**
|
|
||||||
* @brief Gets the category of the handle.
|
|
||||||
*
|
|
||||||
* A base handle offers no functionality to promote it to the actual handle
|
|
||||||
* type. By means of this function, an opaque value that identifies the
|
|
||||||
* category of the handle is made available to the users.
|
|
||||||
*
|
|
||||||
* @return The actual category of the handle.
|
|
||||||
*/
|
|
||||||
virtual HandleCategory category() const noexcept = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Gets the type of the handle.
|
|
||||||
*
|
|
||||||
* A base handle offers no functionality to promote it to the actual handle
|
|
||||||
* type. By means of this function, the type of the underlying handle as
|
|
||||||
* specified by HandleType is made available to the user.
|
|
||||||
*
|
|
||||||
* @return The actual type of the handle.
|
|
||||||
*/
|
|
||||||
virtual HandleType type() const noexcept = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if the handle is active.
|
|
||||||
*
|
|
||||||
* What _active_ means depends on the type of handle:
|
|
||||||
*
|
|
||||||
* * An AsyncHandle handle is always active and cannot be deactivated,
|
|
||||||
* except by closing it with uv_close().
|
|
||||||
* * A PipeHandle, TCPHandle, UDPHandle, etc. handle - basically any handle
|
|
||||||
* that deals with I/O - is active when it is doing something that involves
|
|
||||||
* I/O, like reading, writing, connecting, accepting new connections, etc.
|
|
||||||
* * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
|
|
||||||
* has been started with a call to `start()`.
|
|
||||||
*
|
|
||||||
* Rule of thumb: if a handle of type `FooHandle` has a `start()` member
|
|
||||||
* method, then it’s active from the moment that method is called. Likewise,
|
|
||||||
* `stop()` deactivates the handle again.
|
|
||||||
*
|
|
||||||
* @return True if the handle is active, false otherwise.
|
|
||||||
*/
|
|
||||||
virtual bool active() const noexcept = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if a handle is closing or closed.
|
|
||||||
*
|
|
||||||
* This function should only be used between the initialization of the
|
|
||||||
* handle and the arrival of the close callback.
|
|
||||||
*
|
|
||||||
* @return True if the handle is closing or closed, false otherwise.
|
|
||||||
*/
|
|
||||||
virtual bool closing() const noexcept = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reference the given handle.
|
|
||||||
*
|
|
||||||
* References are idempotent, that is, if a handle is already referenced
|
|
||||||
* calling this function again will have no effect.
|
|
||||||
*/
|
|
||||||
virtual void reference() noexcept = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unreference the given handle.
|
|
||||||
*
|
|
||||||
* References are idempotent, that is, if a handle is not referenced calling
|
|
||||||
* this function again will have no effect.
|
|
||||||
*/
|
|
||||||
virtual void unreference() noexcept = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if the given handle referenced.
|
|
||||||
* @return True if the handle referenced, false otherwise.
|
|
||||||
*/
|
|
||||||
virtual bool referenced() const noexcept = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Request handle to be closed.
|
|
||||||
*
|
|
||||||
* This **must** be called on each handle before memory is released.<br/>
|
|
||||||
* In-progress requests are cancelled and this can result in an ErrorEvent
|
|
||||||
* emitted.
|
|
||||||
*/
|
|
||||||
virtual void close() noexcept = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The Loop class.
|
* @brief The Loop class.
|
||||||
*
|
*
|
||||||
@ -147,6 +67,18 @@ class Loop final: public Emitter<Loop>, public std::enable_shared_from_this<Loop
|
|||||||
template<typename, typename>
|
template<typename, typename>
|
||||||
friend class Resource;
|
friend class Resource;
|
||||||
|
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
auto create_resource(int, Args&&... args) -> decltype(std::declval<R>().init(), std::shared_ptr<R>{}) {
|
||||||
|
auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
|
||||||
|
ptr = ptr->init() ? ptr : nullptr;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
std::shared_ptr<R> create_resource(char, Args&&... args) {
|
||||||
|
return R::create(shared_from_this(), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
Loop(std::unique_ptr<uv_loop_t, Deleter> ptr) noexcept;
|
Loop(std::unique_ptr<uv_loop_t, Deleter> ptr) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -228,13 +160,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<typename R, typename... Args>
|
template<typename R, typename... Args>
|
||||||
std::shared_ptr<R> resource(Args&&... args) {
|
std::shared_ptr<R> resource(Args&&... args) {
|
||||||
if constexpr(std::is_base_of_v<BaseHandle, R>) {
|
return create_resource<R>(0, std::forward<Args>(args)...);
|
||||||
auto ptr = R::create(shared_from_this(), std::forward<Args>(args)...);
|
|
||||||
ptr = ptr->init() ? ptr : nullptr;
|
|
||||||
return ptr;
|
|
||||||
} else {
|
|
||||||
return R::create(shared_from_this(), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -335,7 +261,62 @@ public:
|
|||||||
*
|
*
|
||||||
* @param callback A function to be invoked once for each active handle.
|
* @param callback A function to be invoked once for each active handle.
|
||||||
*/
|
*/
|
||||||
void walk(std::function<void(BaseHandle &)> callback);
|
template<typename Func>
|
||||||
|
void walk(Func callback) {
|
||||||
|
// remember: non-capturing lambdas decay to pointers to functions
|
||||||
|
uv_walk(loop.get(), [](uv_handle_t *handle, void *func) {
|
||||||
|
auto &cb = *static_cast<Func *>(func);
|
||||||
|
|
||||||
|
switch(Utilities::guessHandle(HandleCategory{handle->type})) {
|
||||||
|
case HandleType::ASYNC:
|
||||||
|
cb(*static_cast<AsyncHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::CHECK:
|
||||||
|
cb(*static_cast<CheckHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::FS_EVENT:
|
||||||
|
cb(*static_cast<FsEventHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::FS_POLL:
|
||||||
|
cb(*static_cast<FsPollHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::IDLE:
|
||||||
|
cb(*static_cast<IdleHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::PIPE:
|
||||||
|
cb(*static_cast<PipeHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::POLL:
|
||||||
|
cb(*static_cast<PollHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::PREPARE:
|
||||||
|
cb(*static_cast<PrepareHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::PROCESS:
|
||||||
|
cb(*static_cast<ProcessHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::SIGNAL:
|
||||||
|
cb(*static_cast<SignalHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::TCP:
|
||||||
|
cb(*static_cast<TCPHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::TIMER:
|
||||||
|
cb(*static_cast<TimerHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::TTY:
|
||||||
|
cb(*static_cast<TTYHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
case HandleType::UDP:
|
||||||
|
cb(*static_cast<UDPHandle *>(handle->data));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// returns the underlying handle, uvw doesn't manage it properly yet
|
||||||
|
cb(handle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, &callback);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reinitialize any kernel state necessary in the child process after
|
* @brief Reinitialize any kernel state necessary in the child process after
|
||||||
|
|||||||
@ -821,6 +821,24 @@ struct Utilities {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper type for visitors.
|
||||||
|
* @tparam Func Types of function objects.
|
||||||
|
*/
|
||||||
|
template<class... Func>
|
||||||
|
struct Overloaded: Func... {
|
||||||
|
using Func::operator()...;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deduction guide.
|
||||||
|
* @tparam Func Types of function objects.
|
||||||
|
*/
|
||||||
|
template<class... Func>
|
||||||
|
Overloaded(Func...) -> Overloaded<Func...>;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@ void listen(uvw::Loop &loop) {
|
|||||||
client->on<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TCPHandle &handle) {
|
client->on<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TCPHandle &handle) {
|
||||||
std::cout << "end" << std::endl;
|
std::cout << "end" << std::endl;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
handle.loop().walk([&count](uvw::BaseHandle &) { ++count; });
|
handle.loop().walk([&count](auto &) { ++count; });
|
||||||
std::cout << "still alive: " << count << " handles" << std::endl;
|
std::cout << "still alive: " << count << " handles" << std::endl;
|
||||||
handle.close();
|
handle.close();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,7 +9,7 @@ TEST(Loop, DefaultLoop) {
|
|||||||
ASSERT_FALSE(def->alive());
|
ASSERT_FALSE(def->alive());
|
||||||
ASSERT_NO_THROW(def->stop());
|
ASSERT_NO_THROW(def->stop());
|
||||||
|
|
||||||
def->walk([](uvw::BaseHandle &) { FAIL(); });
|
def->walk([](auto &) { FAIL(); });
|
||||||
|
|
||||||
auto def2 = uvw::Loop::getDefault();
|
auto def2 = uvw::Loop::getDefault();
|
||||||
ASSERT_EQ(def, def2);
|
ASSERT_EQ(def, def2);
|
||||||
@ -38,7 +38,7 @@ TEST(Loop, Functionalities) {
|
|||||||
|
|
||||||
handle->start();
|
handle->start();
|
||||||
handle->on<uvw::PrepareEvent>([](const auto &, auto &hndl) {
|
handle->on<uvw::PrepareEvent>([](const auto &, auto &hndl) {
|
||||||
hndl.loop().walk([](uvw::BaseHandle &) {
|
hndl.loop().walk([](auto &) {
|
||||||
static bool trigger = true;
|
static bool trigger = true;
|
||||||
ASSERT_TRUE(trigger);
|
ASSERT_TRUE(trigger);
|
||||||
trigger = false;
|
trigger = false;
|
||||||
@ -51,7 +51,7 @@ TEST(Loop, Functionalities) {
|
|||||||
ASSERT_TRUE(loop->timeout().first);
|
ASSERT_TRUE(loop->timeout().first);
|
||||||
ASSERT_NO_THROW(loop->run());
|
ASSERT_NO_THROW(loop->run());
|
||||||
|
|
||||||
loop->walk([](uvw::BaseHandle &) { FAIL(); });
|
loop->walk([](auto &) { FAIL(); });
|
||||||
|
|
||||||
ASSERT_NO_THROW(loop->run<uvw::Loop::Mode::ONCE>());
|
ASSERT_NO_THROW(loop->run<uvw::Loop::Mode::ONCE>());
|
||||||
ASSERT_NO_THROW(loop->run<uvw::Loop::Mode::NOWAIT>());
|
ASSERT_NO_THROW(loop->run<uvw::Loop::Mode::NOWAIT>());
|
||||||
|
|||||||
@ -123,16 +123,18 @@ TEST(Timer, Fake) {
|
|||||||
loop->run();
|
loop->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(Timer, BaseHandleWalk) {
|
TEST(Timer, BaseHandleWalk) {
|
||||||
auto loop = uvw::Loop::getDefault();
|
auto loop = uvw::Loop::getDefault();
|
||||||
auto timer = loop->resource<uvw::TimerHandle>();
|
auto timer = loop->resource<uvw::TimerHandle>();
|
||||||
timer->on<uvw::TimerEvent>([](const auto &event, uvw::TimerHandle &handle) {
|
|
||||||
auto &loop = handle.loop();
|
timer->on<uvw::TimerEvent>([](const auto &, uvw::TimerHandle &handle) {
|
||||||
loop.walk([](uvw::BaseHandle& h){
|
handle.loop().walk(uvw::Overloaded{
|
||||||
h.type();
|
[](uvw::TimerHandle &h){ h.close(); },
|
||||||
|
[](auto &&){}
|
||||||
});
|
});
|
||||||
handle.close();
|
|
||||||
});
|
});
|
||||||
timer->start(uvw::TimerHandle::Time{1000}, uvw::TimerHandle::Time{1000});
|
|
||||||
|
timer->start(uvw::TimerHandle::Time{100}, uvw::TimerHandle::Time{100});
|
||||||
loop->run();
|
loop->run();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user