summaryrefslogtreecommitdiff
path: root/source/libs
diff options
context:
space:
mode:
Diffstat (limited to 'source/libs')
-rw-r--r--source/libs/asura-lib-utils/io/binding/_data_buffer.cpp1
-rw-r--r--source/libs/asura-lib-utils/io/io_batch_task.cpp0
-rw-r--r--source/libs/asura-lib-utils/io/io_batch_task.h31
-rw-r--r--source/libs/asura-lib-utils/io/io_task.cpp4
-rw-r--r--source/libs/asura-lib-utils/io/io_task.h2
-rw-r--r--source/libs/asura-lib-utils/scripting/lua_env.h14
-rw-r--r--source/libs/asura-lib-utils/threading/binding/_thread.cpp154
-rw-r--r--source/libs/asura-lib-utils/threading/semaphore.cpp88
-rw-r--r--source/libs/asura-lib-utils/threading/semaphore.h70
-rw-r--r--source/libs/asura-lib-utils/threading/task.h4
-rw-r--r--source/libs/asura-lib-utils/threading/thread.cpp217
-rw-r--r--source/libs/asura-lib-utils/threading/thread.h108
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_win32.cpp11
-rw-r--r--source/libs/asura-lib-utils/threading/thread_impl_win32.h3
14 files changed, 617 insertions, 90 deletions
diff --git a/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp b/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp
index 6725bc4..cd73b31 100644
--- a/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp
+++ b/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp
@@ -42,6 +42,7 @@ namespace AsuraEngine
size_t size = lua_tonumber(L, 1);
DataBuffer* buffer = new DataBuffer(size);
buffer->PushLuaxUserdata(state);
+ return 1;
}
else
{
diff --git a/source/libs/asura-lib-utils/io/io_batch_task.cpp b/source/libs/asura-lib-utils/io/io_batch_task.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/io_batch_task.cpp
diff --git a/source/libs/asura-lib-utils/io/io_batch_task.h b/source/libs/asura-lib-utils/io/io_batch_task.h
new file mode 100644
index 0000000..c0be921
--- /dev/null
+++ b/source/libs/asura-lib-utils/io/io_batch_task.h
@@ -0,0 +1,31 @@
+#ifndef __ASURA_IO_BATCH_TASK_H__
+#define __ASURA_IO_BATCH_TASK_H__
+
+#include "io_task.h"
+
+namespace AsuraEngine
+{
+ namespace IO
+ {
+
+ ///
+ /// ÅúÁ¿´¦Àí¶Á»òÕßд¡£Ò»´ÎÐÔÌá½»Ò»¸ötable£¬ÒÀ´Î´¦Àíºó·µ»Ø½á¹û¡£
+ ///
+ class IOBatchTask ASURA_FINAL : public AEThreading::Task
+ {
+ public:
+
+ private:
+
+ ///
+ /// ÈÎÎñ±í£¬Ã¿Ò»ÌõµÄ½á¹¹ÈçÏ£º
+ /// { path = "", }
+ ///
+ Luax::LuaxMemberRef mTasks;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/io/io_task.cpp b/source/libs/asura-lib-utils/io/io_task.cpp
index 38e21ad..361b9c5 100644
--- a/source/libs/asura-lib-utils/io/io_task.cpp
+++ b/source/libs/asura-lib-utils/io/io_task.cpp
@@ -38,11 +38,11 @@ namespace AsuraEngine
return true;
}
- void IOTask::Invoke()
+ void IOTask::Invoke(lua_State* invokeThreaad)
{
if (mCallback)
{
- LuaxScopedState state(LuaEnv::Get()->GetMainThread());
+ LuaxScopedState state(invokeThreaad);
if (PushLuaxMemberRef(state, mCallback))
{
PushLuaxMemberRef(state, mBufferRef);
diff --git a/source/libs/asura-lib-utils/io/io_task.h b/source/libs/asura-lib-utils/io/io_task.h
index 5f454ee..8f04142 100644
--- a/source/libs/asura-lib-utils/io/io_task.h
+++ b/source/libs/asura-lib-utils/io/io_task.h
@@ -35,7 +35,7 @@ namespace AsuraEngine
~IOTask();
bool Execute() override ;
- void Invoke() override;
+ void Invoke(lua_State* invokeThreaad) override;
private:
diff --git a/source/libs/asura-lib-utils/scripting/lua_env.h b/source/libs/asura-lib-utils/scripting/lua_env.h
index bae6c4c..e2fc4fc 100644
--- a/source/libs/asura-lib-utils/scripting/lua_env.h
+++ b/source/libs/asura-lib-utils/scripting/lua_env.h
@@ -16,8 +16,8 @@ namespace AsuraEngine
{
///
- /// ³ÌÐòͨ¹ýÕâ¸ö½Ó¿Ú·ÃÎÊÖ÷lua state¡£Asura³ÌÐòµÄ˼ÏëÊÇ£¬½ø³ÌÖ÷Ïß³Ìά»¤Ò»¸öluaÐéÄâ»ú£¬Ó¦ÓõÄÖ÷ÒªÂß¼­ÅÜÔÚ´ËÐéÄâ»úµÄÖ÷lua
- /// Ïß³ÌÀ»òÕß½ÐÖ÷Õ»À¡£
+ /// ³ÌÐòͨ¹ýÕâ¸ö½Ó¿Ú·ÃÎÊÖ÷lua state¡£Asura³ÌÐòµÄ˼ÏëÊÇ£¬½ø³ÌÖ÷Ïß³Ìά»¤Ò»¸öluaÐéÄâ»ú£¬Ó¦ÓÃ
+ /// µÄÖ÷ÒªÂß¼­ÅÜÔÚ´ËÐéÄâ»úµÄÖ÷luaÏß³ÌÀ»òÕß½ÐÖ÷Õ»À¡£
///
class LuaEnv ASURA_FINAL : public Singleton<LuaEnv>
{
@@ -51,14 +51,14 @@ namespace AsuraEngine
private:
///
- /// Ö÷Ï̱߳£´æÒ»¸öÖ÷luaÐéÄâ»ú¡£Ò»¸öAsura³ÌÐòÓÀÔ¶Ö»ÓÐÒ»¸öÖ÷ÐéÄâ»ú£¬´ó²¿·Ö´úÂë¶¼ÔÚÕâ¸öÐéÄâ»úÖÐÔËÐУ¬ÇÒÖ»ÄÜÉèÖÃÒ»´Î¡£
- /// Ö÷Ïß³Ì\Ö÷Ö´ÐÐÕ»¶ÔÓ¦µÄÊÇglobal_StateÀïÃæµÄ£º
+ /// Ö÷Ï̱߳£´æÒ»¸öÖ÷luaÐéÄâ»ú¡£Ò»¸öAsura³ÌÐòÓÀÔ¶Ö»ÓÐÒ»¸öÖ÷ÐéÄâ»ú£¬´ó²¿·Ö´úÂë¶¼ÔÚÕâ¸öÐé
+ /// Äâ»úÖÐÔËÐУ¬ÇÒÖ»ÄÜÉèÖÃÒ»´Î¡£Ö÷Ïß³Ì\Ö÷Ö´ÐÐÕ»¶ÔÓ¦µÄÊÇglobal_StateÀïÃæµÄ£º
///
/// struct lua_State *mainthread;
///
- /// ʹÓÃlua_newstate()£¬»á´´½¨Ò»¸öÐéÄâ»ú£¬°üº¬Ò»¸öglobal_State½á¹¹£¬²¢´´½¨Ò»¸öÕâ¸öÐéÄâ»úµÄÖ÷Ïß³Ìlua_State²¢·µ»Ø¡£
- /// global_StateÓÉÕâ¸öÐéÄâ»úµÄËùÓÐÏ̹߳²Ïí£¬³ýÁ˵ÚÒ»¸öÖ÷Ïß³ÌÓÉlua_newstate()´´½¨Í⣬ÆäÓàÏß³ÌÓÉlua_newthread()
- /// ´´½¨¡£
+ /// ʹÓÃlua_newstate()£¬»á´´½¨Ò»¸öÐéÄâ»ú£¬°üº¬Ò»¸öglobal_State½á¹¹£¬²¢´´½¨Ò»¸öÕâ¸öÐé
+ /// Äâ»úµÄÖ÷Ïß³Ìlua_State²¢·µ»Ø¡£global_StateÓÉÕâ¸öÐéÄâ»úµÄËùÓÐÏ̹߳²Ïí£¬³ýÁ˵ÚÒ»¸öÖ÷
+ /// Ïß³ÌÓÉlua_newstate()´´½¨Í⣬ÆäÓàÏß³ÌÓÉlua_newthread()´´½¨¡£
///
Luax::LuaxVM* mVM;
diff --git a/source/libs/asura-lib-utils/threading/binding/_thread.cpp b/source/libs/asura-lib-utils/threading/binding/_thread.cpp
index 9403486..a5aff03 100644
--- a/source/libs/asura-lib-utils/threading/binding/_thread.cpp
+++ b/source/libs/asura-lib-utils/threading/binding/_thread.cpp
@@ -1,5 +1,4 @@
#include "../thread.h"
-#include "../task.h"
using namespace std;
@@ -12,67 +11,114 @@ namespace AsuraEngine
{
LUAX_REGISTER_METHODS(state,
{ "New", _New },
+ { "AddTask", _AddTask },
{ "Start", _Start },
+ { "Idle", _Idle },
+ { "Pause", _Pause },
+ { "Resume", _Resume },
+ { "Stop", _Stop },
{ "Join", _Join },
- { "Kill", _Kill },
- { "AddTask", _AddTask },
{ "IsRunning", _IsRunning },
+ { "IsPaused", _IsPaused },
+ { "IsStopped", _IsStopped },
{ "IsCurrent", _IsCurrent },
+ { "Sleep", _Sleep },
+ { "Post", _Post },
{ "GetName", _GetName },
- { "Sleep", _Sleep }
+ { "GetType", _GetType },
+ { "GetState", _GetState }
);
}
LUAX_POSTPROCESS(Thread)
{
-
+ LUAX_REGISTER_ENUM(state, "EThreadType",
+ { "DEFERRED", THREAD_TYPE_DEFERRED },
+ { "IMMEDIATE", THREAD_TYPE_IMMEDIATE }
+ );
+ LUAX_REGISTER_ENUM(state, "EThreadState",
+ { "READY", THREAD_STATE_IDLE },
+ { "RUNNING", THREAD_STATE_RUNNING },
+ { "PAUSED", THREAD_STATE_PAUSED },
+ { "STOPPED", THREAD_STATE_STOPPED }
+ );
}
- // thread = Thread.New(name)
+ // thread = Thread.New(thread_type, sleepTime, name)
LUAX_IMPL_METHOD(Thread, _New)
{
LUAX_STATE(L);
- cc8* name = state.GetValue<cc8*>(1, "");
+ ThreadType type = (ThreadType)state.GetValue<int>(1, THREAD_TYPE_DEFERRED);
+ uint sleepTime = state.GetValue<uint>(2,1);
+ cc8* name = state.GetValue<cc8*>(3, "");
- Thread* thread = new Thread(state, name);
+ Thread* thread = new Thread(state, type, sleepTime, name);
thread->PushLuaxUserdata(state);
return 1;
}
- // thread:Start()
+ // thread:AddTask(task)
+ LUAX_IMPL_METHOD(Thread, _AddTask)
+ {
+ LUAX_PREPARE(L, Thread);
+
+ Task* task = state.GetUserdata<Task>(2);
+ self->AddTask(task);
+ self->LuaxRetain<Task>(state, task);
+ return 0;
+ }
+
+ // successed = thread:Start(isDeamon, stackSize)
LUAX_IMPL_METHOD(Thread, _Start)
{
LUAX_PREPARE(L, Thread);
- self->Start();
+
+ bool isDaemon = state.GetValue(2, true);
+ uint stackSize = state.GetValue(3, 0);
+
+ state.Push(self->Start(isDaemon, stackSize));
+ return 1;
+ }
+
+ // thread:Idle()
+ LUAX_IMPL_METHOD(Thread, _Idle)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Idle();
return 0;
}
- // thread:Join()
- LUAX_IMPL_METHOD(Thread, _Join)
+ // thread:Pause()
+ LUAX_IMPL_METHOD(Thread, _Pause)
{
LUAX_PREPARE(L, Thread);
- self->Join();
+ self->Pause();
return 0;
}
- // thread:Kill()
- LUAX_IMPL_METHOD(Thread, _Kill)
+ // thread:Resume()
+ LUAX_IMPL_METHOD(Thread, _Resume)
{
LUAX_PREPARE(L, Thread);
- self->Kill();
+ self->Resume();
return 0;
}
- // successed = thread:AddTask(task)
- LUAX_IMPL_METHOD(Thread, _AddTask)
+ // thread:Stop()
+ LUAX_IMPL_METHOD(Thread, _Stop)
{
LUAX_PREPARE(L, Thread);
+ self->Stop();
+ return 0;
+ }
- Task* task = state.GetUserdata<Task>(2);
- self->AddTask(task);
- self->LuaxRetain<Task>(state, task);
+ // thread:Join()
+ LUAX_IMPL_METHOD(Thread, _Join)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Join();
return 0;
}
@@ -80,39 +126,83 @@ namespace AsuraEngine
LUAX_IMPL_METHOD(Thread, _IsRunning)
{
LUAX_PREPARE(L, Thread);
-
state.Push(self->IsRunning());
return 1;
}
+ // thread:IsPaused()
+ LUAX_IMPL_METHOD(Thread, _IsPaused)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->IsPaused());
+ return 1;
+ }
+
+ // thread:IsStopped()
+ LUAX_IMPL_METHOD(Thread, _IsStopped)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->IsStopped());
+ return 1;
+ }
+
// thread:IsCurrent()
LUAX_IMPL_METHOD(Thread, _IsCurrent)
{
LUAX_PREPARE(L, Thread);
-
state.Push(self->IsCurrent());
return 1;
}
+ // Thread.Sleep(ms)
+ LUAX_IMPL_METHOD(Thread, _Sleep)
+ {
+ LUAX_STATE(L);
+ uint ms = state.GetValue(1, 0);
+#ifdef _WIN32
+ ::Sleep(ms);
+#endif
+ return 0;
+ }
+
+ // thread:Post()
+ LUAX_IMPL_METHOD(Thread, _Post)
+ {
+ LUAX_PREPARE(L, Thread);
+ self->Post();
+ return 0;
+ }
+
// thread:GetName()
LUAX_IMPL_METHOD(Thread, _GetName)
{
LUAX_PREPARE(L, Thread);
-
state.Push(self->GetName());
return 1;
}
- // Thread.Sleep(milliseconds)
- LUAX_IMPL_METHOD(Thread, _Sleep)
+ // thread:GetType()
+ LUAX_IMPL_METHOD(Thread, _GetType)
{
- LUAX_STATE(L);
- int ms = state.CheckValue<int>(1);
-#if ASURA_THREAD_WIN32
- ::Sleep(ms);
-#elif ASURA_THREAD_STD
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->mType);
+ return 1;
+ }
-#endif
+ // thread:GetState()
+ LUAX_IMPL_METHOD(Thread, _GetState)
+ {
+ LUAX_PREPARE(L, Thread);
+ state.Push(self->mState);
+ return 1;
+ }
+
+ // thread:SetSleepTime(sleepTime)
+ LUAX_IMPL_METHOD(Thread, _SetSleepTime)
+ {
+ LUAX_PREPARE(L, Thread);
+ uint time = state.CheckValue<uint>(2);
+ self->SetSleepTime(time);
return 0;
}
diff --git a/source/libs/asura-lib-utils/threading/semaphore.cpp b/source/libs/asura-lib-utils/threading/semaphore.cpp
new file mode 100644
index 0000000..d59ec78
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/semaphore.cpp
@@ -0,0 +1,88 @@
+#include "../exceptions/exception.h"
+#include "../type.h"
+
+#include "semaphore.h"
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+#define try_create_semaphore(impl) \
+ if (!mImpl) \
+ { \
+ try \
+ { \
+ mImpl = new impl(init_count); \
+ } \
+ catch (Exception& e) \
+ { \
+ mImpl = nullptr; \
+ } \
+ }
+
+ Semaphore::Semaphore(unsigned int init_count)
+ : mImpl(nullptr)
+ {
+#ifdef ASURA_THREAD_WIN32
+ try_create_semaphore(SemaphoreWin32);
+#endif
+ ASSERT(mImpl);
+ }
+
+ Semaphore::~Semaphore()
+ {
+ if (mImpl) delete mImpl;
+ }
+
+ void Semaphore::Signal()
+ {
+ ASSERT(mImpl);
+ mImpl->Signal();
+ }
+
+ void Semaphore::Wait(int timeout)
+ {
+ ASSERT(mImpl);
+ mImpl->Wait(timeout);
+ }
+
+#if ASURA_THREAD_WIN32
+
+ SemaphoreWin32::SemaphoreWin32(unsigned int init_value)
+ : SemaphoreImpl(init_value)
+ {
+ mSem = CreateSemaphore(NULL, init_value, UINT_MAX, NULL);
+ if (!mSem)
+ throw Exception("Cant use win32 semaphore.");
+ }
+
+ SemaphoreWin32::~SemaphoreWin32()
+ {
+ CloseHandle(mSem);
+ }
+
+ void SemaphoreWin32::Signal()
+ {
+ InterlockedIncrement(&mCount);
+ if (ReleaseSemaphore(mSem, 1, NULL) == FALSE)
+ InterlockedDecrement(&mCount);
+ }
+
+ bool SemaphoreWin32::Wait(int timeout)
+ {
+ int result;
+ result = WaitForSingleObject(mSem, timeout < 0 ? INFINITE : timeout);
+ if (result == WAIT_OBJECT_0)
+ {
+ InterlockedDecrement(&mCount);
+ return true;
+ }
+ else
+ return false;
+ }
+
+#endif // ASURA_THREAD_WIN32
+
+ }
+} \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/semaphore.h b/source/libs/asura-lib-utils/threading/semaphore.h
new file mode 100644
index 0000000..80773d8
--- /dev/null
+++ b/source/libs/asura-lib-utils/threading/semaphore.h
@@ -0,0 +1,70 @@
+#ifndef __ASURA_SEMAPHORE_H__
+#define __ASURA_SEMAPHORE_H__
+
+#include "../utils_config.h"
+
+#if ASURA_THREAD_WIN32
+#include <windows.h>
+#endif
+
+namespace AsuraEngine
+{
+ namespace Threading
+ {
+
+ class SemaphoreImpl;
+
+ ///
+ /// ÐźÅÁ¿
+ ///
+ class Semaphore
+ {
+ public:
+
+ Semaphore(unsigned int init_count = 1);
+ ~Semaphore();
+
+ void Signal();
+ void Wait(int timeout = 0);
+
+ private:
+ SemaphoreImpl* mImpl;
+ };
+
+ class SemaphoreImpl
+ {
+ public:
+ SemaphoreImpl(unsigned int init_value)
+ : mCount(init_value)
+ {
+ };
+ virtual ~SemaphoreImpl() {};
+ virtual void Signal() = 0;
+ virtual bool Wait(int timeout) = 0;
+ inline int Current() { return mCount; }
+ protected:
+ unsigned int mCount;
+ };
+
+#define wait(sem) sem.Wait();
+#define signal(sem) sem.Signal();
+
+#if ASURA_THREAD_WIN32
+
+ class SemaphoreWin32 : public SemaphoreImpl
+ {
+ public:
+ SemaphoreWin32(unsigned int init_value);
+ ~SemaphoreWin32();
+ void Signal() override;
+ bool Wait(int timeout) override;
+ private:
+ HANDLE mSem;
+ };
+
+#endif // ASURA_THREAD_WIN32
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/source/libs/asura-lib-utils/threading/task.h b/source/libs/asura-lib-utils/threading/task.h
index 9c0b12c..fb7aa5f 100644
--- a/source/libs/asura-lib-utils/threading/task.h
+++ b/source/libs/asura-lib-utils/threading/task.h
@@ -26,9 +26,9 @@ namespace AsuraEngine
virtual bool Execute() = 0;
///
- /// µ÷Óûص÷¡£
+ /// µ÷Óûص÷¡£ÔÚinvoke threadÀïÃæ»Øµ÷¡£
///
- virtual void Invoke() = 0;
+ virtual void Invoke(lua_State* invokeThreaad) = 0;
protected:
diff --git a/source/libs/asura-lib-utils/threading/thread.cpp b/source/libs/asura-lib-utils/threading/thread.cpp
index 628eee4..0f4f5da 100644
--- a/source/libs/asura-lib-utils/threading/thread.cpp
+++ b/source/libs/asura-lib-utils/threading/thread.cpp
@@ -10,14 +10,50 @@ namespace AsuraEngine
namespace Threading
{
- Thread::Thread(ThreadType type, Luax::LuaxState& luaThread, const std::string& name/* = ""*/)
+ 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()
{
- delete mImpl;
+ 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)\
@@ -31,20 +67,72 @@ namespace AsuraEngine
} \
}
- bool Thread::AddTask(Task* task)
+ bool Thread::Start(bool isDaemon /*= true*/, uint32 stacksize /*= 0*/)
{
- lock(mMutex);
- mTaskQueue.push(task);
- return true;
- }
+ if (mState != THREAD_STATE_IDLE)
+ return false;
+
+ // Èç¹ûÒѾ­´æÔÚÒ»¸ö֮ǰ´´½¨µÄ£¬¹Ø±ÕËü¡£
+ if (mImpl)
+ {
+ delete mImpl;
+ mImpl = nullptr;
+ }
- void Thread::Start(uint32 stacksize)
- {
#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()
@@ -53,21 +141,40 @@ namespace AsuraEngine
mImpl->Join();
}
- void Thread::Kill()
+ ThreadState Thread::GetState()
{
- ASSERT(mImpl);
- mImpl->Kill();
+ ThreadState state;
+ mStateMutex.Lock();
+ state = mState;
+ mStateMutex.Unlock();
+ return state;
}
bool Thread::IsRunning()
{
ASSERT(mImpl);
- return mImpl->IsRunning();
+
+ 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();
}
@@ -78,22 +185,88 @@ namespace AsuraEngine
void Thread::Process()
{
- LUAX_STATE(AEScripting::LuaEnv::Get()->GetMainThread());
- while (!mTaskQueue.empty())
+ 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 = mTaskQueue.front();
- if (task && task->Execute())
+ Task* task = mFinishedTasks.front();
+ if (task)
{
- // unsafe
- task->Invoke();
+ task->Invoke(mLuaThread);
this->LuaxRelease<Task>(state, task);
+ mFinishedMutex.Lock();
+ mFinishedTasks.pop();
+ mFinishedMutex.Unlock();
}
+ }
+ }
- mMutex.Lock();
- mTaskQueue.pop();
- mMutex.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
diff --git a/source/libs/asura-lib-utils/threading/thread.h b/source/libs/asura-lib-utils/threading/thread.h
index 3928963..0e75770 100644
--- a/source/libs/asura-lib-utils/threading/thread.h
+++ b/source/libs/asura-lib-utils/threading/thread.h
@@ -8,6 +8,7 @@
#include "task.h"
#include "mutex.h"
+#include "semaphore.h"
namespace AsuraEngine
{
@@ -22,20 +23,19 @@ namespace AsuraEngine
/// ÔÚÖ÷Ï̵߳÷»Øµ÷º¯Êý£¬½«·¢²¼´ÓÒì²½¸ÄΪͬ²½²Ù×÷£¬½â¾öÖ÷lua_State³åÍ»µÄÎÊÌâ¡£
/// 2: Immediate£¨Á¢¼´Ä£Ê½£©£¬Ã¿Ò»¸öÏß³Ìά»¤Ò»¸ölua_newthread´´½¨³öÀ´µÄlua_State¡£
/// »Øµ÷º¯ÊýÔÚ²»Í¬µÄlua_StateÖе÷Ó㬱ÜÃⲻͬµÄÏ̷߳ÃÎÊͬһ¸ölua_State¡£
- /// 3: Daemon£¨ÊØ»¤Ä£Ê½£©£¬Ï̻߳áÒ»Ö±ÔËÐÐÔÚºǫ́¡£
///
enum ThreadType
{
THREAD_TYPE_DEFERRED,
THREAD_TYPE_IMMEDIATE,
- THREAD_TYPE_DAEMON
};
enum ThreadState
{
- THREAD_STATE_RUNNING,
- THREAD_STATE_DEAD,
- THREAD_STATE_SUSPEND,
+ THREAD_STATE_IDLE, ///< ÏÐÖ㬻¹Î´´´½¨Äں˶ÔÏó
+ THREAD_STATE_RUNNING, ///< ÕýÔÚÔËÐÐÑ­»·
+ THREAD_STATE_PAUSED, ///< ÔÚÑ­»·ÖÐÔÝÍ£
+ THREAD_STATE_STOPPED, ///< Í˳öÑ­»·
};
///
@@ -48,27 +48,54 @@ namespace AsuraEngine
LUAX_DECL_FACTORY(Thread);
- Thread(ThreadType type, Luax::LuaxState& luaThread, const std::string& name = "");
+ Thread(lua_State* luaThread, ThreadType type = THREAD_TYPE_DEFERRED, uint sleepTime = 1, const std::string& name = "");
~Thread();
bool AddTask(Task* task);
+ ///
+ /// »ñµÃµÈ´ý´¦ÀíµÄÈÎÎñÊý
+ ///
+ uint GetTaskCount();
+
+ void Idle();
- void Start(uint32 stacksize = 0);
+ ///
+ /// ´´½¨Äں˶ÔÏ󣬲¢ÔËÐС£Èç¹ûÊÇdaemon£¬»áµÈ´ýÊÖ¶¯stop¡£·ñÔò»áÔÚijʱ¿Ì¶ÓÁÐÍê³Éºó×Ô¶¯stop¡£
+ ///
+ bool Start(bool daemon = true, uint32 stacksize = 0);
///
- /// Ç¿ÖÆÖÕÖ¹Ï̡߳£×¢ÒâÒª±ÜÃâÔÚnewºÍdeleteÖ®¼äÖ´ÐÐTerminateThread£¬·ñÔò³ÌÐò½«²»ÄÜÔÚ¼Ì
- /// ÐøÊ¹ÓÃnewÁË¡£
- /// https://blog.csdn.net/anye3000/article/details/7470674
- /// ×¢Ò⣺¾¡Á¿²»ÒªÊ¹ÓÃÕâ¸ö½Ó¿Ú£¬Ó¦¸ÃÈÃÏß³Ì×Ô¼ºÔËÐе½Öյ㣬¶ø²»ÊÇÊÖ¶¯¹Ø±ÕËü¡£
+ /// ·Çͬ²½Ï߳̿ØÖÆ£¬²»ÊÇʵʱµÄ¡£¿ÉÄÜÐèÒªÔÚÖ÷Ïß³ÌÀïʹÓÃIsº¯ÊýÈ·Èϵ½´ïÖ¸¶¨×´Ì¬¡£
///
- void Kill();
+ void Pause();
+ void Resume();
+ void Stop();
+
+ ///
+ /// ͬ²½Ï߳̿ØÖÆ£¬»áµÈ·µ»ØÀ´Ðźźó¼ÌÐøÏòÏÂÖ´ÐС£»áÔì³ÉÖ÷Ï̵߳ȴý¡£
+ ///
+ void PauseSync();
+ void ResumeSync();
+ void StopSync();
///
/// ¸¸Ï̵߳ȴý±¾Ï߳̽áÊøºó²Å¼ÌÐøÖ´ÐС£
///
void Join();
+ ThreadState GetState();
+
+ ///
+ /// Âß¼­²ãÃæµÄÏß³Ì״̬£º
+ /// 1: Idle£¨¿ÕÏУ©£¬Ï̴߳´½¨ºóµÄĬÈÏ״̬£¬¿ÉÒÔËæÊ±¼ÓÈÎÎñ²¢ÇÒStart¡£
+ /// 2: Running£¨ÔËÐУ©£¬Äں˶ÔÏóß´´½¨£¬ÒѾ­´¦ÓÚÄں˵÷¶ÈÖУ¬²¢´¦Àí¾ßÌåTask¡£
+ /// 3: Paused£¨ÔÝÍ££©£¬ÒÀÈ»´æÔÚÓÚÄÚºËÖУ¬µ«ÊÇÌø¹ýÁ˶ÔÈÎÎñµÄ´¦Àí£¬Âß¼­ÉÏÔÝÍ£¡£
+ /// 4: Stopped£¨Í£Ö¹£©£¬ÒÀÈ»´æÔÚÓÚÄÚºËÖУ¬µ«ÊÇÒѾ­ÎÞ·¨¼ÌÐø´¦ÀíÈÎÎñ¡£
+ ///
+ bool IsIdle();
bool IsRunning();
+ bool IsPaused();
+ bool IsStopped();
bool IsCurrent();
@@ -84,41 +111,84 @@ namespace AsuraEngine
///
void Post();
+ ///
+ /// ÐÝÃߺ¯Êý
+ ///
+ void Sleep(uint ms);
+
+ ///
+ /// ÉèÖÃÐÝÃßʱ¼ä
+ ///
+ void SetSleepTime(uint ms);
+
private:
//----------------------------------------------------------------------------//
LUAX_DECL_ENUM(ThreadType);
+ LUAX_DECL_ENUM(ThreadState);
LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_AddTask);
LUAX_DECL_METHOD(_Start);
+ LUAX_DECL_METHOD(_Idle);
+ LUAX_DECL_METHOD(_Pause);
+ LUAX_DECL_METHOD(_Resume);
+ LUAX_DECL_METHOD(_Stop);
LUAX_DECL_METHOD(_Join);
- LUAX_DECL_METHOD(_Kill);
- LUAX_DECL_METHOD(_AddTask);
LUAX_DECL_METHOD(_IsRunning);
+ LUAX_DECL_METHOD(_IsPaused);
+ LUAX_DECL_METHOD(_IsStopped);
LUAX_DECL_METHOD(_IsCurrent);
- LUAX_DECL_METHOD(_GetName);
LUAX_DECL_METHOD(_Sleep);
LUAX_DECL_METHOD(_Post);
+ LUAX_DECL_METHOD(_GetName);
LUAX_DECL_METHOD(_GetType);
+ LUAX_DECL_METHOD(_GetState);
+ LUAX_DECL_METHOD(_SetSleepTime);
//----------------------------------------------------------------------------//
+ ///
+ /// ´Ë´ÎÔËÐÐÊÇ·ñÊÇÊØ»¤Ä£Ê½¡£
+ ///
+ bool mIsDaemon;
+
+ lua_State* mLuaThread;
+
ThreadImpl* mImpl;
std::string mName;
ThreadType mType;
+ uint mSleepTime;
+
+ ThreadState mState;
+ Mutex mStateMutex;
+
+ ///
+ /// ͬ²½¿ØÖÆÏà¹ØµÄÐźÅÁ¿
+ ///
+ Semaphore mSemPause;
+ Semaphore mSemResume;
+ Semaphore mSemStop;
///
/// ´ý´¦ÀíµÄÈÎÎñ¶ÓÁС£
///
std::queue<Task*> mTaskQueue;
- Mutex mMutex;
-
- lua_State* mLuaThread;
+ Mutex mTaskQueueMutex;
+ ///
+ /// ÑÓ³ÙģʽʹÓÃ
+ ///
std::queue<Task*> mFinishedTasks;
Mutex mFinishedMutex;
+ ///
+ /// Á¢¼´Ä£Ê½Ê¹Ó㬻ص÷ʹÓõÄluaÏß³Ì
+ ///
+ lua_State* mCallbackThread;
+ Luax::LuaxMemberRef mCallbackThreadRef;
+
};
///
@@ -138,6 +208,8 @@ namespace AsuraEngine
virtual void Join() = 0;
virtual void Kill() = 0;
+ virtual void Sleep(uint ms) = 0;
+
virtual bool IsRunning() = 0;
virtual bool IsCurrent() = 0;
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp b/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp
index ad859b6..6871c2d 100644
--- a/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp
+++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp
@@ -11,11 +11,7 @@ namespace AsuraEngine
static DWORD WINAPI _thread_win32_runner(LPVOID param)
{
Thread* thread = (Thread*)param;
- while (thread->IsRunning())
- {
- thread->Process();
- ::Sleep(100);
- }
+ thread->Process();
return 0;
}
@@ -55,6 +51,11 @@ namespace AsuraEngine
::TerminateThread(mHandle, FALSE);
}
+ void ThreadImplWin32::Sleep(uint ms)
+ {
+ ::Sleep(ms);
+ }
+
bool ThreadImplWin32::IsRunning()
{
if (mHandle) {
diff --git a/source/libs/asura-lib-utils/threading/thread_impl_win32.h b/source/libs/asura-lib-utils/threading/thread_impl_win32.h
index 361152f..a22aeef 100644
--- a/source/libs/asura-lib-utils/threading/thread_impl_win32.h
+++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.h
@@ -26,9 +26,10 @@ namespace AsuraEngine
bool Start(Thread* thread, uint32 stacksize) override;
void Join() override;
-
void Kill() override;
+ void Sleep(uint ms) override;
+
bool IsRunning() override;
bool IsCurrent() override;