diff --git a/include/components/controller.hpp b/include/components/controller.hpp index 646f1057..bcf9741a 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -64,7 +64,7 @@ class controller : public signal_receiver m_notifier{nullptr}; + /** + * Notification data for the controller. + * + * Triggers, potentially from other threads, update this structure and notify the controller through m_notifier. + */ + notifications_t m_notifications{}; + + /** + * \brief Protected m_notifications. + * + * All accesses to m_notifications must hold this mutex. + */ + std::mutex m_notification_mutex{}; + /** * \brief Destination path of generated snapshot */ @@ -119,11 +143,6 @@ class controller : public signal_receiver(input_data); + std::unique_lock guard(m_notification_mutex); + + if (m_notifications.inputdata.empty()) { + m_notifications.inputdata = std::forward(input_data); + // TODO create function for this UV(uv_async_send, m_notifier.get()); + } else { + m_log.trace("controller: Swallowing input event (pending data)"); } } void controller::trigger_quit(bool reload) { - g_terminate = 1; - g_reload = reload; + std::unique_lock guard(m_notification_mutex); + m_notifications.quit = true; + m_notifications.reload = m_notifications.reload || reload; // TODO create function for this UV(uv_async_send, m_notifier.get()); } void controller::trigger_update(bool force) { - if (force) { - g_force_update = 1; - } else { - g_update = 1; - } + std::unique_lock guard(m_notification_mutex); + m_notifications.update = true; + m_notifications.force_update = m_notifications.force_update || force; // TODO this isn't really safe if (m_notifier) { + // TODO create function for this UV(uv_async_send, m_notifier.get()); } } void controller::stop(bool reload) { - g_terminate = 1; g_reload = reload; eloop->stop(); } @@ -220,23 +217,27 @@ void controller::confwatch_handler(const char* filename, int, int) { } void controller::notifier_handler() { - if (g_terminate) { + notifications_t data{}; + + { + std::unique_lock guard(m_notification_mutex); + std::swap(m_notifications, data); + } + + if (data.quit) { + // TODO store this in the instance + g_reload = data.reload; eloop->stop(); return; } - if (!m_inputdata.empty()) { - process_inputdata(); + if (!data.inputdata.empty()) { + process_inputdata(std::move(data.inputdata)); } - if (g_force_update) { - process_update(true); - } else if (g_update) { - process_update(false); + if (data.update) { + process_update(data.force_update); } - - g_update = 0; - g_force_update = 0; } static void ipc_alloc_cb(uv_handle_t*, size_t, uv_buf_t* buf) { @@ -484,14 +485,7 @@ bool controller::forward_action(const actions_util::action& action_triple) { /** * Process stored input data */ -void controller::process_inputdata() { - if (m_inputdata.empty()) { - return; - } - - const string cmd = std::move(m_inputdata); - m_inputdata = string{}; - +void controller::process_inputdata(string&& cmd) { m_log.trace("controller: Processing inputdata: %s", cmd); // Every command that starts with '#' is considered an action string.