Second pass idLib integration.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
// The Win32 implementation was reconstructed from the recovered fiber API;
|
||||
// retain the platform-neutral Tungsten include path for callers.
|
||||
#include "idlib/sys/win32/win_fibers.h"
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
#include "sys_threading.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
idSysMutex::idSysMutex()
|
||||
: handle(CreateMutexA(nullptr, FALSE, nullptr)) {
|
||||
}
|
||||
|
||||
idSysMutex::~idSysMutex() {
|
||||
if (handle != nullptr) CloseHandle(static_cast<HANDLE>(handle));
|
||||
handle = nullptr;
|
||||
}
|
||||
|
||||
bool idSysMutex::Lock(const bool blocking) {
|
||||
if (handle == nullptr) return false;
|
||||
const DWORD result = WaitForSingleObject(static_cast<HANDLE>(handle),
|
||||
blocking ? INFINITE : 0);
|
||||
return result == WAIT_OBJECT_0 || result == WAIT_ABANDONED;
|
||||
}
|
||||
|
||||
void idSysMutex::Unlock() {
|
||||
if (handle != nullptr) ReleaseMutex(static_cast<HANDLE>(handle));
|
||||
}
|
||||
|
||||
idSysSignal::idSysSignal(const bool manualReset)
|
||||
: handle(CreateEventA(nullptr, manualReset ? TRUE : FALSE, FALSE, nullptr)) {
|
||||
}
|
||||
|
||||
idSysSignal::~idSysSignal() {
|
||||
if (handle != nullptr) CloseHandle(static_cast<HANDLE>(handle));
|
||||
handle = nullptr;
|
||||
}
|
||||
|
||||
void idSysSignal::Raise() {
|
||||
if (handle != nullptr) SetEvent(static_cast<HANDLE>(handle));
|
||||
}
|
||||
|
||||
void idSysSignal::Clear() {
|
||||
if (handle != nullptr) ResetEvent(static_cast<HANDLE>(handle));
|
||||
}
|
||||
|
||||
bool idSysSignal::Wait(const int timeoutMilliseconds) const {
|
||||
if (handle == nullptr) return false;
|
||||
const DWORD timeout = timeoutMilliseconds < 0
|
||||
? INFINITE
|
||||
: static_cast<DWORD>(timeoutMilliseconds);
|
||||
return WaitForSingleObject(static_cast<HANDLE>(handle), timeout)
|
||||
== WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
idSysThread::idSysThread()
|
||||
: name(), threadHandle(0), isWorker(false), isRunning(false),
|
||||
isTerminating(false), moreWorkToDo(false), signalWorkerDone(true),
|
||||
signalMoreWorkToDo(false), signalMutex() {
|
||||
}
|
||||
|
||||
idSysThread::~idSysThread() {
|
||||
StopThread(true);
|
||||
if (threadHandle != 0) {
|
||||
CloseHandle(reinterpret_cast<HANDLE>(
|
||||
static_cast<std::uintptr_t>(threadHandle)));
|
||||
threadHandle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int idSysThread::Run() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI idSysThread::ThreadProc(void* parameter) {
|
||||
idSysThread* const thread = static_cast<idSysThread*>(parameter);
|
||||
int result = 0;
|
||||
if (thread->isWorker) {
|
||||
for (;;) {
|
||||
thread->signalMutex.Lock();
|
||||
if (!thread->moreWorkToDo) {
|
||||
thread->signalWorkerDone.Raise();
|
||||
thread->signalMutex.Unlock();
|
||||
thread->signalMoreWorkToDo.Wait();
|
||||
continue;
|
||||
}
|
||||
thread->moreWorkToDo = false;
|
||||
thread->signalMoreWorkToDo.Clear();
|
||||
const bool terminate = thread->isTerminating;
|
||||
thread->signalMutex.Unlock();
|
||||
if (terminate) break;
|
||||
result = thread->Run();
|
||||
}
|
||||
thread->signalWorkerDone.Raise();
|
||||
} else {
|
||||
result = thread->Run();
|
||||
}
|
||||
thread->isRunning = false;
|
||||
return static_cast<DWORD>(result);
|
||||
}
|
||||
|
||||
bool idSysThread::StartThread(const char* threadName, const core_t core,
|
||||
const xthreadPriority priority, const int stackSize) {
|
||||
if (isRunning) return false;
|
||||
name = threadName;
|
||||
isTerminating = false;
|
||||
if (threadHandle != 0) {
|
||||
HANDLE oldHandle = reinterpret_cast<HANDLE>(
|
||||
static_cast<std::uintptr_t>(threadHandle));
|
||||
WaitForSingleObject(oldHandle, INFINITE);
|
||||
CloseHandle(oldHandle);
|
||||
threadHandle = 0;
|
||||
}
|
||||
HANDLE handle = CreateThread(nullptr, static_cast<SIZE_T>(stackSize),
|
||||
ThreadProc, this, 0, nullptr);
|
||||
if (handle == nullptr) return false;
|
||||
threadHandle = static_cast<unsigned int>(
|
||||
reinterpret_cast<std::uintptr_t>(handle));
|
||||
static const int priorities[] = {
|
||||
THREAD_PRIORITY_LOWEST,
|
||||
THREAD_PRIORITY_BELOW_NORMAL,
|
||||
THREAD_PRIORITY_NORMAL,
|
||||
THREAD_PRIORITY_ABOVE_NORMAL,
|
||||
THREAD_PRIORITY_HIGHEST
|
||||
};
|
||||
const int priorityIndex = static_cast<int>(priority);
|
||||
if (priorityIndex >= 0 && priorityIndex < 5)
|
||||
SetThreadPriority(handle, priorities[priorityIndex]);
|
||||
if (core != CORE_ANY && static_cast<unsigned int>(core) < 32)
|
||||
SetThreadAffinityMask(handle, std::uintptr_t(1) << static_cast<int>(core));
|
||||
isRunning = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool idSysThread::StartWorkerThread(const char* threadName, const core_t core,
|
||||
const xthreadPriority priority, const int stackSize) {
|
||||
if (isRunning) return false;
|
||||
isWorker = true;
|
||||
signalWorkerDone.Clear();
|
||||
if (!StartThread(threadName, core, priority, stackSize)) return false;
|
||||
signalWorkerDone.Wait();
|
||||
return true;
|
||||
}
|
||||
|
||||
void idSysThread::StopThread(const bool wait) {
|
||||
if (!isRunning) return;
|
||||
if (isWorker) {
|
||||
signalMutex.Lock();
|
||||
moreWorkToDo = true;
|
||||
signalWorkerDone.Clear();
|
||||
isTerminating = true;
|
||||
signalMoreWorkToDo.Raise();
|
||||
signalMutex.Unlock();
|
||||
} else {
|
||||
isTerminating = true;
|
||||
}
|
||||
if (wait) WaitForThread();
|
||||
}
|
||||
|
||||
void idSysThread::WaitForThread() {
|
||||
if (isWorker) {
|
||||
signalWorkerDone.Wait();
|
||||
return;
|
||||
}
|
||||
if (threadHandle == 0) return;
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(
|
||||
static_cast<std::uintptr_t>(threadHandle));
|
||||
WaitForSingleObject(handle, INFINITE);
|
||||
CloseHandle(handle);
|
||||
threadHandle = 0;
|
||||
}
|
||||
|
||||
void idSysThread::SignalWork() {
|
||||
if (!isWorker) return;
|
||||
signalMutex.Lock();
|
||||
moreWorkToDo = true;
|
||||
signalWorkerDone.Clear();
|
||||
signalMoreWorkToDo.Raise();
|
||||
signalMutex.Unlock();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include "../text/str.h"
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum xthreadPriority : int {
|
||||
THREAD_LOWEST = 0,
|
||||
THREAD_BELOW_NORMAL = 1,
|
||||
THREAD_NORMAL = 2,
|
||||
THREAD_ABOVE_NORMAL = 3,
|
||||
THREAD_HIGHEST = 4
|
||||
};
|
||||
|
||||
enum core_t : int {
|
||||
CORE_ANY = -1,
|
||||
CORE_0A = 0,
|
||||
CORE_0B = 1,
|
||||
CORE_1A = 2,
|
||||
CORE_1B = 3,
|
||||
CORE_2A = 4,
|
||||
CORE_2B = 5
|
||||
};
|
||||
|
||||
class idSysMutex {
|
||||
public:
|
||||
void* handle;
|
||||
|
||||
idSysMutex();
|
||||
~idSysMutex();
|
||||
bool Lock(bool blocking = true);
|
||||
void Unlock();
|
||||
|
||||
idSysMutex(const idSysMutex&) = delete;
|
||||
idSysMutex& operator=(const idSysMutex&) = delete;
|
||||
};
|
||||
|
||||
class idSysSignal {
|
||||
public:
|
||||
void* handle;
|
||||
|
||||
explicit idSysSignal(bool manualReset = false);
|
||||
~idSysSignal();
|
||||
void Raise();
|
||||
void Clear();
|
||||
bool Wait(int timeoutMilliseconds = -1) const;
|
||||
|
||||
idSysSignal(const idSysSignal&) = delete;
|
||||
idSysSignal& operator=(const idSysSignal&) = delete;
|
||||
};
|
||||
|
||||
class idSysThread {
|
||||
public:
|
||||
idSysThread();
|
||||
virtual ~idSysThread();
|
||||
virtual int Run();
|
||||
|
||||
bool StartThread(const char* threadName, core_t core = CORE_ANY,
|
||||
xthreadPriority priority = THREAD_NORMAL, int stackSize = 0x20000);
|
||||
bool StartWorkerThread(const char* threadName, core_t core = CORE_ANY,
|
||||
xthreadPriority priority = THREAD_NORMAL, int stackSize = 0x20000);
|
||||
void StopThread(bool wait = true);
|
||||
void WaitForThread();
|
||||
void SignalWork();
|
||||
|
||||
bool IsRunning() const { return isRunning; }
|
||||
bool IsTerminating() const { return isTerminating; }
|
||||
const char* GetName() const { return name.c_str(); }
|
||||
|
||||
idStr name;
|
||||
unsigned int threadHandle;
|
||||
bool isWorker;
|
||||
bool isRunning;
|
||||
volatile bool isTerminating;
|
||||
volatile bool moreWorkToDo;
|
||||
idSysSignal signalWorkerDone;
|
||||
idSysSignal signalMoreWorkToDo;
|
||||
idSysMutex signalMutex;
|
||||
|
||||
private:
|
||||
static DWORD WINAPI ThreadProc(void* parameter);
|
||||
};
|
||||
|
||||
struct ssThreadInfo_t {
|
||||
int spawnId;
|
||||
int objectId;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
#if INTPTR_MAX == INT32_MAX
|
||||
static_assert(sizeof(idSysMutex) == 4, "Recovered idSysMutex ABI changed");
|
||||
static_assert(sizeof(idSysSignal) == 4, "Recovered idSysSignal ABI changed");
|
||||
static_assert(sizeof(idSysThread) == 56, "Recovered idSysThread ABI changed");
|
||||
static_assert(sizeof(ssThreadInfo_t) == 12, "Recovered ssThreadInfo_t ABI changed");
|
||||
#endif
|
||||
Reference in New Issue
Block a user