emitter/event improvements

This commit is contained in:
Michele Caini 2017-01-31 14:49:42 +01:00
parent bef8bd1d5c
commit 1be55de0a5
25 changed files with 84 additions and 182 deletions

View File

@ -1,7 +1,6 @@
#include "uvw/async.hpp"
#include "uvw/check.hpp"
#include "uvw/dns.hpp"
#include "uvw/event.hpp"
#include "uvw/fs.hpp"
#include "uvw/fs_event.hpp"
#include "uvw/fs_poll.hpp"

View File

@ -4,7 +4,6 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "loop.hpp"
@ -17,7 +16,7 @@ namespace uvw {
*
* It will be emitted by AsyncHandle according with its functionalities.
*/
struct AsyncEvent: Event<AsyncEvent> {};
struct AsyncEvent {};
/**

View File

@ -4,7 +4,6 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "loop.hpp"
@ -19,7 +18,7 @@ namespace uvw {
*
* To create a `CheckHandle` through a `Loop`, no arguments are required.
*/
struct CheckEvent: Event<CheckEvent> {};
struct CheckEvent {};
/**

View File

@ -5,7 +5,6 @@
#include <memory>
#include <string>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "util.hpp"
#include "loop.hpp"
@ -19,7 +18,7 @@ namespace uvw {
*
* It will be emitted by GetAddrInfoReq according with its functionalities.
*/
struct AddrInfoEvent: Event<AddrInfoEvent> {
struct AddrInfoEvent {
using Deleter = void(*)(addrinfo *);
AddrInfoEvent(std::unique_ptr<addrinfo, Deleter> addr)
@ -41,7 +40,7 @@ struct AddrInfoEvent: Event<AddrInfoEvent> {
*
* It will be emitted by GetNameInfoReq according with its functionalities.
*/
struct NameInfoEvent: Event<NameInfoEvent> {
struct NameInfoEvent {
NameInfoEvent(const char *host, const char *serv)
: hostname{host}, service{serv}
{}

View File

@ -9,12 +9,50 @@
#include <vector>
#include <memory>
#include <list>
#include "event.hpp"
#include <uv.h>
namespace uvw {
/**
* @brief The ErrorEvent event.
*
* Custom wrapper around libuv's error constants.
*/
struct ErrorEvent {
template<typename U, typename = std::enable_if_t<std::is_integral<U>::value>>
explicit ErrorEvent(U val) noexcept
: ec{static_cast<int>(val)}, str{uv_strerror(ec)}
{}
/**
* @brief Returns the error message for the given error code.
*
* Leaks a few bytes of memory when you call it with an unknown error code.
*
* @return The error message for the given error code.
*/
const char * what() const noexcept { return str; }
/**
* @brief Gets the underlying error code, that is a libuv's error constant.
* @return The underlying error code.
*/
int code() const noexcept { return ec; }
/**
* @brief Checks if the event contains a valid error code.
* @return True in case of success, false otherwise.
*/
explicit operator bool() const noexcept { return ec < 0; }
private:
const int ec;
const char *str;
};
/**
* @brief Event emitter base class.
*
@ -96,11 +134,20 @@ class Emitter {
ListenerList onL{};
};
static std::size_t next_type() noexcept {
static std::size_t counter = 0;
return counter++;
}
template<typename E>
static std::size_t event_type() noexcept {
static std::size_t value = next_type();
return value;
}
template<typename E>
Handler<E> & handler() noexcept {
static_assert(std::is_base_of<Event<E>, E>::value, "!");
std::size_t type = E::type();
std::size_t type = event_type<E>();
if(!(type < handlers.size())) {
handlers.resize(type+1);
@ -222,7 +269,7 @@ public:
*/
template<typename E>
bool empty() const noexcept {
std::size_t type = E::type();
std::size_t type = event_type<E>();
return (!(type < handlers.size()) ||
!handlers[type] ||

View File

@ -1,85 +0,0 @@
#pragma once
#include <cstddef>
#include <memory>
#include <uv.h>
namespace uvw {
namespace details {
struct BaseEvent {
virtual ~BaseEvent() noexcept {}
static std::size_t next() noexcept {
static std::size_t cnt = 0;
return cnt++;
}
};
}
/**
* @brief Generic event type.
*
* Events in `uvw` must be associated with an unique numerical identifier. To do
* that, they shall inherit from this class.
*/
template<typename E>
struct Event: details::BaseEvent {
/**
* @brief Gets the unique numerical identifier.
* @return An unique numerical identifier for the given event type.
*/
static std::size_t type() noexcept {
static std::size_t val = BaseEvent::next();
return val;
}
};
/**
* @brief The ErrorEvent event.
*
* Custom wrapper around libuv's error constants.
*/
struct ErrorEvent: Event<ErrorEvent> {
template<typename U, typename = std::enable_if_t<std::is_integral<U>::value>>
explicit ErrorEvent(U val) noexcept
: ec{static_cast<int>(val)}, str{uv_strerror(ec)}
{}
/**
* @brief Returns the error message for the given error code.
*
* Leaks a few bytes of memory when you call it with an unknown error code.
*
* @return The error message for the given error code.
*/
const char * what() const noexcept { return str; }
/**
* @brief Gets the underlying error code, that is a libuv's error constant.
* @return The underlying error code.
*/
int code() const noexcept { return ec; }
/**
* @brief Checks if the event contains a valid error code.
* @return True in case of success, false otherwise.
*/
explicit operator bool() const noexcept { return ec < 0; }
private:
const int ec;
const char *str;
};
}

View File

@ -6,7 +6,6 @@
#include <string>
#include <chrono>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "util.hpp"
#include "loop.hpp"
@ -111,7 +110,7 @@ enum class UVDirentTypeT: std::underlying_type_t<uv_dirent_type_t> {
* for further details.
*/
template<details::UVFsType e>
struct FsEvent: Event<FsEvent<e>> {
struct FsEvent {
FsEvent(const char *pathname) noexcept: path{pathname} {}
const char * path; /*!< The path affecting the request. */
@ -125,9 +124,7 @@ struct FsEvent: Event<FsEvent<e>> {
* functionalities.
*/
template<>
struct FsEvent<details::UVFsType::READ>
: Event<FsEvent<details::UVFsType::READ>>
{
struct FsEvent<details::UVFsType::READ> {
FsEvent(const char *pathname, std::unique_ptr<const char[]> buf, std::size_t sz) noexcept
: path{pathname}, data{std::move(buf)}, size{sz}
{}
@ -145,9 +142,7 @@ struct FsEvent<details::UVFsType::READ>
* functionalities.
*/
template<>
struct FsEvent<details::UVFsType::WRITE>
: Event<FsEvent<details::UVFsType::WRITE>>
{
struct FsEvent<details::UVFsType::WRITE> {
FsEvent(const char *pathname, std::size_t sz) noexcept
: path{pathname}, size{sz}
{}
@ -164,9 +159,7 @@ struct FsEvent<details::UVFsType::WRITE>
* functionalities.
*/
template<>
struct FsEvent<details::UVFsType::SENDFILE>
: Event<FsEvent<details::UVFsType::SENDFILE>>
{
struct FsEvent<details::UVFsType::SENDFILE> {
FsEvent(const char *pathname, std::size_t sz) noexcept
: path{pathname}, size{sz}
{}
@ -183,9 +176,7 @@ struct FsEvent<details::UVFsType::SENDFILE>
* functionalities.
*/
template<>
struct FsEvent<details::UVFsType::STAT>
: Event<FsEvent<details::UVFsType::STAT>>
{
struct FsEvent<details::UVFsType::STAT> {
FsEvent(const char *pathname, Stat curr) noexcept
: path{pathname}, stat{std::move(curr)}
{}
@ -202,9 +193,7 @@ struct FsEvent<details::UVFsType::STAT>
* functionalities.
*/
template<>
struct FsEvent<details::UVFsType::FSTAT>
: Event<FsEvent<details::UVFsType::FSTAT>>
{
struct FsEvent<details::UVFsType::FSTAT> {
FsEvent(const char *pathname, Stat curr) noexcept
: path{pathname}, stat{std::move(curr)}
{}
@ -221,9 +210,7 @@ struct FsEvent<details::UVFsType::FSTAT>
* functionalities.
*/
template<>
struct FsEvent<details::UVFsType::LSTAT>
: Event<FsEvent<details::UVFsType::LSTAT>>
{
struct FsEvent<details::UVFsType::LSTAT> {
FsEvent(const char *pathname, Stat curr) noexcept
: path{pathname}, stat{std::move(curr)}
{}
@ -240,9 +227,7 @@ struct FsEvent<details::UVFsType::LSTAT>
* functionalities.
*/
template<>
struct FsEvent<details::UVFsType::SCANDIR>
: Event<FsEvent<details::UVFsType::SCANDIR>>
{
struct FsEvent<details::UVFsType::SCANDIR> {
FsEvent(const char *pathname, std::size_t sz) noexcept
: path{pathname}, size{sz}
{}
@ -259,9 +244,7 @@ struct FsEvent<details::UVFsType::SCANDIR>
* functionalities.
*/
template<>
struct FsEvent<details::UVFsType::READLINK>
: Event<FsEvent<details::UVFsType::READLINK>>
{
struct FsEvent<details::UVFsType::READLINK> {
explicit FsEvent(const char *pathname, const char *buf, std::size_t sz) noexcept
: path{pathname}, data{buf}, size{sz}
{}

View File

@ -5,7 +5,6 @@
#include <string>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "util.hpp"
#include "loop.hpp"
@ -38,7 +37,7 @@ enum class UVFsEvent: std::underlying_type_t<uv_fs_event> {
*
* It will be emitted by FsEventHandle according with its functionalities.
*/
struct FsEventEvent: Event<FsEventEvent> {
struct FsEventEvent {
FsEventEvent(const char * pathname, Flags<details::UVFsEvent> events)
: filename{pathname}, flags{std::move(events)}
{}

View File

@ -5,7 +5,6 @@
#include <string>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "util.hpp"
#include "loop.hpp"
@ -19,7 +18,7 @@ namespace uvw {
*
* It will be emitted by FsPollHandle according with its functionalities.
*/
struct FsPollEvent: Event<FsPollEvent> {
struct FsPollEvent {
explicit FsPollEvent(Stat previous, Stat current) noexcept
: prev{std::move(previous)}, curr{std::move(current)}
{}

View File

@ -17,7 +17,7 @@ namespace uvw {
*
* It will be emitted by the handles according with their functionalities.
*/
struct CloseEvent: Event<CloseEvent> {};
struct CloseEvent {};
/**

View File

@ -4,7 +4,6 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "loop.hpp"
@ -17,7 +16,7 @@ namespace uvw {
*
* It will be emitted by IdleHandle according with its functionalities.
*/
struct IdleEvent: Event<IdleEvent> {};
struct IdleEvent {};
/**

View File

@ -6,7 +6,6 @@
#include <memory>
#include <string>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "stream.hpp"
#include "util.hpp"

View File

@ -5,7 +5,6 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "util.hpp"
@ -31,7 +30,7 @@ enum class UVPollEvent: std::underlying_type_t<uv_poll_event> {
*
* It will be emitted by PollHandle according with its functionalities.
*/
struct PollEvent: Event<PollEvent> {
struct PollEvent {
explicit PollEvent(Flags<details::UVPollEvent> events) noexcept
: flags{std::move(events)}
{}

View File

@ -4,7 +4,6 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "loop.hpp"
@ -19,7 +18,7 @@ namespace uvw {
*
* To create a `PrepareHandle` through a `Loop`, no arguments are required.
*/
struct PrepareEvent: Event<PrepareEvent> {};
struct PrepareEvent {};
/**

View File

@ -7,7 +7,6 @@
#include <string>
#include <vector>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "stream.hpp"
#include "util.hpp"
@ -47,7 +46,7 @@ enum class UVStdIOFlags: std::underlying_type_t<uv_stdio_flags> {
*
* It will be emitted by ProcessHandle according with its functionalities.
*/
struct ExitEvent: Event<ExitEvent> {
struct ExitEvent {
explicit ExitEvent(int64_t code, int sig) noexcept
: status{code}, signal{sig}
{}

View File

@ -4,7 +4,6 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "loop.hpp"
@ -17,7 +16,7 @@ namespace uvw {
*
* It will be emitted by SignalHandle according with its functionalities.
*/
struct SignalEvent: Event<SignalEvent> {
struct SignalEvent {
explicit SignalEvent(int sig) noexcept: signum{sig} {}
int signum; /*!< The signal being monitored by this handle. */

View File

@ -7,7 +7,6 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "handle.hpp"
#include "loop.hpp"
@ -21,7 +20,7 @@ namespace uvw {
*
* It will be emitted by StreamHandle according with its functionalities.
*/
struct ConnectEvent: Event<ConnectEvent> {};
struct ConnectEvent {};
/**
@ -29,7 +28,7 @@ struct ConnectEvent: Event<ConnectEvent> {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
struct EndEvent: Event<EndEvent> {};
struct EndEvent {};
/**
@ -37,7 +36,7 @@ struct EndEvent: Event<EndEvent> {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
struct ListenEvent: Event<ListenEvent> {};
struct ListenEvent {};
/**
@ -45,7 +44,7 @@ struct ListenEvent: Event<ListenEvent> {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
struct ShutdownEvent: Event<ShutdownEvent> {};
struct ShutdownEvent {};
/**
@ -53,7 +52,7 @@ struct ShutdownEvent: Event<ShutdownEvent> {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
struct WriteEvent: Event<WriteEvent> {};
struct WriteEvent {};
/**
@ -61,7 +60,7 @@ struct WriteEvent: Event<WriteEvent> {};
*
* It will be emitted by StreamHandle according with its functionalities.
*/
struct DataEvent: Event<DataEvent> {
struct DataEvent {
explicit DataEvent(std::unique_ptr<char[]> buf, std::size_t len) noexcept
: data{std::move(buf)}, length{len}
{}

View File

@ -7,7 +7,6 @@
#include <string>
#include <chrono>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "stream.hpp"
#include "util.hpp"

View File

@ -5,7 +5,6 @@
#include <memory>
#include <chrono>
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "loop.hpp"
@ -18,7 +17,7 @@ namespace uvw {
*
* It will be emitted by TimerHandle according with its functionalities.
*/
struct TimerEvent: Event<TimerEvent> {};
struct TimerEvent {};
/**

View File

@ -5,7 +5,6 @@
#include <cstddef>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "stream.hpp"
#include "util.hpp"

View File

@ -9,7 +9,6 @@
#include <memory>
#include <string>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "handle.hpp"
#include "util.hpp"
@ -23,7 +22,7 @@ namespace uvw {
*
* It will be emitted by UDPHandle according with its functionalities.
*/
struct SendEvent: Event<SendEvent> {};
struct SendEvent {};
/**
@ -31,7 +30,7 @@ struct SendEvent: Event<SendEvent> {};
*
* It will be emitted by UDPHandle according with its functionalities.
*/
struct UDPDataEvent: Event<UDPDataEvent> {
struct UDPDataEvent {
explicit UDPDataEvent(Addr sndr, std::unique_ptr<const char[]> buf, std::size_t len, bool part) noexcept
: data{std::move(buf)}, length{len}, sender{std::move(sndr)}, partial{part}
{}

View File

@ -5,7 +5,6 @@
#include <utility>
#include <memory>
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "loop.hpp"
@ -18,7 +17,7 @@ namespace uvw {
*
* It will be emitted by WorkReq according with its functionalities.
*/
struct WorkEvent: Event<WorkEvent> {};
struct WorkEvent {};
/**

View File

@ -36,7 +36,6 @@ set(TARGET_ASYNC async)
set(TARGET_CHECK check)
set(TARGET_DNS dns)
set(TARGET_EMITTER emitter)
set(TARGET_EVENT event)
set(TARGET_FS_REQ fs_req)
set(TARGET_FILE_REQ file_req)
set(TARGET_HANDLE handle)
@ -91,14 +90,6 @@ target_include_directories(${TARGET_EMITTER} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_EMITTER} PRIVATE ${COMMON_LINK_LIBS})
add_test(NAME ${TARGET_EMITTER} COMMAND ${TARGET_EMITTER})
# Test TARGET_EVENT
set(TARGET_EVENT_SOURCES $<TARGET_OBJECTS:odr> uvw/event.cpp)
add_executable(${TARGET_EVENT} ${TARGET_EVENT_SOURCES})
target_include_directories(${TARGET_EVENT} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_EVENT} PRIVATE ${COMMON_LINK_LIBS})
add_test(NAME ${TARGET_EVENT} COMMAND ${TARGET_EVENT})
# Test TARGET_FS_REQ
set(TARGET_FS_REQ_SOURCES $<TARGET_OBJECTS:odr> uvw/fs_req.cpp)

View File

@ -1,9 +1,8 @@
#include <gtest/gtest.h>
#include <uvw/emitter.hpp>
#include <uvw/event.hpp>
struct FakeEvent: uvw::Event<FakeEvent> { };
struct FakeEvent { };
struct TestEmitter: uvw::Emitter<TestEmitter> {
void emit() { publish(FakeEvent{}); }

View File

@ -1,15 +0,0 @@
#include <gtest/gtest.h>
#include <uvw/event.hpp>
struct EventA: uvw::Event<EventA> {};
struct EventB: uvw::Event<EventB> {};
TEST(Event, Uniqueness) {
ASSERT_EQ(EventA::type(), EventA::type());
ASSERT_EQ(EventA::type(), EventA{}.type());
ASSERT_NE(EventA::type(), EventB::type());
ASSERT_NE(EventA::type(), EventB{}.type());
}