diff options
Diffstat (limited to 'source/modules/asura-utils/Threads/Thread.cpp')
-rw-r--r-- | source/modules/asura-utils/Threads/Thread.cpp | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/source/modules/asura-utils/Threads/Thread.cpp b/source/modules/asura-utils/Threads/Thread.cpp new file mode 100644 index 0000000..1153912 --- /dev/null +++ b/source/modules/asura-utils/Threads/Thread.cpp @@ -0,0 +1,287 @@ +#include "Thread.h" + +#include "ThreadImplWin32.h" +#include "ThreadImplPosix.h" +#include "ThreadImplSdl.h" +#include "ThreadImplStd.h" + +namespace_begin(AsuraEngine) +namespace_begin(Threads) + +Thread::Thread(lua_State* luaThread, ThreadType type /*= THREAD_TYPE_DEFERRED*/, uint sleepTime /*= 0*/, const std::string& name /*= ""*/) + : m_Name(name) + , m_State(THREAD_STATE_IDLE) + , m_Type(type) + , m_LuaThread(luaThread) + , m_CallbackThread(nullptr) + , m_SleepTime(sleepTime) +{ + LUAX_STATE(luaThread); + if (type == THREAD_TYPE_IMMEDIATE) + { + Luax::LuaxVM* vm = state.GetVM(); + ASSERT(vm); + m_CallbackThread = vm->CreateThread(); + ASSERT(m_CallbackThread); + SetLuaxMemberRef(state, m_CallbackThreadRef, -1); + state.Pop(); // callback thread + } +} + +Thread::~Thread() +{ + if (m_Impl) + { + delete m_Impl; + m_Impl = nullptr; + } +} + +bool Thread::AddTask(Task* task) +{ + lock(m_TaskQueueMutex) + { + task->Retain(); + m_TaskQueue.push(task); + } + return true; +} + +uint Thread::GetTaskCount() +{ + return m_TaskQueue.size(); +} + +void Thread::Idle() +{ + m_State = THREAD_STATE_IDLE; +} + +#define try_start_thread(impl)\ +if (!m_Impl) \ +{ \ +m_Impl = new impl(); \ +if (!m_Impl->Start(this, stacksize)) \ +{ \ + delete m_Impl; \ + m_Impl = nullptr; \ +} \ +} + +bool Thread::Start(bool isDaemon /*= true*/, uint32 stacksize /*= 0*/) +{ + if (m_State != THREAD_STATE_IDLE) + return false; + + // Ѿһ֮ǰģر + if (m_Impl) + { + delete m_Impl; + m_Impl = nullptr; + } + +#if ASURA_THREAD_WIN32 + try_start_thread(ThreadImplWin32); +#endif + + if (!m_Impl) + return false; + + m_IsDaemon = isDaemon; + m_StateMutex.Lock(); + m_State = THREAD_STATE_RUNNING; + m_StateMutex.Unlock(); +} + +void Thread::Pause() +{ + ASSERT(m_Impl); + + lock(m_StateMutex) + { + m_State = THREAD_STATE_PAUSED; + } +} + +void Thread::Resume() +{ + ASSERT(m_Impl); + + lock(m_StateMutex) + { + if (m_State == THREAD_STATE_PAUSED) + m_State = THREAD_STATE_RUNNING; + } +} + +void Thread::Stop() +{ + ASSERT(m_Impl); + + lock(m_StateMutex) + { + m_State = THREAD_STATE_STOPPED; + } +} + +void Thread::PauseSync() +{ + Pause(); + wait(m_SemPause); +} + +void Thread::ResumeSync() +{ + Resume(); + wait(m_SemResume); +} + +void Thread::StopSync() +{ + Stop(); + wait(m_SemStop); +} + +void Thread::Join() +{ + ASSERT(m_Impl); + m_Impl->Join(); +} + +ThreadState Thread::GetState() +{ + ThreadState state; + lock(m_StateMutex) + { + state = m_State; + } + return state; +} + +bool Thread::IsRunning() +{ + ASSERT(m_Impl); + + return GetState() == THREAD_STATE_RUNNING; +} + +bool Thread::IsPaused() +{ + ASSERT(m_Impl); + + return GetState() == THREAD_STATE_PAUSED; +} + +bool Thread::IsStopped() +{ + ASSERT(m_Impl); + + return GetState() == THREAD_STATE_STOPPED; +} + +bool Thread::IsCurrent() +{ + ASSERT(m_Impl); + + return m_Impl->IsCurrent(); +} + +const std::string& Thread::GetName() +{ + return m_Name; +} + +int Thread::Process() +{ + LUAX_STATE(m_LuaThread); + + do{ + if (IsRunning()) + { + while (!m_TaskQueue.empty()) + { + Task* task = m_TaskQueue.front(); + if (task && task->Execute()) + { + if (m_Type == THREAD_TYPE_DEFERRED) + { + m_FinishedMutex.Lock(); + task->Retain(); + m_FinishedTasks.push(task); + m_FinishedMutex.Unlock(); + } + else if (m_Type == THREAD_TYPE_IMMEDIATE) + { + // unsafe + task->Invoke(m_CallbackThread); + this->LuaxRelease<Task>(state, task); + } + m_TaskQueueMutex.Lock(); + m_TaskQueue.pop(); + task->Release(); + m_TaskQueueMutex.Unlock(); + } + } + } + + // ˳ѭ + if (IsStopped()) + break; + + // CPUʹ + Sleep(m_SleepTime); + + } while (m_IsDaemon); + + // ػ̣߳еstop״̬ + if (!m_IsDaemon) + Stop(); + + signal(m_SemStop); + + // ״̬ΪIdle + Idle(); + + return 0; +} + +/// +/// ӳģʽص +/// +void Thread::Dispatch() +{ + if (m_Type != THREAD_TYPE_DEFERRED) + return; + + LUAX_STATE(m_LuaThread); + while (!m_FinishedTasks.empty()) + { + Task* task = m_FinishedTasks.front(); + if (task) + { + task->Invoke(m_LuaThread); + this->LuaxRelease<Task>(state, task); + m_FinishedMutex.Lock(); + m_FinishedTasks.pop(); + task->Release(); + m_FinishedMutex.Unlock(); + } + } +} + +void Thread::Sleep(uint ms) +{ + ASSERT(m_Impl); + if (m_Impl) + { + m_Impl->Sleep(ms); + } +} + +void Thread::SetSleepTime(uint ms) +{ + m_SleepTime = ms; +} + +namespace_end +namespace_end
\ No newline at end of file |