mirror of
https://github.com/polybar/polybar.git
synced 2024-12-09 14:10:19 -05:00
b636baf082
If any signal receiver throws an exception for any reason after receiving a signal, no one would find out about it because the signal emitter just ignored exceptions Also actually delivering the signal caused some exceptions because not all signals have a receiver. Resolves #1593
107 lines
2.7 KiB
C++
107 lines
2.7 KiB
C++
#pragma once
|
|
|
|
#include "common.hpp"
|
|
#include "components/logger.hpp"
|
|
#include "events/signal_receiver.hpp"
|
|
|
|
POLYBAR_NS
|
|
|
|
/**
|
|
* \brief Holds all signal receivers attached to the emitter
|
|
*/
|
|
extern signal_receivers_t g_signal_receivers;
|
|
|
|
/**
|
|
* Wrapper used to delegate emitted signals
|
|
* to attached signal receivers
|
|
*/
|
|
class signal_emitter {
|
|
public:
|
|
using make_type = signal_emitter&;
|
|
static make_type make();
|
|
|
|
explicit signal_emitter() = default;
|
|
virtual ~signal_emitter() {}
|
|
|
|
template <typename Signal>
|
|
bool emit(const Signal& sig) {
|
|
try {
|
|
if (g_signal_receivers.find(id<Signal>()) != g_signal_receivers.end()) {
|
|
for (auto&& item : g_signal_receivers.at(id<Signal>())) {
|
|
if (item.second->on(sig)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
} catch (const std::exception& e) {
|
|
logger::make().err(e.what());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template <typename Signal, typename Next, typename... Signals>
|
|
bool emit(const Signal& sig) const {
|
|
return emit<Signal>(sig) || emit<Next, Signals...>(sig);
|
|
}
|
|
|
|
template <int Priority, typename Signal, typename... Signals>
|
|
void attach(signal_receiver<Priority, Signal, Signals...>* s) {
|
|
attach<signal_receiver<Priority, Signal, Signals...>, Signal, Signals...>(s);
|
|
}
|
|
|
|
template <int Priority, typename Signal, typename... Signals>
|
|
void detach(signal_receiver<Priority, Signal, Signals...>* s) {
|
|
detach<signal_receiver<Priority, Signal, Signals...>, Signal, Signals...>(s);
|
|
}
|
|
|
|
protected:
|
|
template <typename Signal>
|
|
std::type_index id() const {
|
|
return typeid(Signal);
|
|
}
|
|
|
|
template <typename Receiver, typename Signal>
|
|
void attach(Receiver* s) {
|
|
attach(s, id<Signal>());
|
|
}
|
|
|
|
template <typename Receiver, typename Signal, typename Next, typename... Signals>
|
|
void attach(Receiver* s) {
|
|
attach(s, id<Signal>());
|
|
attach<Receiver, Next, Signals...>(s);
|
|
}
|
|
|
|
void attach(signal_receiver_interface* s, std::type_index id) {
|
|
g_signal_receivers[id].emplace(s->priority(), s);
|
|
}
|
|
|
|
template <typename Receiver, typename Signal>
|
|
void detach(Receiver* s) {
|
|
detach(s, id<Signal>());
|
|
}
|
|
|
|
template <typename Receiver, typename Signal, typename Next, typename... Signals>
|
|
void detach(Receiver* s) {
|
|
detach(s, id<Signal>());
|
|
detach<Receiver, Next, Signals...>(s);
|
|
}
|
|
|
|
void detach(signal_receiver_interface* d, std::type_index id) {
|
|
try {
|
|
auto& prio_map = g_signal_receivers.at(id);
|
|
const auto& prio_sink_pair = prio_map.equal_range(d->priority());
|
|
|
|
for (auto it = prio_sink_pair.first; it != prio_sink_pair.second;) {
|
|
if (d == it->second) {
|
|
it = prio_map.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
} catch (...) {
|
|
}
|
|
}
|
|
};
|
|
|
|
POLYBAR_NS_END
|