diff --git a/src/framework/core/eventdispatcher.cpp b/src/framework/core/eventdispatcher.cpp index 020f1e35b4..abc2830816 100644 --- a/src/framework/core/eventdispatcher.cpp +++ b/src/framework/core/eventdispatcher.cpp @@ -27,8 +27,8 @@ #include "timer.h" EventDispatcher g_dispatcher, g_textDispatcher, g_mainDispatcher; -std::thread::id g_mainThreadId = std::this_thread::get_id(); -std::thread::id g_eventThreadId; +int16_t g_mainThreadId = EventDispatcher::getThreadId(); +int16_t g_eventThreadId = -1; void EventDispatcher::init() { m_threads.reserve(g_asyncDispatcher.getNumberOfThreads() + 1); @@ -45,6 +45,8 @@ void EventDispatcher::shutdown() } while (!m_eventList.empty()); m_scheduledEventList.clear(); + m_deferEventList.clear(); + m_threads.clear(); m_disabled = true; } @@ -54,6 +56,7 @@ void EventDispatcher::poll() mergeEvents(); executeEvents(); executeScheduledEvents(); + executeDeferEvents(); } void EventDispatcher::startEvent(const ScheduledEventPtr& event) @@ -100,7 +103,7 @@ EventPtr EventDispatcher::addEvent(const std::function& callback) if (m_disabled) return std::make_shared(nullptr); - if (&g_mainDispatcher == this && g_mainThreadId == std::this_thread::get_id()) { + if (&g_mainDispatcher == this && g_mainThreadId == getThreadId()) { callback(); return std::make_shared(nullptr); } @@ -110,17 +113,42 @@ EventPtr EventDispatcher::addEvent(const std::function& callback) return thread->events.emplace_back(std::make_shared(callback)); } +void EventDispatcher::deferEvent(const std::function& callback) { + if (m_disabled) + return; + + const auto& thread = getThreadTask(); + std::scoped_lock lock(thread->mutex); + thread->deferEvents.emplace_back(callback); +} + void EventDispatcher::executeEvents() { if (m_eventList.empty()) { return; } - for (const auto& event : m_eventList) { + for (const auto& event : m_eventList) event->execute(); - } + m_eventList.clear(); } +void EventDispatcher::executeDeferEvents() { + do { + for (auto& event : m_deferEventList) + event.execute(); + m_deferEventList.clear(); + + for (const auto& thread : m_threads) { + std::scoped_lock lock(thread->mutex); + if (!thread->deferEvents.empty()) { + m_deferEventList.insert(m_deferEventList.end(), make_move_iterator(thread->deferEvents.begin()), make_move_iterator(thread->deferEvents.end())); + thread->deferEvents.clear(); + } + } + } while (!m_deferEventList.empty()); +} + void EventDispatcher::executeScheduledEvents() { auto& threadScheduledTasks = getThreadTask()->scheduledEventList; diff --git a/src/framework/core/eventdispatcher.h b/src/framework/core/eventdispatcher.h index c00853f45e..a996f56186 100644 --- a/src/framework/core/eventdispatcher.h +++ b/src/framework/core/eventdispatcher.h @@ -40,20 +40,12 @@ class EventDispatcher void poll(); EventPtr addEvent(const std::function& callback); + void deferEvent(const std::function& callback); ScheduledEventPtr scheduleEvent(const std::function& callback, int delay); ScheduledEventPtr cycleEvent(const std::function& callback, int delay); void startEvent(const ScheduledEventPtr& event); -private: - inline void mergeEvents(); - inline void executeEvents(); - inline void executeScheduledEvents(); - - const auto& getThreadTask() const { - return m_threads[getThreadId()]; - } - static int16_t getThreadId() { static std::atomic_int16_t lastId = -1; thread_local static int16_t id = -1; @@ -66,6 +58,16 @@ class EventDispatcher return id; }; +private: + inline void mergeEvents(); + inline void executeEvents(); + inline void executeDeferEvents(); + inline void executeScheduledEvents(); + + const auto& getThreadTask() const { + return m_threads[getThreadId()]; + } + size_t m_pollEventsSize{}; bool m_disabled{ false }; @@ -78,6 +80,7 @@ class EventDispatcher } std::vector events; + std::vector deferEvents; std::vector scheduledEventList; std::mutex mutex; }; @@ -85,9 +88,10 @@ class EventDispatcher // Main Events std::vector m_eventList; + std::vector m_deferEventList; phmap::btree_multiset m_scheduledEventList; }; extern EventDispatcher g_dispatcher, g_textDispatcher, g_mainDispatcher; -extern std::thread::id g_mainThreadId; -extern std::thread::id g_eventThreadId; +extern int16_t g_mainThreadId; +extern int16_t g_eventThreadId; diff --git a/src/framework/core/graphicalapplication.cpp b/src/framework/core/graphicalapplication.cpp index 62a7a02c3b..b0fb10a9b1 100644 --- a/src/framework/core/graphicalapplication.cpp +++ b/src/framework/core/graphicalapplication.cpp @@ -182,7 +182,7 @@ void GraphicalApplication::run() // THREAD - POOL & MAP g_asyncDispatcher.dispatch([&] { - g_eventThreadId = std::this_thread::get_id(); + g_eventThreadId = EventDispatcher::getThreadId(); while (!m_stopping) { poll(); diff --git a/src/framework/core/logger.cpp b/src/framework/core/logger.cpp index 2814964b84..94af11d0bf 100644 --- a/src/framework/core/logger.cpp +++ b/src/framework/core/logger.cpp @@ -62,7 +62,7 @@ void Logger::log(Fw::LogLevel level, const std::string_view message) if (s_ignoreLogs) return; - if (g_eventThreadId != std::this_thread::get_id()) { + if (g_eventThreadId > -1 && g_eventThreadId != EventDispatcher::getThreadId()) { g_dispatcher.addEvent([this, level, msg = std::string{ message }] { log(level, msg); }); @@ -110,7 +110,7 @@ void Logger::log(Fw::LogLevel level, const std::string_view message) void Logger::logFunc(Fw::LogLevel level, const std::string_view message, const std::string_view prettyFunction) { - if (g_eventThreadId != std::this_thread::get_id()) { + if (g_eventThreadId > -1 && g_eventThreadId != EventDispatcher::getThreadId()) { g_dispatcher.addEvent([this, level, msg = std::string{ message }, prettyFunction = std::string{ prettyFunction }] { logFunc(level, msg, prettyFunction); }); diff --git a/src/framework/ui/uigridlayout.cpp b/src/framework/ui/uigridlayout.cpp index bd060e8eda..7292b9b5b3 100644 --- a/src/framework/ui/uigridlayout.cpp +++ b/src/framework/ui/uigridlayout.cpp @@ -112,7 +112,7 @@ bool UIGridLayout::internalUpdate() if (m_fitChildren && preferredHeight != parentWidget->getHeight()) { // must set the preferred height later - g_dispatcher.addEvent([=] { + g_dispatcher.deferEvent([=] { parentWidget->setHeight(preferredHeight); }); } diff --git a/src/framework/ui/uihorizontallayout.cpp b/src/framework/ui/uihorizontallayout.cpp index 01d05db561..f634522802 100644 --- a/src/framework/ui/uihorizontallayout.cpp +++ b/src/framework/ui/uihorizontallayout.cpp @@ -91,7 +91,7 @@ bool UIHorizontalLayout::internalUpdate() if (m_fitChildren && preferredWidth != parentWidget->getWidth()) { // must set the preferred width later - g_dispatcher.addEvent([=] { + g_dispatcher.deferEvent([=] { parentWidget->setWidth(preferredWidth); }); } diff --git a/src/framework/ui/uilayout.cpp b/src/framework/ui/uilayout.cpp index 161c32fb11..8e9b17501d 100644 --- a/src/framework/ui/uilayout.cpp +++ b/src/framework/ui/uilayout.cpp @@ -64,7 +64,7 @@ void UILayout::updateLater() return; auto self = static_self_cast(); - g_dispatcher.addEvent([self] { + g_dispatcher.deferEvent([self] { self->m_updateScheduled = false; self->update(); }); diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp index 72fb3a8235..7cc7995fc3 100644 --- a/src/framework/ui/uimanager.cpp +++ b/src/framework/ui/uimanager.cpp @@ -259,7 +259,7 @@ void UIManager::updateHoveredWidget(bool now) func(); else { m_hoverUpdateScheduled = true; - g_dispatcher.addEvent(func); + g_dispatcher.deferEvent(func); } } @@ -600,4 +600,4 @@ UIWidgetPtr UIManager::createWidgetFromOTML(const OTMLNodePtr& widgetNode, const widget->callLuaField("onSetup"); return widget; -} +} \ No newline at end of file diff --git a/src/framework/ui/uiverticallayout.cpp b/src/framework/ui/uiverticallayout.cpp index 2dbeb56cdd..0e80a0a159 100644 --- a/src/framework/ui/uiverticallayout.cpp +++ b/src/framework/ui/uiverticallayout.cpp @@ -93,7 +93,7 @@ bool UIVerticalLayout::internalUpdate() if (m_fitChildren && preferredHeight != parentWidget->getHeight()) { // must set the preferred width later - g_dispatcher.addEvent([=] { + g_dispatcher.deferEvent([=] { parentWidget->setHeight(preferredHeight); }); } diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 80b0d96935..60bf2d8f7c 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -133,7 +133,7 @@ void UIWidget::drawChildren(const Rect& visibleRect, DrawPoolType drawPane) // debug draw box if (g_ui.isDrawingDebugBoxes() && drawPane == DrawPoolType::FOREGROUND) { - if(child->isFocused()) + if (child->isFocused()) g_drawPool.addBoundingRect(child->getRect(), Color::yellow); else g_drawPool.addBoundingRect(child->getRect(), Color::green); @@ -1046,7 +1046,7 @@ bool UIWidget::setRect(const Rect& rect) // avoid massive update events if (!hasProp(PropUpdateEventScheduled)) { auto self = static_self_cast(); - g_dispatcher.addEvent([self, oldRect] { + g_dispatcher.deferEvent([self, oldRect] { self->setProp(PropUpdateEventScheduled, false); const auto& rect = self->getRect(); if (oldRect != rect) { @@ -1625,7 +1625,7 @@ void UIWidget::updateStyle() if (hasProp(PropLoadingStyle) && !hasProp(PropUpdateStyleScheduled)) { UIWidgetPtr self = static_self_cast(); - g_dispatcher.addEvent([self] { + g_dispatcher.deferEvent([self] { self->setProp(PropUpdateStyleScheduled, false); self->updateStyle(); }); @@ -1819,7 +1819,7 @@ bool UIWidget::onDoubleClick(const Point& mousePos) return callLuaField("onDoubleClick", mousePos); } -UIWidgetPtr UIWidget::getHoveredChild() +UIWidgetPtr UIWidget::getHoveredChild() { const auto& hovered = g_ui.getHoveredWidget(); return hovered ? getChildById(hovered->getId()) : nullptr; @@ -1958,7 +1958,7 @@ void UIWidget::move(int x, int y) { if (!hasProp(PropUpdatingMove)) { setProp(PropUpdatingMove, true); - g_dispatcher.addEvent([self = static_self_cast()] { + g_dispatcher.deferEvent([self = static_self_cast()] { const auto rect = self->m_rect; self->m_rect = {}; // force update self->setRect(rect); @@ -1980,4 +1980,4 @@ void UIWidget::setShader(const std::string_view name) { }); } -void UIWidget::repaint() { g_app.repaint(); } +void UIWidget::repaint() { g_app.repaint(); } \ No newline at end of file diff --git a/src/framework/ui/uiwidgetbasestyle.cpp b/src/framework/ui/uiwidgetbasestyle.cpp index 2f76132880..e07533de77 100644 --- a/src/framework/ui/uiwidgetbasestyle.cpp +++ b/src/framework/ui/uiwidgetbasestyle.cpp @@ -410,4 +410,4 @@ void UIWidget::setIcon(const std::string& iconFile) repaint(); }); -} +} \ No newline at end of file