#pragma once // ------------------------------------------------------------------------------------------------ #include "Base/Shared.hpp" #include "Base/VecMap.hpp" #include "Library/Worker/Job.hpp" // ------------------------------------------------------------------------------------------------ #include #include #include #include #include #include // ------------------------------------------------------------------------------------------------ #include // ------------------------------------------------------------------------------------------------ namespace SqMod { using namespace moodycamel; // ------------------------------------------------------------------------------------------------ struct Worker; /* ------------------------------------------------------------------------------------------------ * Thread. */ struct Thread { // -------------------------------------------------------------------------------------------- Worker * mWorker; // Worker pointer. LightObj mObject; // Worker object. std::thread mThread; // Worker thread. /* -------------------------------------------------------------------------------------------- * Default constructor. */ Thread() : mWorker(nullptr), mObject(), mThread() { } /* -------------------------------------------------------------------------------------------- * Base constructor. */ Thread(Worker * worker); /* -------------------------------------------------------------------------------------------- * Copy constructor (disabled). */ Thread(const Thread & o) = delete; /* -------------------------------------------------------------------------------------------- * Move constructor (disabled). */ Thread(Thread && o) noexcept; /* -------------------------------------------------------------------------------------------- * Destructor. */ ~Thread() { End(); } /* -------------------------------------------------------------------------------------------- * Copy assignment (disabled). */ Thread & operator = (const Thread & o) = delete; /* -------------------------------------------------------------------------------------------- * Move assignment (disabled). */ Thread & operator = (Thread && o) = delete; /* -------------------------------------------------------------------------------------------- * */ void End() { } }; /* ------------------------------------------------------------------------------------------------ * */ struct Worker { /* -------------------------------------------------------------------------------------------- * Default constructor. */ Worker(SQInteger stack, String && str, size_t h); /* -------------------------------------------------------------------------------------------- * Copy constructor (disabled). */ Worker(const Worker & o) = delete; /* -------------------------------------------------------------------------------------------- * Move constructor (disabled). */ Worker(Worker && o) = delete; /* -------------------------------------------------------------------------------------------- * Destructor. */ ~Worker(); /* -------------------------------------------------------------------------------------------- * Copy assignment operator (disabled). */ Worker & operator = (const Worker & o) = delete; /* -------------------------------------------------------------------------------------------- * Move assignment operator (disabled). */ Worker & operator = (Worker && o) = delete; /* -------------------------------------------------------------------------------------------- * */ static void Terminate(); /* -------------------------------------------------------------------------------------------- * */ static void Process(size_t jobs); /* -------------------------------------------------------------------------------------------- * */ static LightObj Create(SQInteger stack, StackStrF & str); /* -------------------------------------------------------------------------------------------- * Invoke the actual process loop only if the worker was not requested to stop. */ void Start(); /* -------------------------------------------------------------------------------------------- * Stop the worker but do not remove from container. */ void Kill() { std::lock_guard< std::mutex > lg(m_Mutex); } /* -------------------------------------------------------------------------------------------- * Stop the worker and remove from container. */ void Stop() { m_Running.clear(); // Stop running as soon as you finish what you're doing } /* -------------------------------------------------------------------------------------------- * Retrieve the worker name. */ const String & GetName() const { return m_Name; } /* -------------------------------------------------------------------------------------------- * */ void Evaluate(StackStrF & str, Function & callback) { // Is there something to evaluate? if (str.mLen <= 0) { STHROWF("Nothing to evaluate"); } // Create the job std::unique_ptr< Job > job(new Job(std::move(callback))); // Define type job->mType = Job::Type::Eval; // Assign data job->mPayload.assign(str.mPtr, static_cast< size_t >(str.mLen)); // Submit job m_PendingJobs.enqueue(std::move(job)); } /* -------------------------------------------------------------------------------------------- * */ void EvaluateTarget(StackStrF & str) { } /* -------------------------------------------------------------------------------------------- * */ void Execute(StackStrF & str) { } /* -------------------------------------------------------------------------------------------- * */ void ExecuteTarget(StackStrF & str) { } private: /* -------------------------------------------------------------------------------------------- * Worker thread container. */ using Container = VecMap< size_t, std::unique_ptr< Thread > >; /* -------------------------------------------------------------------------------------------- * List of active worker threads. */ static Container sm_Workers; /* -------------------------------------------------------------------------------------------- * */ using Jobs = ConcurrentQueue< std::unique_ptr< Job > >; /* -------------------------------------------------------------------------------------------- * Job queue. */ Jobs m_PendingJobs; /* -------------------------------------------------------------------------------------------- * Job queue. */ Jobs m_FinishedJobs; /* -------------------------------------------------------------------------------------------- * Loop state. */ std::atomic_flag m_Running; /* -------------------------------------------------------------------------------------------- * Script state. */ HSQUIRRELVM m_VM; /* -------------------------------------------------------------------------------------------- * Instance mutex. */ std::mutex m_Mutex; /* -------------------------------------------------------------------------------------------- * Cached name hash. */ size_t m_Hash; /* -------------------------------------------------------------------------------------------- * Worker name string. */ String m_Name; /* -------------------------------------------------------------------------------------------- * Cached name hash. */ SQInteger m_StackSize; /* -------------------------------------------------------------------------------------------- * Take jobs from the queue and perform them. */ void Work(); /* -------------------------------------------------------------------------------------------- * Script output handlers. */ static void PrintFunc(HSQUIRRELVM vm, CSStr msg, ...); static void ErrorFunc(HSQUIRRELVM vm, CSStr msg, ...); }; } // Namespace:: SqMod