mirror of https://github.com/AxioDL/metaforce.git
116 lines
3.5 KiB
C++
116 lines
3.5 KiB
C++
#ifndef HECL_CLIENT_PROCESS_HPP
|
|
#define HECL_CLIENT_PROCESS_HPP
|
|
|
|
#include "hecl.hpp"
|
|
#include "Database.hpp"
|
|
#include "boo/ThreadLocalPtr.hpp"
|
|
#include "hecl/Blender/Token.hpp"
|
|
#include <list>
|
|
#include <thread>
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
|
|
namespace hecl
|
|
{
|
|
|
|
class ClientProcess
|
|
{
|
|
std::mutex m_mutex;
|
|
std::condition_variable m_cv;
|
|
std::condition_variable m_initCv;
|
|
std::condition_variable m_waitCv;
|
|
int m_verbosity;
|
|
bool m_fast;
|
|
bool m_force;
|
|
|
|
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 : Transaction
|
|
{
|
|
ProjectPath m_path;
|
|
void* m_targetBuf;
|
|
size_t m_maxLen;
|
|
size_t m_offset;
|
|
void run(blender::Token& btok);
|
|
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 : Transaction
|
|
{
|
|
ProjectPath m_path;
|
|
Database::IDataSpec* m_dataSpec;
|
|
bool m_returnResult = false;
|
|
void run(blender::Token& btok);
|
|
CookTransaction(ClientProcess& parent, const ProjectPath& path, Database::IDataSpec* spec)
|
|
: Transaction(parent, Type::Cook), m_path(path), m_dataSpec(spec) {}
|
|
};
|
|
struct LambdaTransaction : Transaction
|
|
{
|
|
std::function<void(blender::Token&)> m_func;
|
|
void run(blender::Token& btok);
|
|
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(int verbosityLevel=1, bool fast=false, bool force=false);
|
|
~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, 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);
|
|
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;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif // HECL_CLIENT_PROCESS_HPP
|