From cc58ea29bc823b0faac2c144a486801a6254576c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 15 Apr 2024 19:44:21 +0300 Subject: [PATCH] world converter threading --- src/assets/AssetsLoader.cpp | 4 +- src/files/WorldConverter.cpp | 98 ++++++++++++++++++++++---- src/files/WorldConverter.h | 44 +++++------- src/files/WorldRegions.cpp | 2 +- src/frontend/menu/menu.cpp | 12 ++-- src/frontend/menu/menu_settings.cpp | 3 +- src/graphics/render/ChunksRenderer.cpp | 2 +- src/graphics/render/ChunksRenderer.h | 2 +- src/interfaces/Task.h | 2 +- src/util/ThreadPool.h | 16 ++--- 10 files changed, 122 insertions(+), 63 deletions(-) diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index e1b550c5..85dc5641 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -208,7 +208,7 @@ const ResPaths* AssetsLoader::getPaths() const { return paths; } -class LoaderWorker : public util::Worker, assetload::postfunc> { +class LoaderWorker : public util::Worker { AssetsLoader* loader; public: LoaderWorker(AssetsLoader* loader) : loader(loader) { @@ -222,7 +222,7 @@ public: std::shared_ptr AssetsLoader::startTask(runnable onDone) { auto pool = std::make_shared< - util::ThreadPool, assetload::postfunc> + util::ThreadPool >( "assets-loader-pool", [=](){return std::make_shared(this);}, diff --git a/src/files/WorldConverter.cpp b/src/files/WorldConverter.cpp index 045faf4e..8c81b1d8 100644 --- a/src/files/WorldConverter.cpp +++ b/src/files/WorldConverter.cpp @@ -11,16 +11,29 @@ #include "../content/ContentLUT.h" #include "../objects/Player.h" #include "../debug/Logger.h" +#include "../util/ThreadPool.h" namespace fs = std::filesystem; static debug::Logger logger("world-converter"); +class ConverterWorker : public util::Worker { + std::shared_ptr converter; +public: + ConverterWorker(std::shared_ptr converter) + : converter(converter) {} + + int operator()(const std::shared_ptr& task) override { + converter->convert(*task); + return 0; + } +}; + WorldConverter::WorldConverter( fs::path folder, const Content* content, std::shared_ptr lut -) : wfile(std::make_unique(folder, DebugSettings {})), +) : wfile(std::make_unique(folder)), lut(lut), content(content) { @@ -38,7 +51,40 @@ WorldConverter::WorldConverter( WorldConverter::~WorldConverter() { } -void WorldConverter::convertRegion(fs::path file) { +std::shared_ptr WorldConverter::startTask( + fs::path folder, + const Content* content, + std::shared_ptr lut, + runnable onDone, + bool multithreading +) { + auto converter = std::make_shared(folder, content, lut); + if (!multithreading) { + converter->setOnComplete([=]() { + converter->write(); + onDone(); + }); + return converter; + } + auto pool = std::make_shared>( + "converter-pool", + [=](){return std::make_shared(converter);}, + [=](int& _) {} + ); + while (!converter->tasks.empty()) { + const convert_task& task = converter->tasks.front(); + auto ptr = std::make_shared(task); + pool->enqueueJob(ptr); + converter->tasks.pop(); + } + pool->setOnComplete([=]() { + converter->write(); + onDone(); + }); + return pool; +} + +void WorldConverter::convertRegion(fs::path file) const { int x, z; std::string name = file.stem().string(); if (!WorldRegions::parseRegionFilename(name, x, z)) { @@ -54,13 +100,27 @@ void WorldConverter::convertRegion(fs::path file) { }); } -void WorldConverter::convertPlayer(fs::path file) { +void WorldConverter::convertPlayer(fs::path file) const { logger.info() << "converting player " << file.u8string(); auto map = files::read_json(file); Player::convert(map.get(), lut.get()); files::write_json(file, map.get()); } +void WorldConverter::convert(convert_task task) const { + if (!fs::is_regular_file(task.file)) + return; + + switch (task.type) { + case convert_task_type::region: + convertRegion(task.file); + break; + case convert_task_type::player: + convertPlayer(task.file); + break; + } +} + void WorldConverter::convertNext() { if (tasks.empty()) { throw std::runtime_error("no more regions to convert"); @@ -69,18 +129,28 @@ void WorldConverter::convertNext() { tasks.pop(); tasksDone++; - if (!fs::is_regular_file(task.file)) - return; - switch (task.type) { - case convert_task_type::region: - convertRegion(task.file); - break; - case convert_task_type::player: - convertPlayer(task.file); - break; + convert(task); +} + +void WorldConverter::setOnComplete(runnable callback) { + this->onComplete = callback; +} + +void WorldConverter::update() { + convertNext(); + if (onComplete && tasks.empty()) { + onComplete(); } } +void WorldConverter::terminate() { + tasks = {}; +} + +bool WorldConverter::isActive() const { + return !tasks.empty(); +} + void WorldConverter::write() { logger.info() << "writing world"; wfile->write(nullptr, content); @@ -92,8 +162,8 @@ void WorldConverter::waitForEnd() { } } -uint WorldConverter::getWorkRemaining() const { - return tasks.size(); +uint WorldConverter::getWorkTotal() const { + return tasks.size() + tasksDone; } uint WorldConverter::getWorkDone() const { diff --git a/src/files/WorldConverter.h b/src/files/WorldConverter.h index 481d323d..9bc3f52a 100644 --- a/src/files/WorldConverter.h +++ b/src/files/WorldConverter.h @@ -32,41 +32,35 @@ class WorldConverter : public Task { runnable onComplete; uint tasksDone = 0; - void convertPlayer(fs::path file); - void convertRegion(fs::path file); + void convertPlayer(fs::path file) const; + void convertRegion(fs::path file) const; public: WorldConverter( - fs::path folder, const Content* content, + fs::path folder, + const Content* content, std::shared_ptr lut ); ~WorldConverter(); + void convert(convert_task task) const; void convertNext(); - - void setOnComplete(runnable callback) { - this->onComplete = callback; - } - - void update() override { - convertNext(); - if (onComplete && tasks.empty()) { - onComplete(); - } - } - - void terminate() override { - tasks = {}; - } - - bool isActive() const override { - return !tasks.empty(); - } - - void waitForEnd() override; + void setOnComplete(runnable callback); void write(); - uint getWorkRemaining() const override; + void update() override; + void terminate() override; + bool isActive() const override; + void waitForEnd() override; + uint getWorkTotal() const override; uint getWorkDone() const override; + + static std::shared_ptr startTask( + fs::path folder, + const Content* content, + std::shared_ptr lut, + runnable onDone, + bool multithreading + ); }; #endif // FILES_WORLD_CONVERTER_H_ diff --git a/src/files/WorldRegions.cpp b/src/files/WorldRegions.cpp index 9d139de7..9be46960 100644 --- a/src/files/WorldRegions.cpp +++ b/src/files/WorldRegions.cpp @@ -207,7 +207,7 @@ ubyte* WorldRegions::getData( std::shared_ptr WorldRegions::useRegFile(glm::ivec3 coord) { auto* file = openRegFiles[coord].get(); file->inUse = true; - return std::shared_ptr(openRegFiles[coord].get(), [this](regfile* ptr) { + return std::shared_ptr(file, [this](regfile* ptr) { ptr->inUse = false; regFilesCv.notify_one(); }); diff --git a/src/frontend/menu/menu.cpp b/src/frontend/menu/menu.cpp index d06c677e..889a3739 100644 --- a/src/frontend/menu/menu.cpp +++ b/src/frontend/menu/menu.cpp @@ -116,7 +116,7 @@ void show_process_panel(Engine* engine, std::shared_ptr task, std::wstring auto label = std::make_shared