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/parser.hpp"
#include "components/types.hpp"
#include "events/types.hpp"
#include "utils/functional.hpp"
POLYBAR_NS
// fwd decl {{{
// fwd
enum class mousebtn : uint8_t;
enum class syntaxtag : uint8_t;
enum class alignment : 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 detail {
// definition : signal {{{
class signal {
public:
explicit signal() = default;
@ -40,98 +24,161 @@ namespace signals {
virtual size_t size() const = 0;
};
// }}}
// definition : base_signal {{{
template <typename Derived, uint8_t Id>
template <typename Derived>
class base_signal : public signal {
public:
using base_type = base_signal<Derived, Id>;
using base_type = base_signal<Derived>;
explicit base_signal() = default;
virtual ~base_signal() {}
static uint8_t id() {
return Id;
}
virtual size_t size() const override {
return sizeof(Derived);
};
};
// }}}
// definition : value_signal {{{
template <typename Derived, uint8_t Id, typename ValueType>
class value_signal : public base_signal<Derived, Id> {
template <typename Derived, typename ValueType>
class value_signal : public base_signal<Derived> {
public:
using base_type = value_signal<Derived, Id, ValueType>;
using base_type = value_signal<Derived, ValueType>;
using value_type = ValueType;
explicit value_signal() {}
explicit value_signal(ValueType&& data) {
memcpy(m_data, &data, sizeof(data));
template <size_t Size = sizeof(ValueType)>
explicit value_signal(void* data) : m_data(data), m_size(Size) {}
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() {}
const ValueType* operator()() const {
return reinterpret_cast<const ValueType*>(&m_data);
virtual ~value_signal() {
if (m_alloced) {
delete[] static_cast<char*>(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:
char m_data[sizeof(ValueType)];
void* m_data;
size_t m_size;
bool m_alloced{false};
};
// }}}
}
namespace eventqueue {
DEFINE_SIGNAL(1, exit_terminate);
DEFINE_SIGNAL(2, exit_reload);
DEFINE_SIGNAL(3, notify_change);
DEFINE_SIGNAL(4, check_state);
DEFINE_SIGNAL(5, update);
struct exit_terminate : public detail::base_signal<exit_terminate> {
using base_type::base_type;
};
struct exit_reload : public detail::base_signal<exit_reload> {
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 {
DEFINE_VALUE_SIGNAL(20, command, string);
DEFINE_VALUE_SIGNAL(21, hook, string);
DEFINE_VALUE_SIGNAL(22, action, string);
struct command : public detail::value_signal<command, string> {
using base_type::base_type;
};
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 {
DEFINE_SIGNAL(50, tick);
DEFINE_VALUE_SIGNAL(51, button_press, string);
DEFINE_VALUE_SIGNAL(52, visibility_change, bool);
DEFINE_VALUE_SIGNAL(53, dim_window, double);
DEFINE_SIGNAL(54, shade_window);
DEFINE_SIGNAL(55, unshade_window);
struct tick : public detail::base_signal<tick> {
using base_type::base_type;
};
struct button_press : public detail::value_signal<button_press, string> {
using base_type::base_type;
};
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 {
using parser_t = polybar::parser;
DEFINE_VALUE_SIGNAL(70, change_background, uint32_t);
DEFINE_VALUE_SIGNAL(71, change_foreground, uint32_t);
DEFINE_VALUE_SIGNAL(72, change_underline, uint32_t);
DEFINE_VALUE_SIGNAL(73, change_overline, uint32_t);
DEFINE_VALUE_SIGNAL(74, change_font, uint8_t);
DEFINE_VALUE_SIGNAL(75, change_alignment, alignment);
DEFINE_VALUE_SIGNAL(76, offset_pixel, int16_t);
DEFINE_VALUE_SIGNAL(77, attribute_set, attribute);
DEFINE_VALUE_SIGNAL(78, attribute_unset, attribute);
DEFINE_VALUE_SIGNAL(79, attribute_toggle, attribute);
DEFINE_VALUE_SIGNAL(80, action_begin, action);
DEFINE_VALUE_SIGNAL(81, action_end, mousebtn);
DEFINE_VALUE_SIGNAL(82, write_text_ascii, uint16_t);
DEFINE_VALUE_SIGNAL(83, write_text_unicode, uint16_t);
DEFINE_VALUE_SIGNAL(84, write_text_string, parser_t::packet);
struct change_background : public detail::value_signal<change_background, uint32_t> {
using base_type::base_type;
};
struct change_foreground : public detail::value_signal<change_foreground, uint32_t> {
using base_type::base_type;
};
struct change_underline : public detail::value_signal<change_underline, uint32_t> {
using base_type::base_type;
};
struct change_overline : public detail::value_signal<change_overline, uint32_t> {
using base_type::base_type;
};
struct change_font : public detail::value_signal<change_font, uint8_t> {
using base_type::base_type;
};
struct change_alignment : public detail::value_signal<change_alignment, alignment> {
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 "events/signal_receiver.hpp"
#include "utils/factory.hpp"
#include "utils/mixins.hpp"
POLYBAR_NS
@ -55,8 +53,8 @@ class signal_emitter {
protected:
template <typename Signal>
uint8_t id() const {
return Signal::id();
std::type_index id() const {
return typeid(Signal);
}
template <typename Receiver, typename Signal>
@ -70,7 +68,7 @@ class signal_emitter {
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);
}
@ -85,7 +83,7 @@ class signal_emitter {
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 {
auto& prio_map = g_signal_receivers.at(id);
const auto& prio_sink_pair = prio_map.equal_range(d->priority());

View File

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

View File

@ -2,6 +2,8 @@
#include <map>
#include <unordered_map>
#include <typeindex>
#include <typeinfo>
#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

View File

@ -514,7 +514,7 @@ void bar::handle(const evt::leave_notify&) {
if (!m_opts.dimmed) {
m_taskqueue->defer_unique("window-dim", 3s, [&](size_t) {
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) {
m_opts.dimmed = *sig.data() != 1.0;
set_wm_window_opacity(m_connection, m_opts.window, *sig.data() * 0xFFFFFFFF);
m_opts.dimmed = sig.cast() != 1.0;
set_wm_window_opacity(m_connection, m_opts.window, sig.cast() * 0xFFFFFFFF);
m_connection.flush();
return false;
}

View File

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

View File

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

View File

@ -530,7 +530,7 @@ void renderer::debug_hints() {
#endif
bool renderer::on(const change_background& evt) {
const uint32_t color{*evt()};
const uint32_t color{evt.cast()};
if (m_colors[gc::BG] == 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) {
const uint32_t color{*evt()};
const uint32_t color{evt.cast()};
if (m_colors[gc::FG] == 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) {
const uint32_t color{*evt()};
const uint32_t color{evt.cast()};
if (m_colors[gc::UL] == 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) {
const uint32_t color{*evt()};
const uint32_t color{evt.cast()};
if (m_colors[gc::OL] == 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) {
const uint8_t font{*evt()};
const uint8_t font{evt.cast()};
if (m_fontindex == 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) {
auto align = static_cast<const alignment&>(*evt());
auto align = static_cast<const alignment&>(evt.cast());
if (align == m_alignment) {
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) {
shift_content(*evt());
shift_content(evt.cast());
return true;
}
bool renderer::on(const attribute_set& evt) {
m_log.trace_x("renderer: attribute_set(%i, %i)", static_cast<uint8_t>(*evt()), true);
m_attributes |= 1U << static_cast<uint8_t>(*evt());
m_log.trace_x("renderer: attribute_set(%i, %i)", static_cast<uint8_t>(evt.cast()), true);
m_attributes |= 1U << static_cast<uint8_t>(evt.cast());
return true;
}
bool renderer::on(const attribute_unset& evt) {
m_log.trace_x("renderer: attribute_unset(%i, %i)", static_cast<uint8_t>(*evt()), true);
m_attributes &= ~(1U << static_cast<uint8_t>(*evt()));
m_log.trace_x("renderer: attribute_unset(%i, %i)", static_cast<uint8_t>(evt.cast()), true);
m_attributes &= ~(1U << static_cast<uint8_t>(evt.cast()));
return true;
}
bool renderer::on(const attribute_toggle& evt) {
m_log.trace_x("renderer: attribute_toggle(%i)", static_cast<uint8_t>(*evt()));
m_attributes ^= 1U << 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.cast());
return true;
}
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.button = a.button;
action.align = m_alignment;
@ -658,7 +658,7 @@ bool renderer::on(const action_begin& 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};
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) {
const uint16_t data[1]{*evt()};
const uint16_t data[1]{evt.cast()};
draw_textstring(data, 1);
return true;
}
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);
return true;
}
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);
return true;
}

View File

@ -1,4 +1,5 @@
#include "events/signal_emitter.hpp"
#include "utils/factory.hpp"
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: Set client mapped");
find_client(evt->window)->mapped(true);
if (mapped_clients() > m_opts.configured_slots) {
size_t clientcount{mapped_clients()};
if (clientcount > m_opts.configured_slots) {
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)) {
m_log.trace("tray: Received unmap_notify");
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.
*/
bool tray_manager::on(const visibility_change& evt) {
bool visible{*evt()};
bool visible{evt.cast()};
size_t clients{mapped_clients()};
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) {
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();
}
// let the event bubble