Initial commit

This commit is contained in:
2026-04-03 00:22:39 -05:00
commit eca1e8c458
945 changed files with 218160 additions and 0 deletions

322
ZUtil/ZThread.cpp Normal file
View File

@@ -0,0 +1,322 @@
#include <ZUtil/ZThread.hpp>
#include <ZUtil/ZLog.hpp>
#include <ZSTL/ZString.hpp>
#ifdef _MSC_VER //begin Microsoft Visual C++ specific code
#include <windows.h>
#undef CreateMutex
#undef CreateEvent
const DWORD MS_VC_EXCEPTION=0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
//This disgusting little hack sets the thread's name in the MSVC debugger
void NativeSetThreadName(const char* threadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = (DWORD)~0;
info.dwFlags = 0;
__try
{
RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
#else
#define NativeSetThreadName(name)
#endif //end Microsoft Visual C++ specific code
/*************************************************************************/
ZThread::ZThread(ZString _threadName)
:
ThreadName(_threadName),
bShouldShutdown(false), bShouldPause(false),
ThreadContext(),
ThreadLock(),
InitEvent(),
PreviousTickCount(0), CurrentTickCount(0),
bIsRunning(false), bIsInitialized(false)
{
}
/*************************************************************************/
ZThread::~ZThread()
{
ShutdownThread();
}
/*************************************************************************/
int ZThread::InitThread(void *_runnable)
{
ZThread *thr = ((ZThread*)_runnable);
NativeSetThreadName(thr->GetThreadName().Data());
//TODO - hack for now, need to fix CreateThread
thr->ThreadContext.ThreadId = ZConcurrency::GetThreadId();
thr->initThread();
thr->bIsInitialized = true;
thr->InitEvent.Notify();
thr->Run();
return 0;
}
/*************************************************************************/
void ZThread::Run()
{
uint64_t dt;
bIsRunning = true;
while (!bShouldShutdown)
{
while (bShouldPause)
ZConcurrency::YieldThread();
ExecuteThreadRequests();
PreviousTickCount = CurrentTickCount;
CurrentTickCount = ZConcurrency::GetTicks();
dt = CurrentTickCount - PreviousTickCount;
switch (run(dt))
{
case ZTR_LOOP: continue;
case ZTR_PAUSE: bShouldPause = true; break;
case ZTR_TERMINATE: bShouldShutdown = true; break;
default: bShouldShutdown = true; break;
}
}
ExecuteThreadRequests();
shutdownThread();
bIsInitialized = false;
bIsRunning = false;
}
/*************************************************************************/
void ZThread::AddThreadRequest(ZPtr<ZThreadRequest> _request, bool _wait)
{
//If this is thread adding a request to itself, don't deadlock
if(IsCallerTheThread()) {
_request->Execute(this);
return;
}
ThreadLock.Acquire();
{
ZTRCallbacks.PushBack(_request);
}
ThreadLock.Release();
if (_wait)
_request->Wait();
}
/*************************************************************************/
void ZThread::AddCallbackRequest(ZThreadCallbackFunc function, void* arg, bool async)
{
ZThreadCallbackRequest req;
//If this is the thread adding a callback to itself, don't deadlock
if(IsCallerTheThread()) {
function(this, arg);
return;
}
req.arg = arg;
req.callback = function;
req.doneEvent = (async ? NULL : SST_Concurrency_CreateEvent());
ThreadLock.Acquire();
{
Callbacks.PushBack(req);
}
ThreadLock.Release();
//Non-async -> wait for done
if(!async) {
SST_Concurrency_WaitEvent(req.doneEvent, SST_WAIT_INFINITE);
SST_Concurrency_DestroyEvent(req.doneEvent);
}
}
/*************************************************************************/
void ZThread::ExecuteThreadRequests()
{
ZList< ZPtr<ZThreadRequest> > persistentRequests;
ThreadLock.Acquire();
while (!ZTRCallbacks.Empty())
{
//Don't execute if we are told to stop
if (ZTRCallbacks.Front()->Stop)
{
ZTRCallbacks.Front()->Persist = false;
}
else
{
ZTRCallbacks.Front()->CompletedEvent.Reset();
ZTRCallbacks.Front()->Execute(this);
ZTRCallbacks.Front()->CompletedEvent.Notify();
}
//If we are to persist, do so
if (ZTRCallbacks.Front()->Persist)
persistentRequests.PushBack(ZTRCallbacks.PopFront());
else
ZTRCallbacks.PopFront();
}
while(!Callbacks.Empty()) {
ZThreadCallbackRequest& req = Callbacks.Front();
req.callback(this, req.arg);
if(req.doneEvent) {
SST_Concurrency_SignalEvent(req.doneEvent);
}
Callbacks.PopFront();
}
//Swap back in persistent requests
ZTRCallbacks.Swap(persistentRequests);
ThreadLock.Release();
}
/*************************************************************************/
bool ZThread::StartThread()
{
bShouldShutdown = false;
bShouldPause = false;
ThreadContext = ZConcurrency::CreateThread(ZThread::InitThread, this);
if (!ThreadContext.IsValid())
return false;
return true;
}
/*************************************************************************/
void ZThread::ShutdownThread()
{
bShouldShutdown = true;
if (ThreadContext.IsValid())
{
ZConcurrency::WaitThread(ThreadContext);
ZConcurrency::DestroyThread(ThreadContext);
ThreadContext.Invalidate();
}
}
/*************************************************************************/
void ZThread::PauseThread()
{
bShouldPause = true;
}
/*************************************************************************/
void ZThread::RestartThread()
{
bShouldPause = false;
}
/*************************************************************************/
bool ZThread::ThreadRunning()
{
return bIsRunning;
}
/*************************************************************************/
bool ZThread::ThreadInitialized()
{
return bIsInitialized;
}
/*************************************************************************/
uint32_t ZThread::GetThreadId()
{
return ThreadContext.ThreadId;
}
/*************************************************************************/
ZString ZThread::GetThreadName()
{
ZString name;
ThreadLock.Acquire();
name = ThreadName;
ThreadLock.Release();
return name;
}
/*************************************************************************/
void ZThread::WaitInitialized()
{
InitEvent.Wait();
}
/*************************************************************************/
void ZThread::WaitShutdown()
{
if (ThreadContext.IsValid())
ZConcurrency::WaitThread(ThreadContext);
}
/*************************************************************************/
bool ZThread::IsCallerTheThread()
{
uint32_t callerThreadID = SST_Concurrency_GetThreadId();
return (callerThreadID == this->GetThreadId());
}