From f4c338c63f3456a8eccd56c35e233843687d55be Mon Sep 17 00:00:00 2001 From: chai Date: Fri, 29 Mar 2019 00:43:25 +0800 Subject: *thread --- .../asura-lib-utils/threading/binding/_thread.cpp | 21 +++++++-- source/libs/asura-lib-utils/threading/mutex.h | 16 +++---- source/libs/asura-lib-utils/threading/task.cpp | 12 +++++ source/libs/asura-lib-utils/threading/task.h | 11 ++--- source/libs/asura-lib-utils/threading/thread.cpp | 14 +++--- source/libs/asura-lib-utils/threading/thread.h | 52 ++++++++++++++++++---- .../threading/thread_impl_posix.cpp | 9 ++++ .../threading/thread_impl_win32.cpp | 8 +++- .../libs/asura-lib-utils/threading/thread_task.cpp | 0 .../libs/asura-lib-utils/threading/thread_task.h | 44 ++++++++++++++++++ 10 files changed, 156 insertions(+), 31 deletions(-) create mode 100644 source/libs/asura-lib-utils/threading/thread_task.cpp create mode 100644 source/libs/asura-lib-utils/threading/thread_task.h (limited to 'source/libs/asura-lib-utils/threading') diff --git a/source/libs/asura-lib-utils/threading/binding/_thread.cpp b/source/libs/asura-lib-utils/threading/binding/_thread.cpp index 00252a9..9403486 100644 --- a/source/libs/asura-lib-utils/threading/binding/_thread.cpp +++ b/source/libs/asura-lib-utils/threading/binding/_thread.cpp @@ -18,7 +18,8 @@ namespace AsuraEngine { "AddTask", _AddTask }, { "IsRunning", _IsRunning }, { "IsCurrent", _IsCurrent }, - { "GetName", _GetName } + { "GetName", _GetName }, + { "Sleep", _Sleep } ); } @@ -81,7 +82,7 @@ namespace AsuraEngine LUAX_PREPARE(L, Thread); state.Push(self->IsRunning()); - return 0; + return 1; } // thread:IsCurrent() @@ -90,7 +91,7 @@ namespace AsuraEngine LUAX_PREPARE(L, Thread); state.Push(self->IsCurrent()); - return 0; + return 1; } // thread:GetName() @@ -98,6 +99,20 @@ namespace AsuraEngine { LUAX_PREPARE(L, Thread); + state.Push(self->GetName()); + return 1; + } + + // Thread.Sleep(milliseconds) + LUAX_IMPL_METHOD(Thread, _Sleep) + { + LUAX_STATE(L); + int ms = state.CheckValue(1); +#if ASURA_THREAD_WIN32 + ::Sleep(ms); +#elif ASURA_THREAD_STD + +#endif return 0; } diff --git a/source/libs/asura-lib-utils/threading/mutex.h b/source/libs/asura-lib-utils/threading/mutex.h index 51fe63e..7e7d877 100644 --- a/source/libs/asura-lib-utils/threading/mutex.h +++ b/source/libs/asura-lib-utils/threading/mutex.h @@ -32,15 +32,15 @@ namespace AsuraEngine }; - class Lock + class _mutex_locker { public: - Lock(Mutex& mutex) + _mutex_locker(Mutex& mutex) : m(mutex) { m.Lock(); }; - ~Lock() + ~_mutex_locker() { m.Unlock(); } @@ -50,11 +50,11 @@ namespace AsuraEngine }; // 将所在的栈从此位置开始到退栈处作为临界区锁定。 -#define lock(mutex) Lock _asura_scoped_lock_0x0_(mutex) -#define lock2(mutex) Lock _asura_scoped_lock_0x1_(mutex) -#define lock3(mutex) Lock _asura_scoped_lock_0x2_(mutex) -#define lock4(mutex) Lock _asura_scoped_lock_0x3_(mutex) -#define lock5(mutex) Lock _asura_scoped_lock_0x4_(mutex) +#define lock(mutex) _mutex_locker _asura_scoped_lock_0x0(mutex) +#define lock2(mutex) _mutex_locker _asura_scoped_lock_0x1(mutex) +#define lock3(mutex) _mutex_locker _asura_scoped_lock_0x2(mutex) +#define lock4(mutex) _mutex_locker _asura_scoped_lock_0x3(mutex) +#define lock5(mutex) _mutex_locker _asura_scoped_lock_0x4(mutex) ASURA_ABSTRACT class MutexImpl { diff --git a/source/libs/asura-lib-utils/threading/task.cpp b/source/libs/asura-lib-utils/threading/task.cpp index e69de29..2e84ed4 100644 --- a/source/libs/asura-lib-utils/threading/task.cpp +++ b/source/libs/asura-lib-utils/threading/task.cpp @@ -0,0 +1,12 @@ +#include "task.h" +#include "../scripting/lua_env.h" + +using namespace AEScripting; + +namespace AsuraEngine +{ + namespace Threading + { + + } +} diff --git a/source/libs/asura-lib-utils/threading/task.h b/source/libs/asura-lib-utils/threading/task.h index 9f78860..9c0b12c 100644 --- a/source/libs/asura-lib-utils/threading/task.h +++ b/source/libs/asura-lib-utils/threading/task.h @@ -13,12 +13,12 @@ namespace AsuraEngine /// 希望放在另一个线程处理的任务,继承Task并重写Execute方法。 /// ASURA_ABSTRACT class Task - : virtual public AEScripting::NativeAccessor + : public virtual AEScripting::NativeAccessor { public: - Task(); - virtual ~Task(); + Task() {}; + virtual ~Task() {}; /// /// 执行任务,完成后返回true,调用回调函数。 @@ -28,10 +28,11 @@ namespace AsuraEngine /// /// 调用回调。 /// - virtual void Invoke(lua_State* thread) = 0; + virtual void Invoke() = 0; - protected: + protected: + // 取回调函数 Luax::LuaxMemberRef mCallback; }; diff --git a/source/libs/asura-lib-utils/threading/thread.cpp b/source/libs/asura-lib-utils/threading/thread.cpp index 51738de..9c71ace 100644 --- a/source/libs/asura-lib-utils/threading/thread.cpp +++ b/source/libs/asura-lib-utils/threading/thread.cpp @@ -13,9 +13,6 @@ namespace AsuraEngine Thread::Thread(Luax::LuaxState& father, const std::string& name) : mName(name) { - mState = lua_newthread(father); - SetLuaxMemberRef(father, mStateRef, -1); - lua_pop(father, 1); // mState } Thread::~Thread() @@ -79,13 +76,18 @@ namespace AsuraEngine return mName; } - void Thread::Execute() + void Thread::Process() { + LUAX_STATE(AEScripting::LuaEnv::Get()->GetMainState()); while (!mTaskQueue.empty()) { Task* task = mTaskQueue.front(); - if (task->Execute()) - task->Invoke(mState); + if (task && task->Execute()) + { + // unsafe + task->Invoke(); + this->LuaxRelease(state, task); + } mMutex.Lock(); mTaskQueue.pop(); diff --git a/source/libs/asura-lib-utils/threading/thread.h b/source/libs/asura-lib-utils/threading/thread.h index 1bd5f15..3fa079a 100644 --- a/source/libs/asura-lib-utils/threading/thread.h +++ b/source/libs/asura-lib-utils/threading/thread.h @@ -16,6 +16,28 @@ namespace AsuraEngine class ThreadImpl; + /// + /// 线程的几种不同的实现: + /// 1: Deferred(延迟模式),线程上的任务完成后,需要手动在主线程调用Post方法, + /// 在主线程调回调函数,将发布从异步改为同步操作,解决主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, + }; + /// /// 线程主体,每个线程维护一个task queue。 /// @@ -26,7 +48,7 @@ namespace AsuraEngine LUAX_DECL_FACTORY(Thread); - Thread(Luax::LuaxState& father, const std::string& name = ""); + Thread(ThreadType type, Luax::LuaxState& luaThread, const std::string& name = ""); ~Thread(); bool AddTask(Task* task); @@ -34,8 +56,10 @@ namespace AsuraEngine void Start(uint32 stacksize = 0); /// - /// 强制终止线程。注意要避免在new和delete之间执行TerminateThread,否则程序将不能在继续使用new了。 + /// 强制终止线程。注意要避免在new和delete之间执行TerminateThread,否则程序将不能在继 + /// 续使用new了。 /// https://blog.csdn.net/anye3000/article/details/7470674 + /// 注意:尽量不要使用这个接口,应该让线程自己运行到终点,而不是手动关闭它。 /// void Kill(); @@ -51,12 +75,21 @@ namespace AsuraEngine /// /// 执行任务队列。 /// - void Execute(); + void Process(); const std::string& GetName(); + /// + /// 回调。 + /// + void Post(); + private: + //----------------------------------------------------------------------------// + + LUAX_DECL_ENUM(ThreadType); + LUAX_DECL_METHOD(_New); LUAX_DECL_METHOD(_Start); LUAX_DECL_METHOD(_Join); @@ -65,6 +98,10 @@ namespace AsuraEngine LUAX_DECL_METHOD(_IsRunning); LUAX_DECL_METHOD(_IsCurrent); LUAX_DECL_METHOD(_GetName); + LUAX_DECL_METHOD(_Sleep); + LUAX_DECL_METHOD(_Post); + + //----------------------------------------------------------------------------// ThreadImpl* mImpl; std::string mName; @@ -75,11 +112,10 @@ namespace AsuraEngine std::queue mTaskQueue; Mutex mMutex; - /// - /// 此线程的lua执行栈,为了避免和主执行栈冲突 - /// - lua_State* mState; - Luax::LuaxMemberRef mStateRef; + lua_State* mLuaThread; + + std::queue mFinishedTasks; + Mutex mFinishedMutex; }; diff --git a/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp b/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp index e69de29..d2ad7af 100644 --- a/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp +++ b/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp @@ -0,0 +1,9 @@ +#include "thread_impl_posix.h" + +namespace AsuraEngine +{ + namespace Threading + { + + } +} \ No newline at end of file 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 fd1b066..ad859b6 100644 --- a/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp +++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp @@ -1,6 +1,8 @@ #include "thread_impl_win32.h" #include "thread.h" +#include + namespace AsuraEngine { namespace Threading @@ -9,7 +11,11 @@ namespace AsuraEngine static DWORD WINAPI _thread_win32_runner(LPVOID param) { Thread* thread = (Thread*)param; - thread->Execute(); + while (thread->IsRunning()) + { + thread->Process(); + ::Sleep(100); + } return 0; } diff --git a/source/libs/asura-lib-utils/threading/thread_task.cpp b/source/libs/asura-lib-utils/threading/thread_task.cpp new file mode 100644 index 0000000..e69de29 diff --git a/source/libs/asura-lib-utils/threading/thread_task.h b/source/libs/asura-lib-utils/threading/thread_task.h new file mode 100644 index 0000000..1ea0a1a --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_task.h @@ -0,0 +1,44 @@ +#ifndef __ASURA_THRAD_TASK_H__ +#define __ASURA_THRAD_TASK_H__ + +#include +#include + +namespace AsuraEngine +{ + namespace Threading + { + + /// + /// 希望放在另一个线程处理的任务,继承Task并重写Execute方法。 + /// + ASURA_ABSTRACT class ThreadTask + : virtual public AEScripting::NativeAccessor + { + public: + + ThreadTask(); + virtual ~ThreadTask(); + + /// + /// 执行任务,完成后返回true,调用回调函数。 + /// + virtual bool Execute() = 0; + + /// + /// 调用回调。 + /// + virtual void Invoke() = 0; + + protected: + + Luax::LuaxMemberRef mCallback; + + }; + + } +} + +namespace AEThreading = AsuraEngine::Threading; + +#endif \ No newline at end of file -- cgit v1.1-26-g67d0