diff options
author | chai <chaifix@163.com> | 2021-10-25 23:29:21 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-10-25 23:29:21 +0800 |
commit | 7ecf913256fb396e3027aac3318d996a716a52ef (patch) | |
tree | 4540835c881a63b665e2a692bf30115fd29e8bb0 /Runtime/Threading | |
parent | 0816cd70ca1a213b6ed872bcf3c0bf0912473722 (diff) |
+ job system
Diffstat (limited to 'Runtime/Threading')
-rw-r--r-- | Runtime/Threading/Job.cpp | 13 | ||||
-rw-r--r-- | Runtime/Threading/Job.h | 17 | ||||
-rw-r--r-- | Runtime/Threading/JobSystem.cpp | 43 | ||||
-rw-r--r-- | Runtime/Threading/JobSystem.h | 22 | ||||
-rw-r--r-- | Runtime/Threading/Mutex.cpp | 25 | ||||
-rw-r--r-- | Runtime/Threading/Mutex.h | 39 | ||||
-rw-r--r-- | Runtime/Threading/Semaphore.cpp | 0 | ||||
-rw-r--r-- | Runtime/Threading/Semaphore.h | 0 | ||||
-rw-r--r-- | Runtime/Threading/Thread.cpp | 69 | ||||
-rw-r--r-- | Runtime/Threading/Thread.h | 70 | ||||
-rw-r--r-- | Runtime/Threading/WorkThread.cpp | 48 |
11 files changed, 346 insertions, 0 deletions
diff --git a/Runtime/Threading/Job.cpp b/Runtime/Threading/Job.cpp new file mode 100644 index 0000000..18794c5 --- /dev/null +++ b/Runtime/Threading/Job.cpp @@ -0,0 +1,13 @@ +#include "Job.h" +#include "Runtime/Utilities/UIDGenerator.h" + +static UIDGenerator s_JobIDGenerator; + +Job::Job() + : m_ID(s_JobIDGenerator.GenUID()) +{ +} + +Job::~Job() +{ +} diff --git a/Runtime/Threading/Job.h b/Runtime/Threading/Job.h new file mode 100644 index 0000000..db89feb --- /dev/null +++ b/Runtime/Threading/Job.h @@ -0,0 +1,17 @@ +#pragma once + +// 任务的抽象基类 +class Job +{ +public: + Job(); + virtual ~Job(); + + virtual void Process() = 0; + virtual bool IsFinished() = 0; + virtual void Dispacth(void* param) = 0; // call in main thread + +protected: + int m_ID; // Job ID + +};
\ No newline at end of file diff --git a/Runtime/Threading/JobSystem.cpp b/Runtime/Threading/JobSystem.cpp new file mode 100644 index 0000000..a026300 --- /dev/null +++ b/Runtime/Threading/JobSystem.cpp @@ -0,0 +1,43 @@ +#include "JobSystem.h" + +JobSystem::JobSystem() +{ + +} + +JobSystem::~JobSystem() +{ + +} + +void JobSystem::Initilize(int workThreadCount) +{ + if (workThreadCount <= 0) + return; + + for (int i = 0; i < workThreadCount; ++i) + { + WorkThread* thread = new WorkThread(); + thread->Resume(); + m_Threads.push_back(thread); + } +} + +void JobSystem::Dispatch(void* param) +{ + for (int i = 0; i < m_Threads.size(); ++i) + { + m_Threads[i]->Dispatch(param); + } +} + +void JobSystem::AddJobAtEnd(Job* job) +{ + WorkThread* thread = SelectThread(); + thread->AddJobAtEnd(job); +} + +WorkThread* JobSystem::SelectThread() +{ + return m_Threads[0]; +}
\ No newline at end of file diff --git a/Runtime/Threading/JobSystem.h b/Runtime/Threading/JobSystem.h new file mode 100644 index 0000000..c95037c --- /dev/null +++ b/Runtime/Threading/JobSystem.h @@ -0,0 +1,22 @@ +#pragma once +#include "Runtime/Utilities/Singleton.h" +#include "Runtime/Threading/Thread.h" +#include <vector> + +class JobSystem : public Singleton<JobSystem> +{ +public: + JobSystem(); + ~JobSystem(); + + void AddJobAtEnd(Job* job); + + void Initilize(int workThreadCount = 1); + void Dispatch(void* param); + +private: + WorkThread* SelectThread(); + + std::vector<WorkThread*> m_Threads; + +};
\ No newline at end of file diff --git a/Runtime/Threading/Mutex.cpp b/Runtime/Threading/Mutex.cpp new file mode 100644 index 0000000..eabe48d --- /dev/null +++ b/Runtime/Threading/Mutex.cpp @@ -0,0 +1,25 @@ +#include "Thread.h" +#include "Mutex.h" + +Mutex::Mutex() +{ + m_Handle = ::CreateMutex(NULL, FALSE, NULL); + if (!m_Handle) + throw ThreadException("Cant use win32 mutex."); +} + +Mutex::~Mutex() +{ + ::CloseHandle(m_Handle); + m_Handle = NULL; +} + +void Mutex::Lock() +{ + ::WaitForSingleObject(m_Handle, (~(uint32)0)); +} + +void Mutex::Unlock() +{ + ::ReleaseMutex(m_Handle); +}
\ No newline at end of file diff --git a/Runtime/Threading/Mutex.h b/Runtime/Threading/Mutex.h new file mode 100644 index 0000000..44f8cb9 --- /dev/null +++ b/Runtime/Threading/Mutex.h @@ -0,0 +1,39 @@ +#pragma once +#include <windows.h> + +class Mutex +{ +public: + Mutex(); + ~Mutex(); + + void Lock(); + void Unlock(); + +private: + HANDLE m_Handle; + +}; + + +class MutexLocker +{ +public: + MutexLocker(Mutex& mutex) + : m(mutex) + { + m.Lock(); + }; + ~MutexLocker() + { + m.Unlock(); + } + operator bool() { return false; }; +private: + void* operator new(size_t); + Mutex& m; +}; + +#define _lock(m) \ +if(MutexLocker lock_##m = m){} else + diff --git a/Runtime/Threading/Semaphore.cpp b/Runtime/Threading/Semaphore.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Threading/Semaphore.cpp diff --git a/Runtime/Threading/Semaphore.h b/Runtime/Threading/Semaphore.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Runtime/Threading/Semaphore.h diff --git a/Runtime/Threading/Thread.cpp b/Runtime/Threading/Thread.cpp new file mode 100644 index 0000000..0a41485 --- /dev/null +++ b/Runtime/Threading/Thread.cpp @@ -0,0 +1,69 @@ +#include <string> +#include "Thread.h" +#include "Runtime/Utilities/Assert.h" + +static std::string s_ThreadErr; + +static DWORD WINAPI ThreadMain(LPVOID param) +{ + Thread* thread = (Thread*)param; + thread->Run(); + return NULL; +} + +Thread::Thread(uint32 stacksize) +{ + m_Handle = ::CreateThread( + NULL + , stacksize + , ThreadMain + , this + , CREATE_SUSPENDED + , NULL); + if (m_Handle == 0) + { + s_ThreadErr = "Create Thread Failed. ErrorCode=" + std::to_string(GetLastError()); + throw ThreadException(s_ThreadErr.c_str()); + } +} + +Thread::~Thread() +{ + CloseHandle(m_Handle); +} + +void Thread::Resume() +{ + ::ResumeThread(m_Handle); +} + +bool Thread::IsRunning() +{ + if (m_Handle) { + DWORD exitCode = 0; + // https://blog.csdn.net/yuanmeng567/article/details/19485719 + ::GetExitCodeThread(m_Handle, &exitCode); + return exitCode == STILL_ACTIVE; + } + return false; +} + +void Thread::Join() +{ + ::WaitForSingleObject(m_Handle, INFINITE); +} + +void Thread::Kill() +{ + ::TerminateThread(m_Handle, FALSE); +} + +void Thread::Sleep(uint ms) +{ + ::Sleep(ms); +} + +bool Thread::IsCurrent() +{ + return m_Handle == ::GetCurrentThread(); +} diff --git a/Runtime/Threading/Thread.h b/Runtime/Threading/Thread.h new file mode 100644 index 0000000..ea86e16 --- /dev/null +++ b/Runtime/Threading/Thread.h @@ -0,0 +1,70 @@ +#pragma once +#include <windows.h> +#include <vector> +#include <exception> + +#include "Job.h" +#include "Runtime/Utilities/Type.h" +#include "Mutex.h" + +class ThreadException : public std::exception +{ +public: + ThreadException(const char* what) + : std::exception(what) + { + } +}; + +class Thread +{ +public: + Thread(uint32 stacksize = 0)/*throw ThreadExeception*/; + virtual ~Thread(); + + virtual void Run() = 0; + + virtual void Resume(); + virtual void Join() ; + virtual void Kill() ; + + virtual void Sleep(uint ms) ; + + virtual bool IsRunning() ; + virtual bool IsCurrent() ; + +protected: + HANDLE m_Handle; + +}; + +// 任务系统的线程 +class WorkThread : public Thread +{ +public: + void Run() override; + void Dispatch(void* param); // call in main thread + + void AddJobAtEnd(Job* job); + +private: + Mutex m_PendingMutex; + Mutex m_FinishedMutex; + + std::vector<Job*> m_PendingJobs; + std::vector<Job*> m_FinishedJobs; + +}; + +// 执行小段代码的线程 +class CodePieceThread : public Thread +{ +public: + typedef void(*CodePiece)(); + + void Run() override; + +private: + std::vector<CodePiece> m_CodePieces; + +};
\ No newline at end of file diff --git a/Runtime/Threading/WorkThread.cpp b/Runtime/Threading/WorkThread.cpp new file mode 100644 index 0000000..b3b462a --- /dev/null +++ b/Runtime/Threading/WorkThread.cpp @@ -0,0 +1,48 @@ +#include "Thread.h" +#include "Runtime/Debug/Log.h" + +void WorkThread::Run() +{ + while (true) + { + _lock(m_PendingMutex) + { + for (auto iter = m_PendingJobs.begin(); iter != m_PendingJobs.end();) + { + Job* job = *iter; + job->Process(); + if (job->IsFinished()) + { + _lock(m_FinishedMutex) { + m_FinishedJobs.push_back(job); + } + iter = m_PendingJobs.erase(iter); + continue; + } + ++iter; + } + if (m_PendingJobs.size() == 0) + ::Sleep(1); + } + } +} + +void WorkThread::Dispatch(void* param) +{ + _lock(m_FinishedMutex) + { + for (int i = 0; i < m_FinishedJobs.size(); ++i) + { + m_FinishedJobs[i]->Dispacth(param); + } + m_FinishedJobs.clear(); + } +} + +void WorkThread::AddJobAtEnd(Job* job) +{ + _lock(m_PendingMutex) + { + m_PendingJobs.push_back(job); + } +}
\ No newline at end of file |