diff options
Diffstat (limited to 'source/libs/asura-lib-utils/threading')
11 files changed, 585 insertions, 9 deletions
diff --git a/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp b/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp new file mode 100644 index 0000000..7f74cca --- /dev/null +++ b/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp @@ -0,0 +1,40 @@ +#include "../coroutine.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace Threading + { + + LUAX_REGISTRY(Coroutine) + { + LUAX_REGISTER_METHODS(state, + { "New", _New }, + { "Run", _Run } + ); + } + + LUAX_POSTPROCESS(Coroutine) + { + + } + + // Coroutine.New() + LUAX_IMPL_METHOD(Coroutine, _New) + { + LUAX_STATE(L); + + return 0; + } + + // coroutine:Run() + LUAX_IMPL_METHOD(Coroutine, _Run) + { + LUAX_PREPARE(L, Coroutine); + + return 0; + } + + } +} diff --git a/source/libs/asura-lib-utils/threading/binding/_thread.cpp b/source/libs/asura-lib-utils/threading/binding/_thread.cpp new file mode 100644 index 0000000..9f6d228 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/binding/_thread.cpp @@ -0,0 +1,104 @@ +#include "../thread.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace Threading + { + + LUAX_REGISTRY(Thread) + { + LUAX_REGISTER_METHODS(state, + { "New", _New }, + { "Start", _Start }, + { "Join", _Join }, + { "Kill", _Kill }, + { "AddTask", _AddTask }, + { "IsRunning", _IsRunning }, + { "IsCurrent", _IsCurrent }, + { "GetName", _GetName } + ); + } + + LUAX_POSTPROCESS(Thread) + { + + } + + // thread = Thread.New(name) + LUAX_IMPL_METHOD(Thread, _New) + { + LUAX_STATE(L); + + cc8* name = state.GetValue<cc8*>(1, ""); + + Thread* thread = new Thread(name); + thread->PushLuaxUserdata(state); + + return 1; + } + + // thread:Start() + LUAX_IMPL_METHOD(Thread, _Start) + { + LUAX_PREPARE(L, Thread); + self->Start(); + return 0; + } + + // thread:Join() + LUAX_IMPL_METHOD(Thread, _Join) + { + LUAX_PREPARE(L, Thread); + self->Join(); + return 0; + } + + // thread:Kill() + LUAX_IMPL_METHOD(Thread, _Kill) + { + LUAX_PREPARE(L, Thread); + self->Kill(); + return 0; + } + + // successed = thread:AddTask(thread_task) + LUAX_IMPL_METHOD(Thread, _AddTask) + { + LUAX_PREPARE(L, Thread); + + ThreadTask* task = state.GetUserdata<ThreadTask>(2); + self->AddTask(task); + self->LuaxRetain<ThreadTask>(state, task); + return 0; + } + + // thread:IsRunning() + LUAX_IMPL_METHOD(Thread, _IsRunning) + { + LUAX_PREPARE(L, Thread); + + state.Push(self->IsRunning()); + return 0; + } + + // thread:IsCurrent() + LUAX_IMPL_METHOD(Thread, _IsCurrent) + { + LUAX_PREPARE(L, Thread); + + state.Push(self->IsCurrent()); + return 0; + } + + // thread:GetName() + LUAX_IMPL_METHOD(Thread, _GetName) + { + LUAX_PREPARE(L, Thread); + + return 0; + } + + } +} diff --git a/source/libs/asura-lib-utils/threading/coroutine.h b/source/libs/asura-lib-utils/threading/coroutine.h index 1ac6b21..75d9a10 100644 --- a/source/libs/asura-lib-utils/threading/coroutine.h +++ b/source/libs/asura-lib-utils/threading/coroutine.h @@ -28,4 +28,6 @@ namespace AsuraEngine } } +namespace AEThreading = AsuraEngine::Threading; + #endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/mutex.cpp b/source/libs/asura-lib-utils/threading/mutex.cpp index e69de29..e0b6e1e 100644 --- a/source/libs/asura-lib-utils/threading/mutex.cpp +++ b/source/libs/asura-lib-utils/threading/mutex.cpp @@ -0,0 +1,81 @@ +#include <asura-lib-utils/exceptions/exception.h> + +#include "mutex.h" + +namespace AsuraEngine +{ + namespace Threading + { + +#define try_create_mutex(impl)\ + if (!mImpl) \ + { \ + try \ + { \ + mImpl = new impl(); \ + } \ + catch (Exception& e) \ + { \ + mImpl = nullptr; \ + } \ + } + + Mutex::Mutex() + : mImpl(nullptr) + { +#if ASURA_THREAD_WIN32 + try_create_mutex(MutexImplWin32); +#endif + ASSERT(mImpl); + } + + Mutex::~Mutex() + { + delete mImpl; + } + + void Mutex::Lock() + { + ASSERT(mImpl); + + mImpl->Lock(); + } + + void Mutex::Unlock() + { + ASSERT(mImpl); + + mImpl->Unlock(); + } + +#if ASURA_THREAD_WIN32 + MutexImplWin32::MutexImplWin32() + { + //mHandle = ::CreateMutex(NULL, FALSE, NULL); + //if (!mHandle) + // throw Exception("Cant use win32 mutex."); + ::InitializeCriticalSection(&mMutex); + } + + MutexImplWin32::~MutexImplWin32() + { + //::CloseHandle(mHandle); + //mHandle = NULL; + ::DeleteCriticalSection(&mMutex); + } + + void MutexImplWin32::Lock() + { + //::WaitForSingleObject(mHandle, INFINITE); + ::EnterCriticalSection(&mMutex); + } + + void MutexImplWin32::Unlock() + { + //::ReleaseMutex(mHandle); + ::LeaveCriticalSection(&mMutex); + } +#endif // ASURA_THREAD_WIN32 + + } +} diff --git a/source/libs/asura-lib-utils/threading/mutex.h b/source/libs/asura-lib-utils/threading/mutex.h index 893c6e5..5ed45ae 100644 --- a/source/libs/asura-lib-utils/threading/mutex.h +++ b/source/libs/asura-lib-utils/threading/mutex.h @@ -1,21 +1,105 @@ #ifndef __ASURA_MUTEX_H__ #define __ASURA_MUTEX_H__ +#include <asura-lib-utils/type.h> + +#include "../utils_config.h" + +#if ASURA_THREAD_WIN32 + #include <windows.h> +#endif + namespace AsuraEngine { namespace Threading { + class MutexImpl; + class Mutex { public: + Mutex(); + ~Mutex(); + void Lock(); void Unlock(); + private: + + MutexImpl* mImpl; + + }; + + class Lock + { + public: + Lock(Mutex& mutex) + : m(mutex) + { + m.Lock(); + }; + ~Lock() + { + m.Unlock(); + } + private: + void* operator new(size_t); + Mutex& m; + }; + +#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) + + ASURA_ABSTRACT class MutexImpl + { + public: + + MutexImpl() {}; + virtual ~MutexImpl() {}; + + virtual void Lock() = 0; + virtual void Unlock() = 0; + + }; + +#if ASURA_THREAD_WIN32 + + //https://blog.csdn.net/l799623787/article/details/18259949 + class MutexImplWin32 ASURA_FINAL : public MutexImpl + { + public: + + MutexImplWin32(); + ~MutexImplWin32(); + + void Lock() override; + void Unlock() override; + + private: + + //HANDLE mHandle; + CRITICAL_SECTION mMutex; + }; +#endif // ASURA_THREAD_WIN32 + +#if ASURA_THREAD_STD + + class MutexImplSTD ASURA_FINAL : public MutexImpl + { + }; + +#endif // ASURA_THREAD_STD + } } +namespace AEThreading = AsuraEngine::Threading; + #endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread.cpp b/source/libs/asura-lib-utils/threading/thread.cpp index c77f3ab..d1b055d 100644 --- a/source/libs/asura-lib-utils/threading/thread.cpp +++ b/source/libs/asura-lib-utils/threading/thread.cpp @@ -1,13 +1,92 @@ #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 { - bool Thread::Enqueue(ThreadTask* task) + Thread::Thread(const std::string& name) + : mName(name) + { + } + + Thread::~Thread() + { + delete mImpl; + } + +#define try_start_thread(impl)\ + if (!mImpl) \ + { \ + mImpl = new impl(); \ + if (!mImpl->Start(this, stacksize)) \ + { \ + delete mImpl; \ + mImpl = nullptr; \ + } \ + } + + bool Thread::AddTask(ThreadTask* task) + { + mTaskQueue.push(task); + return true; + } + + void Thread::Start(uint32 stacksize) + { +#if ASURA_THREAD_WIN32 + try_start_thread(ThreadImplWin32); +#endif + + assert(mImpl); + } + + void Thread::Join() + { + assert(mImpl); + mImpl->Join(); + } + + void Thread::Kill() + { + assert(mImpl); + mImpl->Kill(); + } + + bool Thread::IsRunning() + { + assert(mImpl); + return mImpl->IsRunning(); + } + + bool Thread::IsCurrent() + { + assert(mImpl); + return mImpl->IsCurrent(); + } + + const std::string& Thread::GetName() + { + return mName; + } + + void Thread::Execute() { + while (!mTaskQueue.empty()) + { + ThreadTask* task = mTaskQueue.front(); + if (task->Execute()) + task->Invoke(); + mMutex.Lock(); + mTaskQueue.pop(); + mMutex.Unlock(); + } } } diff --git a/source/libs/asura-lib-utils/threading/thread.h b/source/libs/asura-lib-utils/threading/thread.h index 0058144..24b549c 100644 --- a/source/libs/asura-lib-utils/threading/thread.h +++ b/source/libs/asura-lib-utils/threading/thread.h @@ -1,10 +1,13 @@ #ifndef __ASURA_THREAD_H__ #define __ASURA_THREAD_H__ +#include <string> #include <queue> + #include <asura-lib-utils/scripting/portable.hpp> #include "thread_task.h" +#include "mutex.h" namespace AsuraEngine { @@ -23,21 +26,55 @@ namespace AsuraEngine LUAX_DECL_FACTORY(Thread); - bool Enqueue(ThreadTask* task); + Thread(const std::string& name = ""); + ~Thread(); + + bool AddTask(ThreadTask* task); + + void Start(uint32 stacksize = 0); + + /// + /// ǿֹ̡߳עҪnewdeleteִ֮TerminateThreadڼʹnewˡ + /// https://blog.csdn.net/anye3000/article/details/7470674 + /// + void Kill(); + + /// + /// ̵߳ȴ߳̽żִС + /// + void Join(); + + bool IsRunning(); - void Run(); + bool IsCurrent(); + + /// + /// ִС + /// + void Execute(); + + const std::string& GetName(); private: + LUAX_DECL_METHOD(_New); + LUAX_DECL_METHOD(_Start); + LUAX_DECL_METHOD(_Join); + LUAX_DECL_METHOD(_Kill); + LUAX_DECL_METHOD(_AddTask); + LUAX_DECL_METHOD(_IsRunning); + LUAX_DECL_METHOD(_IsCurrent); + LUAX_DECL_METHOD(_GetName); + /// - /// С + /// С /// std::queue<ThreadTask*> mTaskQueue; - ThreadImpl* mImpl; + Mutex mMutex; - LUAX_DECL_METHOD(_Enqueue); - LUAX_DECL_METHOD(_Run); + ThreadImpl* mImpl; + std::string mName; }; @@ -51,6 +88,15 @@ namespace AsuraEngine ASURA_ABSTRACT class ThreadImpl { public: + ThreadImpl() {}; + virtual ~ThreadImpl() {}; + + virtual bool Start(Thread* thread, uint32 stacksize = 0) = 0; + virtual void Join() = 0; + virtual void Kill() = 0; + + virtual bool IsRunning() = 0; + virtual bool IsCurrent() = 0; }; diff --git a/source/libs/asura-lib-utils/threading/thread_impl_std.h b/source/libs/asura-lib-utils/threading/thread_impl_std.h index e69de29..0e7d3da 100644 --- a/source/libs/asura-lib-utils/threading/thread_impl_std.h +++ b/source/libs/asura-lib-utils/threading/thread_impl_std.h @@ -0,0 +1,43 @@ +#ifndef __ASURA_THREAD_STD_H__ +#define __ASURA_THREAD_STD_H__ + +#include "../utils_config.h" + +#if ASURA_THREAD_STD + +#include <windows.h> + +#include "thread.h" + +namespace AsuraEngine +{ + namespace Threading + { + + /// + /// Threadstd::threadʵ֡ + /// + class ThreadImplSTD : public ThreadImpl + { + public: + + ThreadImplSTD(); + ~ThreadImplSTD(); + + bool Start(Thread* thread, uint32 stacksize) override; + void Join() override; + void Kill() override; + + bool IsRunning() override; + bool IsCurrent() override; + + private: + + }; + + } +} + +#endif // #if ASURA_THREAD_STD + +#endif // __ASURA_THREAD_STD_H__
\ 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 e69de29..fd1b066 100644 --- a/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp +++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp @@ -0,0 +1,69 @@ +#include "thread_impl_win32.h" +#include "thread.h" + +namespace AsuraEngine +{ + namespace Threading + { + + static DWORD WINAPI _thread_win32_runner(LPVOID param) + { + Thread* thread = (Thread*)param; + thread->Execute(); + return 0; + } + + ThreadImplWin32::ThreadImplWin32() + { + } + + ThreadImplWin32::~ThreadImplWin32() + { + if (!mHandle) return; + ::CloseHandle(mHandle); + mHandle = 0; + } + + bool ThreadImplWin32::Start(Thread* thread, uint32 stacksize/*=0*/) + { + assert(!IsRunning()); + mHandle = ::CreateThread( + NULL + , stacksize + , _thread_win32_runner + , thread + , 0 /*е*/ + , NULL); + + return mHandle; + } + + void ThreadImplWin32::Join() + { + // ̵߳ȴ̷߳ + ::WaitForSingleObject(mHandle, INFINITE); + } + + void ThreadImplWin32::Kill() + { + ::TerminateThread(mHandle, FALSE); + } + + bool ThreadImplWin32::IsRunning() + { + if (mHandle) { + DWORD exitCode = 0; + // https://blog.csdn.net/yuanmeng567/article/details/19485719 + ::GetExitCodeThread(mHandle, &exitCode); + return exitCode == STILL_ACTIVE; + } + return false; + } + + bool ThreadImplWin32::IsCurrent() + { + return mHandle == ::GetCurrentThread(); + } + + } +}
\ No newline at end of file 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 3dd2a8e..361152f 100644 --- a/source/libs/asura-lib-utils/threading/thread_impl_win32.h +++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.h @@ -6,6 +6,7 @@ #if ASURA_THREAD_WIN32 #include <windows.h> + #include "thread.h" namespace AsuraEngine @@ -20,6 +21,16 @@ namespace AsuraEngine { public: + ThreadImplWin32(); + ~ThreadImplWin32(); + + bool Start(Thread* thread, uint32 stacksize) override; + void Join() override; + + void Kill() override; + + bool IsRunning() override; + bool IsCurrent() override; private: @@ -32,4 +43,4 @@ namespace AsuraEngine #endif // #if ASURA_THREAD_WIN32 -#endif
\ No newline at end of file +#endif // __ASURA_THREAD_WIN32_H__
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread_task.h b/source/libs/asura-lib-utils/threading/thread_task.h index 35e159c..1ea0a1a 100644 --- a/source/libs/asura-lib-utils/threading/thread_task.h +++ b/source/libs/asura-lib-utils/threading/thread_task.h @@ -2,6 +2,7 @@ #define __ASURA_THRAD_TASK_H__ #include <asura-lib-utils/type.h> +#include <asura-lib-utils/scripting/portable.hpp> namespace AsuraEngine { @@ -11,12 +12,28 @@ namespace AsuraEngine /// /// ϣһ̴̳߳TaskдExecute /// - ASURA_ABSTRACT class ThreadTask + 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; + }; } |