| @@ -45,61 +45,58 @@ public: | |||||
| virtual ~Thread() {} | virtual ~Thread() {} | ||||
| }; | }; | ||||
| struct ThreadCommand | |||||
| struct ThreadStatus | |||||
| { | { | ||||
| enum Value | enum Value | ||||
| { | { | ||||
| NOTHING = 0, | |||||
| THREAD_STARTED, | THREAD_STARTED, | ||||
| THREAD_STOPPED, | THREAD_STOPPED, | ||||
| WORK_TODO, | |||||
| WORK_DONE, | |||||
| THREAD_STOP, | |||||
| MAX | MAX | ||||
| } | } | ||||
| m_value; | m_value; | ||||
| inline ThreadCommand() : m_value(ThreadCommand::MAX) {} | |||||
| inline ThreadCommand(Value v) : m_value(v) {} | |||||
| bool operator==(const ThreadCommand& v) { return m_value == v.m_value; } | |||||
| inline ThreadStatus() : m_value(ThreadStatus::NOTHING) {} | |||||
| inline ThreadStatus(Value v) : m_value(v) {} | |||||
| bool operator==(const ThreadStatus& v) { return m_value == v.m_value; } | |||||
| }; | }; | ||||
| template<typename T1> | |||||
| struct JobCommand : public ThreadCommand | |||||
| struct ThreadJobType | |||||
| { | { | ||||
| inline JobCommand() | |||||
| : ThreadCommand(ThreadCommand::WORK_TODO) | |||||
| {} | |||||
| inline JobCommand(Value v) | |||||
| : ThreadCommand(v) | |||||
| {} | |||||
| enum Value | |||||
| { | |||||
| NONE = 0, | |||||
| WORK_TODO, | |||||
| WORK_DONE, | |||||
| THREAD_STOP, | |||||
| inline JobCommand(T1 const &data) | |||||
| : ThreadCommand(ThreadCommand::WORK_TODO), | |||||
| m_data(data) | |||||
| {} | |||||
| MAX | |||||
| } | |||||
| m_value; | |||||
| inline JobCommand(Value v, T1 const &data) | |||||
| : ThreadCommand(v), | |||||
| m_data(data) | |||||
| {} | |||||
| inline ThreadJobType() : m_value(ThreadJobType::MAX) {} | |||||
| inline ThreadJobType(Value v) : m_value(v) {} | |||||
| bool operator==(const ThreadJobType& o) { return m_value == o.m_value; } | |||||
| }; | |||||
| inline void SetData(T1 const &data) | |||||
| { | |||||
| m_data = data; | |||||
| } | |||||
| class ThreadJob | |||||
| { | |||||
| friend class ThreadManager; | |||||
| inline T1 GetData() | |||||
| { | |||||
| return m_data; | |||||
| } | |||||
| public: | |||||
| ThreadJob() { m_type = ThreadJobType::NONE; } | |||||
| ThreadJob(ThreadJobType type) { m_type = type; } | |||||
| ThreadJobType GetJobType() { return m_type; } | |||||
| void SetJobType(ThreadJobType type) { m_type = type; } | |||||
| bool operator==(const ThreadJobType& o) { return GetJobType() == o; } | |||||
| protected: | |||||
| virtual bool DoWork() { return false; } | |||||
| private: | |||||
| T1 m_data; | |||||
| ThreadJobType m_type; | |||||
| }; | }; | ||||
| template<typename T1, typename T2> class ThreadManager | |||||
| class ThreadManager | |||||
| { | { | ||||
| public: | public: | ||||
| ThreadManager(int thread_count) | ThreadManager(int thread_count) | ||||
| @@ -123,15 +120,15 @@ public: | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool AddWork(const JobCommand<T1>& job) | |||||
| bool AddWork(ThreadJob* job) | |||||
| { | { | ||||
| if (m_jobqueue.TryPush(job)) | if (m_jobqueue.TryPush(job)) | ||||
| return true; | return true; | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool FetchResult(Array<JobCommand<T2> >& results) | |||||
| bool FetchResult(Array<ThreadJob*>& results) | |||||
| { | { | ||||
| JobCommand<T2> result; | |||||
| ThreadJob* result; | |||||
| while (m_resultqueue.TryPop(result)) | while (m_resultqueue.TryPop(result)) | ||||
| results << result; | results << result; | ||||
| return results.Count() > 0; | return results.Count() > 0; | ||||
| @@ -140,28 +137,25 @@ public: | |||||
| static void *BaseThreadWork(void* data) | static void *BaseThreadWork(void* data) | ||||
| { | { | ||||
| ThreadManager *that = (ThreadManager *)data; | ThreadManager *that = (ThreadManager *)data; | ||||
| that->m_spawnqueue.Push(ThreadCommand::THREAD_STARTED); | |||||
| that->m_spawnqueue.Push(ThreadStatus::THREAD_STARTED); | |||||
| for ( ; ; ) | for ( ; ; ) | ||||
| { | { | ||||
| JobCommand<T1> job = that->m_jobqueue.Pop(); | |||||
| if (job == ThreadCommand::THREAD_STOP) | |||||
| ThreadJob* job = that->m_jobqueue.Pop(); | |||||
| if (job->GetJobType() == ThreadJobType::THREAD_STOP) | |||||
| break; | break; | ||||
| else if (job == ThreadCommand::WORK_TODO) | |||||
| else if (*job == ThreadJobType::WORK_TODO) | |||||
| { | { | ||||
| JobCommand<T2> result(ThreadCommand::WORK_DONE); | |||||
| if (that->DoThreadWork(job, result)) | |||||
| that->m_resultqueue.Push(result); | |||||
| if (job->DoWork()) | |||||
| { | |||||
| job->SetJobType(ThreadJobType::WORK_DONE); | |||||
| that->m_resultqueue.Push(job); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| that->m_donequeue.Push(ThreadCommand::THREAD_STOPPED); | |||||
| that->m_donequeue.Push(ThreadStatus::THREAD_STOPPED); | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| virtual bool DoThreadWork(JobCommand<T1>& job, JobCommand<T2>& result) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| //Stop the thread | //Stop the thread | ||||
| bool Stop() | bool Stop() | ||||
| { | { | ||||
| @@ -170,8 +164,9 @@ public: | |||||
| /* Signal worker threads for completion and wait for | /* Signal worker threads for completion and wait for | ||||
| * them to quit. */ | * them to quit. */ | ||||
| ThreadJob stop_job(ThreadJobType::THREAD_STOP); | |||||
| for (int i = 0; i < m_thread_count; i++) | for (int i = 0; i < m_thread_count; i++) | ||||
| m_jobqueue.Push(ThreadCommand::THREAD_STOP); | |||||
| m_jobqueue.Push(&stop_job); | |||||
| for (int i = 0; i < m_thread_count; i++) | for (int i = 0; i < m_thread_count; i++) | ||||
| m_donequeue.Pop(); | m_donequeue.Pop(); | ||||
| @@ -182,9 +177,9 @@ protected: | |||||
| /* Worker threads */ | /* Worker threads */ | ||||
| int m_thread_count; | int m_thread_count; | ||||
| Array<Thread*> m_threads; | Array<Thread*> m_threads; | ||||
| Queue<ThreadCommand> m_spawnqueue, m_donequeue; | |||||
| Queue<JobCommand<T1> > m_jobqueue; | |||||
| Queue<JobCommand<T2> > m_resultqueue; | |||||
| Queue<ThreadStatus> m_spawnqueue, m_donequeue; | |||||
| Queue<ThreadJob*> m_jobqueue; | |||||
| Queue<ThreadJob*> m_resultqueue; | |||||
| }; | }; | ||||
| #endif | #endif | ||||