world converter threading
This commit is contained in:
parent
ab110dcdf5
commit
cc58ea29bc
@ -208,7 +208,7 @@ const ResPaths* AssetsLoader::getPaths() const {
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoaderWorker : public util::Worker<std::shared_ptr<aloader_entry>, assetload::postfunc> {
|
class LoaderWorker : public util::Worker<aloader_entry, assetload::postfunc> {
|
||||||
AssetsLoader* loader;
|
AssetsLoader* loader;
|
||||||
public:
|
public:
|
||||||
LoaderWorker(AssetsLoader* loader) : loader(loader) {
|
LoaderWorker(AssetsLoader* loader) : loader(loader) {
|
||||||
@ -222,7 +222,7 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<Task> AssetsLoader::startTask(runnable onDone) {
|
std::shared_ptr<Task> AssetsLoader::startTask(runnable onDone) {
|
||||||
auto pool = std::make_shared<
|
auto pool = std::make_shared<
|
||||||
util::ThreadPool<std::shared_ptr<aloader_entry>, assetload::postfunc>
|
util::ThreadPool<aloader_entry, assetload::postfunc>
|
||||||
>(
|
>(
|
||||||
"assets-loader-pool",
|
"assets-loader-pool",
|
||||||
[=](){return std::make_shared<LoaderWorker>(this);},
|
[=](){return std::make_shared<LoaderWorker>(this);},
|
||||||
|
|||||||
@ -11,16 +11,29 @@
|
|||||||
#include "../content/ContentLUT.h"
|
#include "../content/ContentLUT.h"
|
||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
#include "../debug/Logger.h"
|
#include "../debug/Logger.h"
|
||||||
|
#include "../util/ThreadPool.h"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
static debug::Logger logger("world-converter");
|
static debug::Logger logger("world-converter");
|
||||||
|
|
||||||
|
class ConverterWorker : public util::Worker<convert_task, int> {
|
||||||
|
std::shared_ptr<WorldConverter> converter;
|
||||||
|
public:
|
||||||
|
ConverterWorker(std::shared_ptr<WorldConverter> converter)
|
||||||
|
: converter(converter) {}
|
||||||
|
|
||||||
|
int operator()(const std::shared_ptr<convert_task>& task) override {
|
||||||
|
converter->convert(*task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
WorldConverter::WorldConverter(
|
WorldConverter::WorldConverter(
|
||||||
fs::path folder,
|
fs::path folder,
|
||||||
const Content* content,
|
const Content* content,
|
||||||
std::shared_ptr<ContentLUT> lut
|
std::shared_ptr<ContentLUT> lut
|
||||||
) : wfile(std::make_unique<WorldFiles>(folder, DebugSettings {})),
|
) : wfile(std::make_unique<WorldFiles>(folder)),
|
||||||
lut(lut),
|
lut(lut),
|
||||||
content(content)
|
content(content)
|
||||||
{
|
{
|
||||||
@ -38,7 +51,40 @@ WorldConverter::WorldConverter(
|
|||||||
WorldConverter::~WorldConverter() {
|
WorldConverter::~WorldConverter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldConverter::convertRegion(fs::path file) {
|
std::shared_ptr<Task> WorldConverter::startTask(
|
||||||
|
fs::path folder,
|
||||||
|
const Content* content,
|
||||||
|
std::shared_ptr<ContentLUT> lut,
|
||||||
|
runnable onDone,
|
||||||
|
bool multithreading
|
||||||
|
) {
|
||||||
|
auto converter = std::make_shared<WorldConverter>(folder, content, lut);
|
||||||
|
if (!multithreading) {
|
||||||
|
converter->setOnComplete([=]() {
|
||||||
|
converter->write();
|
||||||
|
onDone();
|
||||||
|
});
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
auto pool = std::make_shared<util::ThreadPool<convert_task, int>>(
|
||||||
|
"converter-pool",
|
||||||
|
[=](){return std::make_shared<ConverterWorker>(converter);},
|
||||||
|
[=](int& _) {}
|
||||||
|
);
|
||||||
|
while (!converter->tasks.empty()) {
|
||||||
|
const convert_task& task = converter->tasks.front();
|
||||||
|
auto ptr = std::make_shared<convert_task>(task);
|
||||||
|
pool->enqueueJob(ptr);
|
||||||
|
converter->tasks.pop();
|
||||||
|
}
|
||||||
|
pool->setOnComplete([=]() {
|
||||||
|
converter->write();
|
||||||
|
onDone();
|
||||||
|
});
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldConverter::convertRegion(fs::path file) const {
|
||||||
int x, z;
|
int x, z;
|
||||||
std::string name = file.stem().string();
|
std::string name = file.stem().string();
|
||||||
if (!WorldRegions::parseRegionFilename(name, x, z)) {
|
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();
|
logger.info() << "converting player " << file.u8string();
|
||||||
auto map = files::read_json(file);
|
auto map = files::read_json(file);
|
||||||
Player::convert(map.get(), lut.get());
|
Player::convert(map.get(), lut.get());
|
||||||
files::write_json(file, map.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() {
|
void WorldConverter::convertNext() {
|
||||||
if (tasks.empty()) {
|
if (tasks.empty()) {
|
||||||
throw std::runtime_error("no more regions to convert");
|
throw std::runtime_error("no more regions to convert");
|
||||||
@ -69,16 +129,26 @@ void WorldConverter::convertNext() {
|
|||||||
tasks.pop();
|
tasks.pop();
|
||||||
tasksDone++;
|
tasksDone++;
|
||||||
|
|
||||||
if (!fs::is_regular_file(task.file))
|
convert(task);
|
||||||
return;
|
|
||||||
switch (task.type) {
|
|
||||||
case convert_task_type::region:
|
|
||||||
convertRegion(task.file);
|
|
||||||
break;
|
|
||||||
case convert_task_type::player:
|
|
||||||
convertPlayer(task.file);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
void WorldConverter::write() {
|
||||||
@ -92,8 +162,8 @@ void WorldConverter::waitForEnd() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint WorldConverter::getWorkRemaining() const {
|
uint WorldConverter::getWorkTotal() const {
|
||||||
return tasks.size();
|
return tasks.size() + tasksDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint WorldConverter::getWorkDone() const {
|
uint WorldConverter::getWorkDone() const {
|
||||||
|
|||||||
@ -32,41 +32,35 @@ class WorldConverter : public Task {
|
|||||||
runnable onComplete;
|
runnable onComplete;
|
||||||
uint tasksDone = 0;
|
uint tasksDone = 0;
|
||||||
|
|
||||||
void convertPlayer(fs::path file);
|
void convertPlayer(fs::path file) const;
|
||||||
void convertRegion(fs::path file);
|
void convertRegion(fs::path file) const;
|
||||||
public:
|
public:
|
||||||
WorldConverter(
|
WorldConverter(
|
||||||
fs::path folder, const Content* content,
|
fs::path folder,
|
||||||
|
const Content* content,
|
||||||
std::shared_ptr<ContentLUT> lut
|
std::shared_ptr<ContentLUT> lut
|
||||||
);
|
);
|
||||||
~WorldConverter();
|
~WorldConverter();
|
||||||
|
|
||||||
|
void convert(convert_task task) const;
|
||||||
void convertNext();
|
void convertNext();
|
||||||
|
void setOnComplete(runnable callback);
|
||||||
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 write();
|
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;
|
uint getWorkDone() const override;
|
||||||
|
|
||||||
|
static std::shared_ptr<Task> startTask(
|
||||||
|
fs::path folder,
|
||||||
|
const Content* content,
|
||||||
|
std::shared_ptr<ContentLUT> lut,
|
||||||
|
runnable onDone,
|
||||||
|
bool multithreading
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FILES_WORLD_CONVERTER_H_
|
#endif // FILES_WORLD_CONVERTER_H_
|
||||||
|
|||||||
@ -207,7 +207,7 @@ ubyte* WorldRegions::getData(
|
|||||||
std::shared_ptr<regfile> WorldRegions::useRegFile(glm::ivec3 coord) {
|
std::shared_ptr<regfile> WorldRegions::useRegFile(glm::ivec3 coord) {
|
||||||
auto* file = openRegFiles[coord].get();
|
auto* file = openRegFiles[coord].get();
|
||||||
file->inUse = true;
|
file->inUse = true;
|
||||||
return std::shared_ptr<regfile>(openRegFiles[coord].get(), [this](regfile* ptr) {
|
return std::shared_ptr<regfile>(file, [this](regfile* ptr) {
|
||||||
ptr->inUse = false;
|
ptr->inUse = false;
|
||||||
regFilesCv.notify_one();
|
regFilesCv.notify_one();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -116,7 +116,7 @@ void show_process_panel(Engine* engine, std::shared_ptr<Task> task, std::wstring
|
|||||||
auto label = std::make_shared<Label>(L"0%");
|
auto label = std::make_shared<Label>(L"0%");
|
||||||
panel->add(label);
|
panel->add(label);
|
||||||
|
|
||||||
uint initialWork = task->getWorkRemaining();
|
uint initialWork = task->getWorkTotal();
|
||||||
|
|
||||||
panel->listenInterval(0.01f, [=]() {
|
panel->listenInterval(0.01f, [=]() {
|
||||||
task->update();
|
task->update();
|
||||||
@ -134,25 +134,21 @@ void show_process_panel(Engine* engine, std::shared_ptr<Task> task, std::wstring
|
|||||||
menu->setPage("process", false);
|
menu->setPage("process", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<WorldConverter> create_converter(
|
std::shared_ptr<Task> create_converter(
|
||||||
Engine* engine,
|
Engine* engine,
|
||||||
fs::path folder,
|
fs::path folder,
|
||||||
const Content* content,
|
const Content* content,
|
||||||
std::shared_ptr<ContentLUT> lut,
|
std::shared_ptr<ContentLUT> lut,
|
||||||
runnable postRunnable)
|
runnable postRunnable)
|
||||||
{
|
{
|
||||||
auto converter = std::make_shared<WorldConverter>(folder, content, lut);
|
return WorldConverter::startTask(folder, content, lut, [=](){
|
||||||
converter->setOnComplete([=](){
|
|
||||||
converter->write();
|
|
||||||
|
|
||||||
auto menu = engine->getGUI()->getMenu();
|
auto menu = engine->getGUI()->getMenu();
|
||||||
menu->reset();
|
menu->reset();
|
||||||
menu->setPage("main", false);
|
menu->setPage("main", false);
|
||||||
engine->getGUI()->postRunnable([=]() {
|
engine->getGUI()->postRunnable([=]() {
|
||||||
postRunnable();
|
postRunnable();
|
||||||
});
|
});
|
||||||
});
|
}, true);
|
||||||
return converter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_convert_request(
|
void show_convert_request(
|
||||||
|
|||||||
@ -34,7 +34,7 @@ static void create_controls_panel(Engine* engine) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto scrollPanel = std::dynamic_pointer_cast<Panel>(guiutil::create(
|
auto scrollPanel = std::dynamic_pointer_cast<Panel>(guiutil::create(
|
||||||
"<panel size='400,200' padding='2' interval='1' max-length='400' color='#0000004C'>"
|
"<panel size='380,200' padding='2' interval='1' max-length='400' color='#0000004C'>"
|
||||||
"</panel>"
|
"</panel>"
|
||||||
));
|
));
|
||||||
for (auto& entry : Events::bindings){
|
for (auto& entry : Events::bindings){
|
||||||
@ -55,7 +55,6 @@ static void create_controls_panel(Engine* engine) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void menus::create_settings_panel(Engine* engine) {
|
void menus::create_settings_panel(Engine* engine) {
|
||||||
//create_audio_settings_panel(engine);
|
|
||||||
create_controls_panel(engine);
|
create_controls_panel(engine);
|
||||||
|
|
||||||
auto menu = engine->getGUI()->getMenu();
|
auto menu = engine->getGUI()->getMenu();
|
||||||
|
|||||||
@ -14,7 +14,7 @@ static debug::Logger logger("chunks-render");
|
|||||||
|
|
||||||
const uint RENDERER_CAPACITY = 9 * 6 * 6 * 3000;
|
const uint RENDERER_CAPACITY = 9 * 6 * 6 * 3000;
|
||||||
|
|
||||||
class RendererWorker : public util::Worker<std::shared_ptr<Chunk>, RendererResult> {
|
class RendererWorker : public util::Worker<Chunk, RendererResult> {
|
||||||
Level* level;
|
Level* level;
|
||||||
BlocksRenderer renderer;
|
BlocksRenderer renderer;
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class ChunksRenderer {
|
|||||||
std::unordered_map<glm::ivec2, std::shared_ptr<Mesh>> meshes;
|
std::unordered_map<glm::ivec2, std::shared_ptr<Mesh>> meshes;
|
||||||
std::unordered_map<glm::ivec2, bool> inwork;
|
std::unordered_map<glm::ivec2, bool> inwork;
|
||||||
|
|
||||||
util::ThreadPool<std::shared_ptr<Chunk>, RendererResult> threadPool;
|
util::ThreadPool<Chunk, RendererResult> threadPool;
|
||||||
public:
|
public:
|
||||||
ChunksRenderer(
|
ChunksRenderer(
|
||||||
Level* level,
|
Level* level,
|
||||||
|
|||||||
@ -10,7 +10,7 @@ public:
|
|||||||
virtual ~Task() {}
|
virtual ~Task() {}
|
||||||
|
|
||||||
virtual bool isActive() const = 0;
|
virtual bool isActive() const = 0;
|
||||||
virtual uint getWorkRemaining() const = 0;
|
virtual uint getWorkTotal() const = 0;
|
||||||
virtual uint getWorkDone() const = 0;
|
virtual uint getWorkDone() const = 0;
|
||||||
virtual void update() = 0;
|
virtual void update() = 0;
|
||||||
virtual void waitForEnd() = 0;
|
virtual void waitForEnd() = 0;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace util {
|
|||||||
|
|
||||||
template<class J, class T>
|
template<class J, class T>
|
||||||
struct ThreadPoolResult {
|
struct ThreadPoolResult {
|
||||||
J job;
|
std::shared_ptr<J> job;
|
||||||
std::condition_variable& variable;
|
std::condition_variable& variable;
|
||||||
int workerIndex;
|
int workerIndex;
|
||||||
bool& locked;
|
bool& locked;
|
||||||
@ -29,13 +29,13 @@ class Worker {
|
|||||||
public:
|
public:
|
||||||
Worker() {}
|
Worker() {}
|
||||||
virtual ~Worker() {}
|
virtual ~Worker() {}
|
||||||
virtual R operator()(const T&) = 0;
|
virtual R operator()(const std::shared_ptr<T>&) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T, class R>
|
template<class T, class R>
|
||||||
class ThreadPool : public Task {
|
class ThreadPool : public Task {
|
||||||
debug::Logger logger;
|
debug::Logger logger;
|
||||||
std::queue<T> jobs;
|
std::queue<std::shared_ptr<T>> jobs;
|
||||||
std::queue<ThreadPoolResult<T, R>> results;
|
std::queue<ThreadPoolResult<T, R>> results;
|
||||||
std::mutex resultsMutex;
|
std::mutex resultsMutex;
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
@ -43,7 +43,7 @@ class ThreadPool : public Task {
|
|||||||
std::mutex jobsMutex;
|
std::mutex jobsMutex;
|
||||||
std::vector<std::unique_lock<std::mutex>> workersBlocked;
|
std::vector<std::unique_lock<std::mutex>> workersBlocked;
|
||||||
consumer<R&> resultConsumer;
|
consumer<R&> resultConsumer;
|
||||||
consumer<T&> onJobFailed = nullptr;
|
consumer<std::shared_ptr<T>&> onJobFailed = nullptr;
|
||||||
runnable onComplete = nullptr;
|
runnable onComplete = nullptr;
|
||||||
std::atomic<int> busyWorkers = 0;
|
std::atomic<int> busyWorkers = 0;
|
||||||
std::atomic<uint> jobsDone = 0;
|
std::atomic<uint> jobsDone = 0;
|
||||||
@ -57,7 +57,7 @@ class ThreadPool : public Task {
|
|||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
bool locked = false;
|
bool locked = false;
|
||||||
while (working) {
|
while (working) {
|
||||||
T job;
|
std::shared_ptr<T> job;
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(jobsMutex);
|
std::unique_lock<std::mutex> lock(jobsMutex);
|
||||||
jobsMutexCondition.wait(lock, [this] {
|
jobsMutexCondition.wait(lock, [this] {
|
||||||
@ -199,7 +199,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void enqueueJob(T job) {
|
void enqueueJob(std::shared_ptr<T> job) {
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(jobsMutex);
|
std::lock_guard<std::mutex> lock(jobsMutex);
|
||||||
jobs.push(job);
|
jobs.push(job);
|
||||||
@ -228,8 +228,8 @@ public:
|
|||||||
this->onComplete = callback;
|
this->onComplete = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getWorkRemaining() const override {
|
uint getWorkTotal() const override {
|
||||||
return jobs.size();
|
return jobs.size()+jobsDone+busyWorkers;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getWorkDone() const override {
|
uint getWorkDone() const override {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user