138 lines
4.0 KiB
C++
138 lines
4.0 KiB
C++
#include <ntstatus.h>
|
|
#include "threading.h"
|
|
|
|
static HANDLE waitArray[WAITID_LAST];
|
|
|
|
void waitclear()
|
|
{
|
|
for(int i = 0; i < WAITID_LAST; i++)
|
|
unlock((WAIT_ID)i);
|
|
}
|
|
|
|
void wait(WAIT_ID id)
|
|
{
|
|
WaitForSingleObject(waitArray[id], INFINITE);
|
|
}
|
|
|
|
bool waitfor(WAIT_ID id, unsigned int Milliseconds)
|
|
{
|
|
return WaitForSingleObject(waitArray[id], Milliseconds) == 0;
|
|
}
|
|
|
|
void lock(WAIT_ID id)
|
|
{
|
|
ResetEvent(waitArray[id]);
|
|
}
|
|
|
|
void unlock(WAIT_ID id)
|
|
{
|
|
SetEvent(waitArray[id]);
|
|
}
|
|
|
|
bool waitislocked(WAIT_ID id)
|
|
{
|
|
return !WaitForSingleObject(waitArray[id], 0) == WAIT_OBJECT_0;
|
|
}
|
|
|
|
void waitinitialize()
|
|
{
|
|
for(int i = 0; i < WAITID_LAST; i++)
|
|
waitArray[i] = CreateEventW(NULL, TRUE, TRUE, NULL);
|
|
}
|
|
|
|
void waitdeinitialize()
|
|
{
|
|
for(int i = 0; i < WAITID_LAST; i++)
|
|
{
|
|
wait((WAIT_ID)i);
|
|
CloseHandle(waitArray[i]);
|
|
}
|
|
}
|
|
|
|
bool SectionLockerGlobal::m_Initialized = false;
|
|
bool SectionLockerGlobal::m_SRWLocks = false;
|
|
SRWLOCK SectionLockerGlobal::m_srwLocks[SectionLock::LockLast];
|
|
SectionLockerGlobal::owner_info SectionLockerGlobal::m_owner[SectionLock::LockLast];
|
|
|
|
CRITICAL_SECTION SectionLockerGlobal::m_crLocks[SectionLock::LockLast];
|
|
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_InitializeSRWLock;
|
|
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockShared;
|
|
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockExclusive;
|
|
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_ReleaseSRWLockShared;
|
|
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_ReleaseSRWLockExclusive;
|
|
|
|
void SectionLockerGlobal::Initialize()
|
|
{
|
|
// This is supposed to only be called once, but
|
|
// create a flag anyway
|
|
if(m_Initialized)
|
|
return;
|
|
|
|
// Attempt to read the SRWLock API
|
|
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
|
m_InitializeSRWLock = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "InitializeSRWLock");
|
|
m_AcquireSRWLockShared = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "AcquireSRWLockShared");
|
|
m_AcquireSRWLockExclusive = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "AcquireSRWLockExclusive");
|
|
m_ReleaseSRWLockShared = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "ReleaseSRWLockShared");
|
|
m_ReleaseSRWLockExclusive = (SRWLOCKFUNCTION)GetProcAddress(hKernel32, "ReleaseSRWLockExclusive");
|
|
|
|
m_SRWLocks = m_InitializeSRWLock &&
|
|
m_AcquireSRWLockShared &&
|
|
m_AcquireSRWLockExclusive &&
|
|
m_ReleaseSRWLockShared &&
|
|
m_ReleaseSRWLockExclusive;
|
|
|
|
if(m_SRWLocks) // Prefer SRWLocks
|
|
{
|
|
// Destroy previous data if any existed
|
|
memset(m_srwLocks, 0, sizeof(m_srwLocks));
|
|
|
|
for(int i = 0; i < ARRAYSIZE(m_srwLocks); i++)
|
|
m_InitializeSRWLock(&m_srwLocks[i]);
|
|
}
|
|
else // Fall back to critical sections otherwise
|
|
{
|
|
// Destroy previous data if any existed
|
|
memset(m_crLocks, 0, sizeof(m_crLocks));
|
|
|
|
for(int i = 0; i < ARRAYSIZE(m_crLocks); i++)
|
|
InitializeCriticalSection(&m_crLocks[i]);
|
|
}
|
|
|
|
m_Initialized = true;
|
|
}
|
|
|
|
void SectionLockerGlobal::Deinitialize()
|
|
{
|
|
if(!m_Initialized)
|
|
return;
|
|
|
|
if(m_SRWLocks)
|
|
{
|
|
for(int i = 0; i < ARRAYSIZE(m_srwLocks); i++)
|
|
{
|
|
// Wait for the lock's ownership to be released
|
|
m_AcquireSRWLockExclusive(&m_srwLocks[i]);
|
|
m_ReleaseSRWLockExclusive(&m_srwLocks[i]);
|
|
|
|
// Invalidate data
|
|
memset(&m_srwLocks[i], 0, sizeof(SRWLOCK));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(int i = 0; i < ARRAYSIZE(m_crLocks); i++)
|
|
{
|
|
// Wait for the lock's ownership to be released
|
|
EnterCriticalSection(&m_crLocks[i]);
|
|
LeaveCriticalSection(&m_crLocks[i]);
|
|
|
|
// Delete critical section
|
|
DeleteCriticalSection(&m_crLocks[i]);
|
|
memset(&m_crLocks[i], 0, sizeof(CRITICAL_SECTION));
|
|
}
|
|
}
|
|
|
|
m_Initialized = false;
|
|
}
|