refactor(signals): Avoid reinterpret_cast

This commit is contained in:
Michael Carlberg 2017-01-01 20:29:38 +01:00
parent d9c035381e
commit a2bcb1a627
10 changed files with 173 additions and 114 deletions

View File

@ -5,34 +5,18 @@
#include "components/ipc.hpp" #include "components/ipc.hpp"
#include "components/parser.hpp" #include "components/parser.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "events/types.hpp"
#include "utils/functional.hpp" #include "utils/functional.hpp"
POLYBAR_NS POLYBAR_NS
// fwd decl {{{ // fwd
enum class mousebtn : uint8_t; enum class mousebtn : uint8_t;
enum class syntaxtag : uint8_t; enum class syntaxtag : uint8_t;
enum class alignment : uint8_t; enum class alignment : uint8_t;
enum class attribute : uint8_t; enum class attribute : uint8_t;
// }}}
#define DEFINE_SIGNAL(id, name) \
struct name : public detail::base_signal<name, id> { \
using base_type::base_type; \
}
#define DEFINE_VALUE_SIGNAL(id, name, type) \
struct name : public detail::value_signal<name, id, type> { \
using base_type::base_type; \
}
namespace signals { namespace signals {
namespace detail { namespace detail {
// definition : signal {{{
class signal { class signal {
public: public:
explicit signal() = default; explicit signal() = default;
@ -40,98 +24,161 @@ namespace signals {
virtual size_t size() const = 0; virtual size_t size() const = 0;
}; };
// }}} template <typename Derived>
// definition : base_signal {{{
template <typename Derived, uint8_t Id>
class base_signal : public signal { class base_signal : public signal {
public: public:
using base_type = base_signal<Derived, Id>; using base_type = base_signal<Derived>;
explicit base_signal() = default; explicit base_signal() = default;
virtual ~base_signal() {} virtual ~base_signal() {}
static uint8_t id() {
return Id;
}
virtual size_t size() const override { virtual size_t size() const override {
return sizeof(Derived); return sizeof(Derived);
}; };
}; };
// }}} template <typename Derived, typename ValueType>
// definition : value_signal {{{ class value_signal : public base_signal<Derived> {
template <typename Derived, uint8_t Id, typename ValueType>
class value_signal : public base_signal<Derived, Id> {
public: public:
using base_type = value_signal<Derived, Id, ValueType>; using base_type = value_signal<Derived, ValueType>;
using value_type = ValueType; using value_type = ValueType;
explicit value_signal() {} template <size_t Size = sizeof(ValueType)>
explicit value_signal(ValueType&& data) { explicit value_signal(void* data) : m_data(data), m_size(Size) {}
memcpy(m_data, &data, sizeof(data));
template <size_t Size = sizeof(ValueType)>
explicit value_signal(ValueType data) : m_size(Size) {
m_data = new char[Size];
m_alloced = true;
memcpy(m_data, static_cast<void*>(&data), Size);
} }
virtual ~value_signal() {} virtual ~value_signal() {
if (m_alloced) {
const ValueType* operator()() const { delete[] static_cast<char*>(m_data);
return reinterpret_cast<const ValueType*>(&m_data);
} }
const ValueType* data() const { }
return reinterpret_cast<const ValueType*>(&m_data);
void* data() const {
return m_data;
}
size_t size() const {
return m_size;
}
inline ValueType cast() const {
return *static_cast<ValueType*>(m_data);
} }
private: private:
char m_data[sizeof(ValueType)]; void* m_data;
size_t m_size;
bool m_alloced{false};
}; };
// }}}
} }
namespace eventqueue { namespace eventqueue {
DEFINE_SIGNAL(1, exit_terminate); struct exit_terminate : public detail::base_signal<exit_terminate> {
DEFINE_SIGNAL(2, exit_reload); using base_type::base_type;
DEFINE_SIGNAL(3, notify_change); };
DEFINE_SIGNAL(4, check_state); struct exit_reload : public detail::base_signal<exit_reload> {
DEFINE_SIGNAL(5, update); using base_type::base_type;
};
struct notify_change : public detail::base_signal<notify_change> {
using base_type::base_type;
};
struct check_state : public detail::base_signal<check_state> {
using base_type::base_type;
};
struct update : public detail::base_signal<update> {
using base_type::base_type;
};
} }
namespace ipc { namespace ipc {
DEFINE_VALUE_SIGNAL(20, command, string); struct command : public detail::value_signal<command, string> {
DEFINE_VALUE_SIGNAL(21, hook, string); using base_type::base_type;
DEFINE_VALUE_SIGNAL(22, action, string); };
struct hook : public detail::value_signal<hook, string> {
using base_type::base_type;
};
struct action : public detail::value_signal<action, string> {
using base_type::base_type;
};
} }
namespace ui { namespace ui {
DEFINE_SIGNAL(50, tick); struct tick : public detail::base_signal<tick> {
DEFINE_VALUE_SIGNAL(51, button_press, string); using base_type::base_type;
DEFINE_VALUE_SIGNAL(52, visibility_change, bool); };
DEFINE_VALUE_SIGNAL(53, dim_window, double); struct button_press : public detail::value_signal<button_press, string> {
DEFINE_SIGNAL(54, shade_window); using base_type::base_type;
DEFINE_SIGNAL(55, unshade_window); };
struct visibility_change : public detail::value_signal<visibility_change, bool> {
using base_type::base_type;
};
struct dim_window : public detail::value_signal<dim_window, double> {
using base_type::base_type;
};
struct shade_window : public detail::base_signal<shade_window> {
using base_type::base_type;
};
struct unshade_window : public detail::base_signal<unshade_window> {
using base_type::base_type;
};
}
namespace ui_tray {
struct mapped_clients : public detail::value_signal<mapped_clients, size_t> {
using base_type::base_type;
};
} }
namespace parser { namespace parser {
using parser_t = polybar::parser; struct change_background : public detail::value_signal<change_background, uint32_t> {
using base_type::base_type;
DEFINE_VALUE_SIGNAL(70, change_background, uint32_t); };
DEFINE_VALUE_SIGNAL(71, change_foreground, uint32_t); struct change_foreground : public detail::value_signal<change_foreground, uint32_t> {
DEFINE_VALUE_SIGNAL(72, change_underline, uint32_t); using base_type::base_type;
DEFINE_VALUE_SIGNAL(73, change_overline, uint32_t); };
DEFINE_VALUE_SIGNAL(74, change_font, uint8_t); struct change_underline : public detail::value_signal<change_underline, uint32_t> {
DEFINE_VALUE_SIGNAL(75, change_alignment, alignment); using base_type::base_type;
DEFINE_VALUE_SIGNAL(76, offset_pixel, int16_t); };
DEFINE_VALUE_SIGNAL(77, attribute_set, attribute); struct change_overline : public detail::value_signal<change_overline, uint32_t> {
DEFINE_VALUE_SIGNAL(78, attribute_unset, attribute); using base_type::base_type;
DEFINE_VALUE_SIGNAL(79, attribute_toggle, attribute); };
DEFINE_VALUE_SIGNAL(80, action_begin, action); struct change_font : public detail::value_signal<change_font, uint8_t> {
DEFINE_VALUE_SIGNAL(81, action_end, mousebtn); using base_type::base_type;
DEFINE_VALUE_SIGNAL(82, write_text_ascii, uint16_t); };
DEFINE_VALUE_SIGNAL(83, write_text_unicode, uint16_t); struct change_alignment : public detail::value_signal<change_alignment, alignment> {
DEFINE_VALUE_SIGNAL(84, write_text_string, parser_t::packet); using base_type::base_type;
};
struct offset_pixel : public detail::value_signal<offset_pixel, int16_t> {
using base_type::base_type;
};
struct attribute_set : public detail::value_signal<attribute_set, attribute> {
using base_type::base_type;
};
struct attribute_unset : public detail::value_signal<attribute_unset, attribute> {
using base_type::base_type;
};
struct attribute_toggle : public detail::value_signal<attribute_toggle, attribute> {
using base_type::base_type;
};
struct action_begin : public detail::value_signal<action_begin, action> {
using base_type::base_type;
};
struct action_end : public detail::value_signal<action_end, mousebtn> {
using base_type::base_type;
};
struct write_text_ascii : public detail::value_signal<write_text_ascii, uint16_t> {
using base_type::base_type;
};
struct write_text_unicode : public detail::value_signal<write_text_unicode, uint16_t> {
using base_type::base_type;
};
struct write_text_string : public detail::value_signal<write_text_string, polybar::parser::packet> {
using base_type::base_type;
};
} }
} }

