#pragma once #ifndef _LOADCONTEXT_HPP_ #define _LOADCONTEXT_HPP_ #include #include #include #include #include class WorkContext; class LoadWorker { WorkContext* _context; public: bool _running; std::thread _thread; void start(); LoadWorker( WorkContext* context ) : _context( context ), _running(true), _thread( std::bind(&LoadWorker::start, this) ) { } ~LoadWorker( ) { _running = false; _thread.join(); } }; /** * @brief Interface for background work */ class WorkJob { WorkContext* _context; public: WorkJob(WorkContext* context) : _context(context) {} virtual ~WorkJob() {} /** * @brief getContext * @return The loading context for this Loader */ WorkContext* getContext() const { return _context; } virtual void work() = 0; virtual void complete() {} }; // TODO: refactor everything to remove this. class GameWorld; /** * @brief A worker queue that runs work in the background. * * Work is added with queueJob, once it completes the job is added * to the _completeQueue to be finalised on the "main" thread. */ class WorkContext { std::queue _workQueue; std::queue _completeQueue; LoadWorker _worker; std::mutex _inMutex; std::mutex _outMutex; GameWorld* _world; public: WorkContext(GameWorld* world = nullptr) : _worker(this), _world(world) { } void queueJob( WorkJob* job ) { std::lock_guard guard(_inMutex); _workQueue.push( job ); } // Called by the worker thread - don't touch; void workNext(); const std::queue getWorkQueue() const { return _workQueue; } const std::queue getCompleteQueue() const { return _completeQueue; } bool isEmpty() { std::lock_guard guardIn( _inMutex ); std::lock_guard guardOu( _outMutex ); return (getWorkQueue().size() + getCompleteQueue().size()) == 0; } GameWorld* getWorld() const { return _world; } void update(); }; #endif