mirror of https://github.com/AxioDL/metaforce.git
111 lines
3.6 KiB
C++
111 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include <condition_variable>
|
|
#include <cstddef>
|
|
#include <functional>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <thread>
|
|
|
|
#include "hecl/Blender/Token.hpp"
|
|
#include "hecl/hecl.hpp"
|
|
#include "hecl/SystemChar.hpp"
|
|
|
|
#include <boo/ThreadLocalPtr.hpp>
|
|
|
|
namespace hecl::Database {
|
|
class IDataSpec;
|
|
}
|
|
|
|
namespace hecl {
|
|
class MultiProgressPrinter;
|
|
|
|
extern int CpuCountOverride;
|
|
void SetCpuCountOverride(int argc, const SystemChar** argv);
|
|
|
|
class ClientProcess {
|
|
std::mutex m_mutex;
|
|
std::condition_variable m_cv;
|
|
std::condition_variable m_initCv;
|
|
std::condition_variable m_waitCv;
|
|
const MultiProgressPrinter* m_progPrinter;
|
|
int m_completedCooks = 0;
|
|
int m_addedCooks = 0;
|
|
|
|
public:
|
|
struct Transaction {
|
|
ClientProcess& m_parent;
|
|
enum class Type { Buffer, Cook, Lambda } m_type;
|
|
bool m_complete = false;
|
|
virtual void run(blender::Token& btok) = 0;
|
|
Transaction(ClientProcess& parent, Type tp) : m_parent(parent), m_type(tp) {}
|
|
};
|
|
struct BufferTransaction final : Transaction {
|
|
ProjectPath m_path;
|
|
void* m_targetBuf;
|
|
size_t m_maxLen;
|
|
size_t m_offset;
|
|
void run(blender::Token& btok) override;
|
|
BufferTransaction(ClientProcess& parent, const ProjectPath& path, void* target, size_t maxLen, size_t offset)
|
|
: Transaction(parent, Type::Buffer), m_path(path), m_targetBuf(target), m_maxLen(maxLen), m_offset(offset) {}
|
|
};
|
|
struct CookTransaction final : Transaction {
|
|
ProjectPath m_path;
|
|
Database::IDataSpec* m_dataSpec;
|
|
bool m_returnResult = false;
|
|
bool m_force;
|
|
bool m_fast;
|
|
void run(blender::Token& btok) override;
|
|
CookTransaction(ClientProcess& parent, const ProjectPath& path, bool force, bool fast, Database::IDataSpec* spec)
|
|
: Transaction(parent, Type::Cook), m_path(path), m_dataSpec(spec), m_force(force), m_fast(fast) {}
|
|
};
|
|
struct LambdaTransaction final : Transaction {
|
|
std::function<void(blender::Token&)> m_func;
|
|
void run(blender::Token& btok) override;
|
|
LambdaTransaction(ClientProcess& parent, std::function<void(blender::Token&)>&& func)
|
|
: Transaction(parent, Type::Lambda), m_func(std::move(func)) {}
|
|
};
|
|
|
|
private:
|
|
std::list<std::shared_ptr<Transaction>> m_pendingQueue;
|
|
std::list<std::shared_ptr<Transaction>> m_completedQueue;
|
|
int m_inProgress = 0;
|
|
bool m_running = true;
|
|
|
|
struct Worker {
|
|
ClientProcess& m_proc;
|
|
int m_idx;
|
|
std::thread m_thr;
|
|
blender::Token m_blendTok;
|
|
bool m_didInit = false;
|
|
Worker(ClientProcess& proc, int idx);
|
|
void proc();
|
|
};
|
|
std::vector<Worker> m_workers;
|
|
static ThreadLocalPtr<ClientProcess::Worker> ThreadWorker;
|
|
|
|
public:
|
|
ClientProcess(const MultiProgressPrinter* progPrinter = nullptr);
|
|
~ClientProcess() { shutdown(); }
|
|
std::shared_ptr<const BufferTransaction> addBufferTransaction(const hecl::ProjectPath& path, void* target,
|
|
size_t maxLen, size_t offset);
|
|
std::shared_ptr<const CookTransaction> addCookTransaction(const hecl::ProjectPath& path, bool force, bool fast,
|
|
Database::IDataSpec* spec);
|
|
std::shared_ptr<const LambdaTransaction> addLambdaTransaction(std::function<void(blender::Token&)>&& func);
|
|
bool syncCook(const hecl::ProjectPath& path, Database::IDataSpec* spec, blender::Token& btok, bool force, bool fast);
|
|
void swapCompletedQueue(std::list<std::shared_ptr<Transaction>>& queue);
|
|
void waitUntilComplete();
|
|
void shutdown();
|
|
bool isBusy() const { return m_pendingQueue.size() || m_inProgress; }
|
|
|
|
static int GetThreadWorkerIdx() {
|
|
Worker* w = ThreadWorker.get();
|
|
if (w)
|
|
return w->m_idx;
|
|
return -1;
|
|
}
|
|
};
|
|
|
|
} // namespace hecl
|