View File

@ -2,8 +2,6 @@
#include "common.hpp" #include "common.hpp"
#include "events/signal_receiver.hpp" #include "events/signal_receiver.hpp"
#include "utils/factory.hpp"
#include "utils/mixins.hpp"
POLYBAR_NS POLYBAR_NS
@ -55,8 +53,8 @@ class signal_emitter {
protected: protected:
template <typename Signal> template <typename Signal>
uint8_t id() const { std::type_index id() const {
return Signal::id(); return typeid(Signal);
} }
template <typename Receiver, typename Signal> template <typename Receiver, typename Signal>
@ -70,7 +68,7 @@ class signal_emitter {
attach<Receiver, Next, Signals...>(s); attach<Receiver, Next, Signals...>(s);
} }
void attach(signal_receiver_interface* s, uint8_t id) { void attach(signal_receiver_interface* s, std::type_index id) {
g_signal_receivers[id].emplace(s->priority(), s); g_signal_receivers[id].emplace(s->priority(), s);
} }
@ -85,7 +83,7 @@ class signal_emitter {
detach<Receiver, Next, Signals...>(s); detach<Receiver, Next, Signals...>(s);
} }
void detach(signal_receiver_interface* d, uint8_t id) { void detach(signal_receiver_interface* d, std::type_index id) {
try { try {
auto& prio_map = g_signal_receivers.at(id); auto& prio_map = g_signal_receivers.at(id);
const auto& prio_sink_pair = prio_map.equal_range(d->priority()); const auto& prio_sink_pair = prio_map.equal_range(d->priority());

View File

@ -4,10 +4,16 @@
POLYBAR_NS POLYBAR_NS
class signal_emitter;
class signal_receiver_interface;
template <uint8_t Priority, typename Signal, typename... Signals> template <uint8_t Priority, typename Signal, typename... Signals>
class signal_receiver; class signal_receiver;
namespace signals { namespace signals {
namespace detail {
class signal;
}
namespace eventqueue { namespace eventqueue {
struct exit_terminate; struct exit_terminate;
struct exit_reload; struct exit_reload;
@ -28,6 +34,9 @@ namespace signals {
struct shade_window; struct shade_window;
struct unshade_window; struct unshade_window;
} }
namespace ui_tray {
struct mapped_clients;
}
namespace parser { namespace parser {
struct change_background; struct change_background;
struct change_foreground; struct change_foreground;

View File

@ -2,6 +2,8 @@
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <typeindex>
#include <typeinfo>
#include "common.hpp" #include "common.hpp"
@ -45,6 +47,6 @@ class signal_receiver : public signal_receiver_interface,
} }
}; };
using signal_receivers_t = std::unordered_map<uint8_t, signal_receiver_interface::prio_map>; using signal_receivers_t = std::unordered_map<std::type_index, signal_receiver_interface::prio_map>;
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -514,7 +514,7 @@ void bar::handle(const evt::leave_notify&) {
if (!m_opts.dimmed) { if (!m_opts.dimmed) {
m_taskqueue->defer_unique("window-dim", 3s, [&](size_t) { m_taskqueue->defer_unique("window-dim", 3s, [&](size_t) {
m_opts.dimmed = true; m_opts.dimmed = true;
m_sig.emit(dim_window{double{m_opts.dimvalue}}); m_sig.emit(dim_window{m_opts.dimvalue});
}); });
} }
} }
@ -722,8 +722,8 @@ bool bar::on(const sig_ui::tick&) {
} }
bool bar::on(const sig_ui::dim_window& sig) { bool bar::on(const sig_ui::dim_window& sig) {
m_opts.dimmed = *sig.data() != 1.0; m_opts.dimmed = sig.cast() != 1.0;
set_wm_window_opacity(m_connection, m_opts.window, *sig.data() * 0xFFFFFFFF); set_wm_window_opacity(m_connection, m_opts.window, sig.cast() * 0xFFFFFFFF);
m_connection.flush(); m_connection.flush();
return false; return false;
} }

View File

@ -531,7 +531,7 @@ bool controller::on(const sig_ev::check_state&) {
* Process ui button press event * Process ui button press event
*/ */
bool controller::on(const sig_ui::button_press& evt) { bool controller::on(const sig_ui::button_press& evt) {
string input{*evt()}; string input{evt.cast()};
if (input.empty()) { if (input.empty()) {
m_log.err("Cannot enqueue empty input"); m_log.err("Cannot enqueue empty input");
@ -546,7 +546,7 @@ bool controller::on(const sig_ui::button_press& evt) {
* Process ipc action messages * Process ipc action messages
*/ */
bool controller::on(const sig_ipc::action& evt) { bool controller::on(const sig_ipc::action& evt) {
string action{*evt()}; string action{evt.cast()};
if (action.empty()) { if (action.empty()) {
m_log.err("Cannot enqueue empty ipc action"); m_log.err("Cannot enqueue empty ipc action");
@ -562,7 +562,7 @@ bool controller::on(const sig_ipc::action& evt) {
* Process ipc command messages * Process ipc command messages
*/ */
bool controller::on(const sig_ipc::command& evt) { bool controller::on(const sig_ipc::command& evt) {
string command{*evt()}; string command{evt.cast()};
if (command.empty()) { if (command.empty()) {
return false; return false;
@ -583,7 +583,7 @@ bool controller::on(const sig_ipc::command& evt) {
* Process ipc hook messages * Process ipc hook messages
*/ */
bool controller::on(const sig_ipc::hook& evt) { bool controller::on(const sig_ipc::hook& evt) {
string hook{*evt()}; string hook{evt.cast()};
for (const auto& block : m_modules) { for (const auto& block : m_modules) {
for (const auto& module : block.second) { for (const auto& module : block.second) {

View File

@ -184,7 +184,7 @@ size_t parser::text(string&& data) {
} }
pkt.length = len; pkt.length = len;
m_sig.emit(write_text_string{move(pkt)}); m_sig.emit(write_text_string{static_cast<void*>(&pkt)});
} }
if (pos > 0) { if (pos > 0) {

View File

@ -530,7 +530,7 @@ void renderer::debug_hints() {
#endif #endif
bool renderer::on(const change_background& evt) { bool renderer::on(const change_background& evt) {
const uint32_t color{*evt()}; const uint32_t color{evt.cast()};
if (m_colors[gc::BG] == color) { if (m_colors[gc::BG] == color) {
m_log.trace_x("renderer: ignoring unchanged background color(#%08x)", color); m_log.trace_x("renderer: ignoring unchanged background color(#%08x)", color);
@ -545,7 +545,7 @@ bool renderer::on(const change_background& evt) {
} }
bool renderer::on(const change_foreground& evt) { bool renderer::on(const change_foreground& evt) {
const uint32_t color{*evt()}; const uint32_t color{evt.cast()};
if (m_colors[gc::FG] == color) { if (m_colors[gc::FG] == color) {
m_log.trace_x("renderer: ignoring unchanged foreground color(#%08x)", color); m_log.trace_x("renderer: ignoring unchanged foreground color(#%08x)", color);
@ -560,7 +560,7 @@ bool renderer::on(const change_foreground& evt) {
} }
bool renderer::on(const change_underline& evt) { bool renderer::on(const change_underline& evt) {
const uint32_t color{*evt()}; const uint32_t color{evt.cast()};
if (m_colors[gc::UL] == color) { if (m_colors[gc::UL] == color) {
m_log.trace_x("renderer: ignoring unchanged underline color(#%08x)", color); m_log.trace_x("renderer: ignoring unchanged underline color(#%08x)", color);
@ -574,7 +574,7 @@ bool renderer::on(const change_underline& evt) {
} }
bool renderer::on(const change_overline& evt) { bool renderer::on(const change_overline& evt) {
const uint32_t color{*evt()}; const uint32_t color{evt.cast()};
if (m_colors[gc::OL] == color) { if (m_colors[gc::OL] == color) {
m_log.trace_x("renderer: ignoring unchanged overline color(#%08x)", color); m_log.trace_x("renderer: ignoring unchanged overline color(#%08x)", color);
@ -588,7 +588,7 @@ bool renderer::on(const change_overline& evt) {
} }
bool renderer::on(const change_font& evt) { bool renderer::on(const change_font& evt) {
const uint8_t font{*evt()}; const uint8_t font{evt.cast()};
if (m_fontindex == font) { if (m_fontindex == font) {
m_log.trace_x("renderer: ignoring unchanged font index(%i)", static_cast<uint8_t>(font)); m_log.trace_x("renderer: ignoring unchanged font index(%i)", static_cast<uint8_t>(font));
@ -602,7 +602,7 @@ bool renderer::on(const change_font& evt) {
} }
bool renderer::on(const change_alignment& evt) { bool renderer::on(const change_alignment& evt) {
auto align = static_cast<const alignment&>(*evt()); auto align = static_cast<const alignment&>(evt.cast());
if (align == m_alignment) { if (align == m_alignment) {
m_log.trace_x("renderer: ignoring unchanged alignment(%i)", static_cast<uint8_t>(align)); m_log.trace_x("renderer: ignoring unchanged alignment(%i)", static_cast<uint8_t>(align));
@ -616,30 +616,30 @@ bool renderer::on(const change_alignment& evt) {
} }
bool renderer::on(const offset_pixel& evt) { bool renderer::on(const offset_pixel& evt) {
shift_content(*evt()); shift_content(evt.cast());
return true; return true;
} }
bool renderer::on(const attribute_set& evt) { bool renderer::on(const attribute_set& evt) {
m_log.trace_x("renderer: attribute_set(%i, %i)", static_cast<uint8_t>(*evt()), true); m_log.trace_x("renderer: attribute_set(%i, %i)", static_cast<uint8_t>(evt.cast()), true);
m_attributes |= 1U << static_cast<uint8_t>(*evt()); m_attributes |= 1U << static_cast<uint8_t>(evt.cast());
return true; return true;
} }
bool renderer::on(const attribute_unset& evt) { bool renderer::on(const attribute_unset& evt) {
m_log.trace_x("renderer: attribute_unset(%i, %i)", static_cast<uint8_t>(*evt()), true); m_log.trace_x("renderer: attribute_unset(%i, %i)", static_cast<uint8_t>(evt.cast()), true);
m_attributes &= ~(1U << static_cast<uint8_t>(*evt())); m_attributes &= ~(1U << static_cast<uint8_t>(evt.cast()));
return true; return true;
} }
bool renderer::on(const attribute_toggle& evt) { bool renderer::on(const attribute_toggle& evt) {
m_log.trace_x("renderer: attribute_toggle(%i)", static_cast<uint8_t>(*evt())); m_log.trace_x("renderer: attribute_toggle(%i)", static_cast<uint8_t>(evt.cast()));
m_attributes ^= 1U << static_cast<uint8_t>(*evt()); m_attributes ^= 1U << static_cast<uint8_t>(evt.cast());
return true; return true;
} }
bool renderer::on(const action_begin& evt) { bool renderer::on(const action_begin& evt) {
auto a = static_cast<const action&>(*evt()); auto a = static_cast<const action&>(evt.cast());
action_block action{}; action_block action{};
action.button = a.button; action.button = a.button;
action.align = m_alignment; action.align = m_alignment;
@ -658,7 +658,7 @@ bool renderer::on(const action_begin& evt) {
} }
bool renderer::on(const action_end& evt) { bool renderer::on(const action_end& evt) {
auto btn = static_cast<const mousebtn&>(*evt()); auto btn = static_cast<const mousebtn&>(evt.cast());
int16_t clickable_width{0}; int16_t clickable_width{0};
for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) { for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) {
@ -695,19 +695,19 @@ bool renderer::on(const action_end& evt) {
} }
bool renderer::on(const write_text_ascii& evt) { bool renderer::on(const write_text_ascii& evt) {
const uint16_t data[1]{*evt()}; const uint16_t data[1]{evt.cast()};
draw_textstring(data, 1); draw_textstring(data, 1);
return true; return true;
} }
bool renderer::on(const write_text_unicode& evt) { bool renderer::on(const write_text_unicode& evt) {
const uint16_t data[1]{*evt()}; const uint16_t data[1]{evt.cast()};
draw_textstring(data, 1); draw_textstring(data, 1);
return true; return true;
} }
bool renderer::on(const write_text_string& evt) { bool renderer::on(const write_text_string& evt) {
auto pkt = static_cast<const parser::packet&>(*evt()); auto pkt = *static_cast<const parser::packet*>(evt.data());
draw_textstring(pkt.data, pkt.length); draw_textstring(pkt.data, pkt.length);
return true; return true;
} }

View File

@ -1,4 +1,5 @@
#include "events/signal_emitter.hpp" #include "events/signal_emitter.hpp"
#include "utils/factory.hpp"
POLYBAR_NS POLYBAR_NS

View File

@ -1093,10 +1093,11 @@ void tray_manager::handle(const evt::map_notify& evt) {
m_log.trace("tray: Received map_notify"); m_log.trace("tray: Received map_notify");
m_log.trace("tray: Set client mapped"); m_log.trace("tray: Set client mapped");
find_client(evt->window)->mapped(true); find_client(evt->window)->mapped(true);
size_t clientcount{mapped_clients()};
if (mapped_clients() > m_opts.configured_slots) { if (clientcount > m_opts.configured_slots) {
reconfigure(); reconfigure();
} }
m_sig.emit(signals::ui_tray::mapped_clients{clientcount});
} }
} }
@ -1111,7 +1112,8 @@ void tray_manager::handle(const evt::unmap_notify& evt) {
} else if (m_activated && is_embedded(evt->window)) { } else if (m_activated && is_embedded(evt->window)) {
m_log.trace("tray: Received unmap_notify"); m_log.trace("tray: Received unmap_notify");
m_log.trace("tray: Set client unmapped"); m_log.trace("tray: Set client unmapped");
find_client(evt->window)->mapped(true); find_client(evt->window)->mapped(false);
m_sig.emit(signals::ui_tray::mapped_clients{mapped_clients()});
} }
} }
@ -1121,7 +1123,7 @@ void tray_manager::handle(const evt::unmap_notify& evt) {
* toggle the tray window whenever the visibility of the bar window changes. * toggle the tray window whenever the visibility of the bar window changes.
*/ */
bool tray_manager::on(const visibility_change& evt) { bool tray_manager::on(const visibility_change& evt) {
bool visible{*evt()}; bool visible{evt.cast()};
size_t clients{mapped_clients()}; size_t clients{mapped_clients()};
m_log.trace("tray: visibility_change (state=%i, activated=%i, mapped=%i, hidden=%i)", visible, m_log.trace("tray: visibility_change (state=%i, activated=%i, mapped=%i, hidden=%i)", visible,
@ -1146,7 +1148,7 @@ bool tray_manager::on(const visibility_change& evt) {
bool tray_manager::on(const dim_window& evt) { bool tray_manager::on(const dim_window& evt) {
if (m_activated) { if (m_activated) {
wm_util::set_wm_window_opacity(m_connection, m_tray, *evt.data() * 0xFFFFFFFF); wm_util::set_wm_window_opacity(m_connection, m_tray, evt.cast() * 0xFFFFFFFF);
m_connection.flush(); m_connection.flush();
} }
// let the event bubble // let the event bubble