diff options
Diffstat (limited to 'source/libs/asura-lib-utils/threading/thread.cpp')
-rw-r--r-- | source/libs/asura-lib-utils/threading/thread.cpp | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/source/libs/asura-lib-utils/threading/thread.cpp b/source/libs/asura-lib-utils/threading/thread.cpp new file mode 100644 index 0000000..0f4f5da --- /dev/null +++ b/source/libs/asura-lib-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 |