24 template<
typename U,
typename = std::enable_if_t<std::is_
integral_v<U>>>
26 : ec{
static_cast<int>(val)}
42 return uv_translate_sys_error(sys);
52 const char *
what() const noexcept {
return uv_strerror(ec); }
61 const char *
name() const noexcept {
return uv_err_name(ec); }
67 int code() const noexcept {
return ec; }
73 explicit operator bool() const noexcept {
return ec < 0; }
89 virtual ~BaseHandler() noexcept =
default;
90 virtual bool empty()
const noexcept = 0;
91 virtual void clear() noexcept = 0;
95 struct Handler final: BaseHandler {
96 using Listener = std::function<void(E &, T &)>;
97 using Element = std::pair<bool, Listener>;
98 using ListenerList = std::list<Element>;
99 using Connection =
typename ListenerList::iterator;
101 bool empty()
const noexcept
override {
102 auto pred = [](
auto &&element){
return element.first; };
104 return std::all_of(onceL.cbegin(), onceL.cend(), pred) &&
105 std::all_of(onL.cbegin(), onL.cend(), pred);
108 void clear() noexcept
override {
110 auto func = [](
auto &&element){ element.first =
true; };
111 std::for_each(onceL.begin(), onceL.end(), func);
112 std::for_each(onL.begin(), onL.end(), func);
120 return onceL.emplace(onceL.cend(),
false, std::move(f));
124 return onL.emplace(onL.cend(),
false, std::move(f));
131 auto pred = [](
auto &&element){
return element.first; };
132 onceL.remove_if(pred);
137 void publish(E event, T &ref) {
138 ListenerList currentL;
139 onceL.swap(currentL);
141 auto func = [&event, &ref](
auto &&element) {
142 return element.first ? void() : element.second(event, ref);
147 std::for_each(onL.rbegin(), onL.rend(), func);
148 std::for_each(currentL.rbegin(), currentL.rend(), func);
152 onL.remove_if([](
auto &&element){
return element.first; });
156 bool publishing{
false};
157 ListenerList onceL{};
161 static std::size_t next_type() noexcept {
162 static std::size_t counter = 0;
167 static std::size_t event_type() noexcept {
168 static std::size_t value = next_type();
173 Handler<E> & handler() noexcept {
174 std::size_t type = event_type<E>();
176 if(!(type < handlers.size())) {
177 handlers.resize(type+1);
180 if(!handlers[type]) {
181 handlers[type] = std::make_unique<Handler<E>>();
184 return static_cast<Handler<E>&
>(*handlers[type]);
189 void publish(E event) {
190 handler<E>().publish(std::move(event), *
static_cast<T*
>(
this));
195 using Listener =
typename Handler<E>::Listener;
206 template<
typename>
friend class Emitter;
212 Connection(
typename Handler<E>::Connection conn)
213 : Handler<E>::Connection{std::move(conn)}
221 static_assert(std::is_base_of_v<
Emitter<T>, T>);
240 Connection<E>
on(Listener<E> f) {
241 return handler<E>().on(std::move(f));
260 Connection<E>
once(Listener<E> f) {
261 return handler<E>().once(std::move(f));
269 void erase(Connection<E> conn) noexcept {
270 handler<E>().erase(std::move(conn));
278 handler<E>().clear();
285 std::for_each(handlers.begin(), handlers.end(),
286 [](
auto &&hdlr){
if(hdlr) { hdlr->clear(); } });
296 std::size_t type = event_type<E>();
298 return (!(type < handlers.size()) ||
300 static_cast<Handler<E>&
>(*handlers[type]).empty());
309 return std::all_of(handlers.cbegin(), handlers.cend(),
310 [](
auto &&hdlr){
return !hdlr || hdlr->empty(); });
314 std::vector<std::unique_ptr<BaseHandler>> handlers{};
Event emitter base class.
Connection type for a given event type.
static int translate(int sys) noexcept
Returns the libuv error code equivalent to the given platform dependent error code.
bool empty() const noexcept
Checks if there are listeners registered for the specific event.
Connection< E > once(Listener< E > f)
Registers a short-lived listener with the event emitter.
const char * what() const noexcept
Returns the error message for the given error code.
bool empty() const noexcept
Checks if there are listeners registered with the event emitter.
void clear() noexcept
Disconnects all the listeners for the given event type.
void erase(Connection< E > conn) noexcept
Disconnects a listener from the event emitter.
void clear() noexcept
Disconnects all the listeners.
const char * name() const noexcept
Returns the error name for the given error code.
Connection< E > on(Listener< E > f)
Registers a long-lived listener with the event emitter.
int code() const noexcept
Gets the underlying error code, that is an error constant of libuv.