diff --git a/src/client/lightview.cpp b/src/client/lightview.cpp index 94a9de6c7c..e8d135c9f2 100644 --- a/src/client/lightview.cpp +++ b/src/client/lightview.cpp @@ -26,20 +26,13 @@ #include "spritemanager.h" #include +#include #include LightView::LightView(const Size& size, const uint16_t tileSize) : m_pool(g_drawPool.get(DrawPoolType::LIGHT)) { g_mainDispatcher.addEvent([this, size] { m_texture = std::make_shared(size); m_texture->setSmooth(true); - - m_thread = std::thread([this]() { - std::unique_lock lock(m_pool->getMutex()); - m_condition.wait(lock, [this]() -> bool { - updatePixels(); - return m_texture == nullptr; - }); - }); }); g_drawPool.use(DrawPoolType::LIGHT); @@ -119,7 +112,9 @@ void LightView::draw(const Rect& dest, const Rect& src) std::scoped_lock l(m_pool->getMutex()); if (++m_currentLightData > 1) m_currentLightData = 0; - m_condition.notify_one(); + g_asyncDispatcher.dispatch([this] { + updatePixels(); + }); } auto& lightData = m_lightData[m_currentLightData]; @@ -144,6 +139,8 @@ void LightView::updateCoords(const Rect& dest, const Rect& src) { } void LightView::updatePixels() { + std::scoped_lock l(m_pool->getMutex()); + const auto& lightData = m_lightData[m_currentLightData ? 0 : 1]; const size_t lightSize = lightData.lights.size(); diff --git a/src/client/lightview.h b/src/client/lightview.h index 9e1670df5f..fb7ae444c8 100644 --- a/src/client/lightview.h +++ b/src/client/lightview.h @@ -26,14 +26,12 @@ #include #include "declarations.h" #include "thingtype.h" -#include -#include class LightView : public LuaObject { public: LightView(const Size& size, const uint16_t tileSize); - ~LightView() { m_texture = nullptr; m_condition.notify_one(); m_thread.join(); } + ~LightView() { m_texture = nullptr; } void resize(const Size& size, uint16_t tileSize); void draw(const Rect& dest, const Rect& src); @@ -85,9 +83,5 @@ class LightView : public LuaObject TexturePtr m_texture; LightData m_lightData[2]; std::atomic_uint8_t m_currentLightData{ 0 }; - - std::thread m_thread; - std::condition_variable m_condition; - std::vector m_pixels; }; diff --git a/src/framework/core/asyncdispatcher.cpp b/src/framework/core/asyncdispatcher.cpp index 785b3729fd..ebab39d6f6 100644 --- a/src/framework/core/asyncdispatcher.cpp +++ b/src/framework/core/asyncdispatcher.cpp @@ -20,61 +20,34 @@ * THE SOFTWARE. */ -#include - #include "asyncdispatcher.h" AsyncDispatcher g_asyncDispatcher; void AsyncDispatcher::init(uint8_t maxThreads) { - if (maxThreads != 0) - m_maxThreads = maxThreads; + if (maxThreads == 0) + maxThreads = 6; // -2 = Main Thread and Map Thread - int_fast8_t threads = std::clamp(std::thread::hardware_concurrency() - 2, 1, m_maxThreads); + int_fast8_t threads = std::clamp(std::thread::hardware_concurrency() - 2, 1, maxThreads); for (; --threads >= 0;) - spawn_thread(); + m_threads.emplace_back([this] { m_ioService.run(); }); } -void AsyncDispatcher::terminate() -{ - stop(); - m_tasks.clear(); -} - -void AsyncDispatcher::spawn_thread() -{ - m_running = true; - m_threads.emplace_back([this] { exec_loop(); }); -} +void AsyncDispatcher::terminate() { stop(); } void AsyncDispatcher::stop() { - m_mutex.lock(); - m_running = false; - m_condition.notify_all(); - m_mutex.unlock(); - for (std::thread& thread : m_threads) - thread.join(); - m_threads.clear(); -}; - -void AsyncDispatcher::exec_loop() -{ - std::unique_lock lock(m_mutex); - while (true) { - while (m_tasks.empty() && m_running) - m_condition.wait(lock); - - if (!m_running) - return; + if (m_ioService.stopped()) { + return; + } - std::function task = m_tasks.front(); - m_tasks.pop_front(); + m_ioService.stop(); - lock.unlock(); - task(); - lock.lock(); + for (std::size_t i = 0; i < m_threads.size(); i++) { + if (m_threads[i].joinable()) { + m_threads[i].join(); + } } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/framework/core/asyncdispatcher.h b/src/framework/core/asyncdispatcher.h index 41676fae5a..604d98ef75 100644 --- a/src/framework/core/asyncdispatcher.h +++ b/src/framework/core/asyncdispatcher.h @@ -22,8 +22,8 @@ #pragma once -#include -#include +#include +#include class AsyncDispatcher { @@ -31,40 +31,32 @@ class AsyncDispatcher void init(uint8_t maxThreads = 0); void terminate(); - void spawn_thread(); void stop(); template std::shared_future> schedule(const F& task) { - std::scoped_lock lock(m_mutex); const auto& prom = std::make_shared>>(); - m_tasks.push_back([=] { prom->set_value(task()); }); - m_condition.notify_all(); + dispatch([=] { prom->set_value(task()); }); return std::shared_future>(prom->get_future()); } - void dispatch(const std::function& f) + void dispatch(std::function&& f) { - std::scoped_lock lock(m_mutex); - m_tasks.push_back(f); - m_condition.notify_all(); + asio::post(m_ioService, [this, f = std::move(f)]() { + if (!m_ioService.stopped()) + f(); + }); } inline auto getNumberOfThreads() const { return m_threads.size(); } -protected: - void exec_loop(); - private: - std::list> m_tasks; - std::list m_threads; - std::mutex m_mutex; - std::condition_variable m_condition; - bool m_running{ false }; - uint8_t m_maxThreads{ 6 }; + asio::io_context m_ioService; + std::vector m_threads; + asio::io_context::work m_work{ m_ioService }; }; extern AsyncDispatcher g_asyncDispatcher; diff --git a/src/framework/core/graphicalapplication.cpp b/src/framework/core/graphicalapplication.cpp index 897d7ad8bb..fbae7ee5c4 100644 --- a/src/framework/core/graphicalapplication.cpp +++ b/src/framework/core/graphicalapplication.cpp @@ -139,8 +139,6 @@ void GraphicalApplication::run() const auto& txt = g_drawPool.get(DrawPoolType::TEXT); const auto& map = g_drawPool.get(DrawPoolType::MAP); - std::condition_variable foreCondition, txtCondition; - // clang c++20 dont support jthread std::thread t1([&]() { g_eventThreadId = std::this_thread::get_id(); @@ -157,15 +155,28 @@ void GraphicalApplication::run() continue; }*/ - if (foreground->canRepaint()) - foreCondition.notify_one(); + if (foreground->canRepaint()) { + g_asyncDispatcher.dispatch([this, &foreground] { + std::scoped_lock l(foreground->getMutex()); + g_ui.render(DrawPoolType::FOREGROUND); + }); + } if (g_game.isOnline()) { if (!g_ui.m_mapWidget) g_ui.m_mapWidget = g_ui.getRootWidget()->recursiveGetChildById("gameMapPanel")->static_self_cast(); - if (txt->canRepaint() || foreground_tile->canRepaint()) - txtCondition.notify_one(); + if (txt->canRepaint() || foreground_tile->canRepaint()) { + g_asyncDispatcher.dispatch([this, &txt] { + std::scoped_lock l(txt->getMutex()); + g_textDispatcher.poll(); + + if (g_ui.m_mapWidget) { + g_ui.m_mapWidget->drawSelf(DrawPoolType::TEXT); + g_ui.m_mapWidget->drawSelf(DrawPoolType::FOREGROUND_TILE); + } + }); + } { std::scoped_lock l(map->getMutex()); @@ -175,31 +186,6 @@ void GraphicalApplication::run() stdext::millisleep(1); } - - foreCondition.notify_one(); - txtCondition.notify_one(); - }); - - std::thread t2([&]() { - std::unique_lock lock(foreground->getMutex()); - foreCondition.wait(lock, [&]() -> bool { - g_ui.render(DrawPoolType::FOREGROUND); - return m_stopping; - }); - }); - - std::thread t3([&]() { - std::unique_lock lock(txt->getMutex()); - txtCondition.wait(lock, [&]() -> bool { - g_textDispatcher.poll(); - - if (g_ui.m_mapWidget) { - g_ui.m_mapWidget->drawSelf(DrawPoolType::TEXT); - g_ui.m_mapWidget->drawSelf(DrawPoolType::FOREGROUND_TILE); - } - - return m_stopping; - }); }); m_running = true; @@ -219,8 +205,6 @@ void GraphicalApplication::run() } t1.join(); - t2.join(); - t3.join(); m_stopping = false; m_running = false;