summaryrefslogtreecommitdiff
path: root/source/modules/asura-utils/threading/thread.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-03-29 22:51:04 +0800
committerchai <chaifix@163.com>2019-03-29 22:51:04 +0800
commitc302f5ae5f9e30a28e487e8a764d9cc31546bbea (patch)
tree7f18bedeece950600336ea7ced7c52c468552c98 /source/modules/asura-utils/threading/thread.cpp
parent157530b8b6e11efc5573d5a0db8987a440197aa1 (diff)
*rename
Diffstat (limited to 'source/modules/asura-utils/threading/thread.cpp')
-rw-r--r--source/modules/asura-utils/threading/thread.cpp272
1 files changed, 272 insertions, 0 deletions
diff --git a/source/modules/asura-utils/threading/thread.cpp b/source/modules/asura-utils/threading/thread.cpp
new file mode 100644
index 0000000..0f4f5da
--- /dev/null
+++ b/source/modules/asura-utils/threading/thread.cpp
@@ -0,0 +1,272 @@
+#include "thread.h"
+
+#include "thread_impl_win32.h"
+#include "thread_impl_posix.h"
+#include "thread_impl_sdl.h"
+#include "thread_impl_std.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ Thread::Thread(lua_State* luaThread, ThreadType type /*= THREAD_TYPE_DEFERRED*/, uint sleepTime /*= 0*/, const std::string& name /*= ""*/)
+ : mName(name)
+ , mState(THREAD_STATE_IDLE)
+ , mType(type)
+ , mLuaThread(luaThread)
+ , mCallbackThread(nullptr)
+ , mSleepTime(sleepTime)
+ {
+ LUAX_STATE(luaThread);
+ if (type == THREAD_TYPE_IMMEDIATE)
+ {
+ Luax::LuaxVM* vm = state.GetVM();
+ ASSERT(vm);
+ mCallbackThread = vm->CreateThread();
+ ASSERT(mCallbackThread);
+ SetLuaxMemberRef(state, mCallbackThreadRef, -1);
+ state.Pop(); // callback thread
+ }
+ }
+
+ Thread::~Thread()
+ {
+ if (mImpl)
+ {
+ delete mImpl;
+ mImpl = nullptr;
+ }
+ }
+
+ bool Thread::AddTask(Task* task)
+ {
+ lock(mTaskQueueMutex);
+ mTaskQueue.push(task);
+ return true;
+ }
+
+ uint Thread::GetTaskCount()
+ {
+ return mTaskQueue.size();
+ }
+
+ void Thread::Idle()
+ {
+ mState = THREAD_STATE_IDLE;
+ }
+
+#define try_start_thread(impl)\
+ if (!mImpl) \
+ { \
+ mImpl = new impl(); \
+ if (!mImpl->Start(this, stacksize)) \
+ { \
+ delete mImpl; \
+ mImpl = nullptr; \
+ } \
+ }
+
+ bool Thread::Start(bool isDaemon /*= true*/, uint32 stacksize /*= 0*/)
+ {
+ if (mState != THREAD_STATE_IDLE)
+ return false;
+
+ // Ѿһ֮ǰģر
+ if (mImpl)
+ {
+ delete mImpl;
+ mImpl = nullptr;
+ }
+
+#if ASURA_THREAD_WIN32
+ try_start_thread(ThreadImplWin32);
+#endif
+
+ if (!mImpl)
+ return false;
+
+ mIsDaemon = isDaemon;
+ mStateMutex.Lock();
+ mState = THREAD_STATE_RUNNING;
+ mStateMutex.Unlock();
+ }
+
+ void Thread::Pause()
+ {
+ ASSERT(mImpl);
+
+ lock(mStateMutex);
+ mState = THREAD_STATE_PAUSED;
+ }
+
+ void Thread::Resume()
+ {
+ ASSERT(mImpl);
+
+ lock(mStateMutex);
+ if(mState == THREAD_STATE_PAUSED)
+ mState = THREAD_STATE_RUNNING;
+ }
+
+ void Thread::Stop()
+ {
+ ASSERT(mImpl);
+
+ lock(mStateMutex);
+ mState = THREAD_STATE_STOPPED;
+ }
+
+ void Thread::PauseSync()
+ {
+ Pause();
+ wait(mSemPause);
+ }
+
+ void Thread::ResumeSync()
+ {
+ Resume();
+ wait(mSemResume);
+ }
+
+ void Thread::StopSync()
+ {
+ Stop();
+ wait(mSemStop);
+ }
+
+ void Thread::Join()
+ {
+ ASSERT(mImpl);
+ mImpl->Join();
+ }
+
+ ThreadState Thread::GetState()
+ {
+ ThreadState state;
+ mStateMutex.Lock();
+ state = mState;
+ mStateMutex.Unlock();
+ return state;
+ }
+
+ bool Thread::IsRunning()
+ {
+ ASSERT(mImpl);
+
+ return GetState() == THREAD_STATE_RUNNING;
+ }
+
+ bool Thread::IsPaused()
+ {
+ ASSERT(mImpl);
+
+ return GetState() == THREAD_STATE_PAUSED;
+ }
+
+ bool Thread::IsStopped()
+ {
+ ASSERT(mImpl);
+
+ return GetState() == THREAD_STATE_STOPPED;
+ }
+
+ bool Thread::IsCurrent()
+ {
+ ASSERT(mImpl);
+
+ return mImpl->IsCurrent();
+ }
+
+ const std::string& Thread::GetName()
+ {
+ return mName;
+ }
+
+ void Thread::Process()
+ {
+ LUAX_STATE(mLuaThread);
+
+ do{
+ if (IsRunning())
+ {
+ while (!mTaskQueue.empty())
+ {
+ Task* task = mTaskQueue.front();
+ if (task && task->Execute())
+ {
+ if (mType == THREAD_TYPE_DEFERRED)
+ {
+ mFinishedMutex.Lock();
+ mFinishedTasks.push(task);
+ mFinishedMutex.Unlock();
+ }
+ else if (mType == THREAD_TYPE_IMMEDIATE)
+ {
+ task->Invoke(mCallbackThread);
+ this->LuaxRelease<Task>(state, task);
+ }
+ mTaskQueueMutex.Lock();
+ mTaskQueue.pop();
+ mTaskQueueMutex.Unlock();
+ }
+ }
+ }
+
+ // ˳ѭ
+ if (IsStopped())
+ break;
+
+ // CPUʹ
+ Sleep(mSleepTime);
+
+ } while (mIsDaemon);
+
+ // ػ̣߳еstop״̬
+ if (!mIsDaemon)
+ Stop();
+
+ signal(mSemStop);
+
+ // ״̬ΪIdle
+ Idle();
+ }
+
+ ///
+ /// ӳģʽص
+ ///
+ void Thread::Post()
+ {
+ ASSERT(mType == THREAD_TYPE_DEFERRED);
+
+ LUAX_STATE(mLuaThread);
+ while (!mFinishedTasks.empty())
+ {
+ Task* task = mFinishedTasks.front();
+ if (task)
+ {
+ task->Invoke(mLuaThread);
+ this->LuaxRelease<Task>(state, task);
+ mFinishedMutex.Lock();
+ mFinishedTasks.pop();
+ mFinishedMutex.Unlock();
+ }
+ }
+ }
+
+ void Thread::Sleep(uint ms)
+ {
+ ASSERT(mImpl);
+ if (mImpl)
+ {
+ mImpl->Sleep(ms);
+ }
+ }
+
+ void Thread::SetSleepTime(uint ms)
+ {
+ mSleepTime = ms;
+ }
+
+ }
+} \ No newline at end of file