summaryrefslogtreecommitdiff
path: root/Source/modules/asura-base/Threads/Thread.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-07 21:08:47 +0800
committerchai <chaifix@163.com>2019-08-07 21:08:47 +0800
commit0c391fdbce5a079cf03e483eb6174dd47806163d (patch)
treeb06cd7a9d0ae0d9bb9e82f3dcb786dfce11f8628 /Source/modules/asura-base/Threads/Thread.cpp
parent9686368e58e25cbd6dc37d686bdd2be3f80486d6 (diff)
*misc
Diffstat (limited to 'Source/modules/asura-base/Threads/Thread.cpp')
-rw-r--r--Source/modules/asura-base/Threads/Thread.cpp287
1 files changed, 287 insertions, 0 deletions
diff --git a/Source/modules/asura-base/Threads/Thread.cpp b/Source/modules/asura-base/Threads/Thread.cpp
new file mode 100644
index 0000000..1153912
--- /dev/null
+++ b/Source/modules/asura-base/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