TgUINTPTR tgTR_Create(
TgPLATFORM_THREAD_FCN pfnThread, PC_TgVOID pParam, C_TgUINT32 uiStack, C_ETgTHREAD_PRIORITY enPriority, CPCU_TgCHAR szName
) {
#pragma pack(push,8)
typedef struct
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} THREADNAME_INFO;
#pragma pack(pop)
TgUINT32 uiThreadID;
THREADNAME_INFO name_data;
C_TgUINTPTR hThread = _beginthreadex( 0, uiStack, pfnThread, pParam, 0, &uiThreadID );
#if TgS_WIDE_CHAR
TgANSICHAR szNameAnsi[1024];
sprintf(szNameAnsi, "%S", szName);
name_data.szName = szNameAnsi;
#else
name_data.szName = szName;
#endif
name_data.dwType = 0x1000;
name_data.dwThreadID = uiThreadID;
name_data.dwFlags = 0;
Sleep(10);
__try
{
RaiseException( 0x406D1388, 0, sizeof(name_data) / sizeof(ULONG_PTR), (ULONG_PTR*)&name_data );
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
};
switch (enPriority)
{
case ETgTHREAD_PRIORITY__CRITICAL:
TgVERIFY(0 != SetThreadPriority( (HANDLE)hThread, THREAD_PRIORITY_TIME_CRITICAL ));
break;
case ETgTHREAD_PRIORITY__HIGHEST:
TgVERIFY(0 != SetThreadPriority( (HANDLE)hThread, THREAD_PRIORITY_HIGHEST ));
break;
case ETgTHREAD_PRIORITY__HIGH:
TgVERIFY(0 != SetThreadPriority( (HANDLE)hThread, THREAD_PRIORITY_ABOVE_NORMAL ));
break;
case ETgTHREAD_PRIORITY__NORMAL:
TgVERIFY(0 != SetThreadPriority( (HANDLE)hThread, THREAD_PRIORITY_NORMAL ));
break;
case ETgTHREAD_PRIORITY__LOW:
TgVERIFY(0 != SetThreadPriority( (HANDLE)hThread, THREAD_PRIORITY_BELOW_NORMAL ));
break;
case ETgTHREAD_PRIORITY__LOWEST:
TgVERIFY(0 != SetThreadPriority( (HANDLE)hThread, THREAD_PRIORITY_LOWEST ));
break;
default:
TgS_NO_DEFAULT(break);
};
return (hThread);
};
TgVOID tgTR_Yield_Thread()
{
SwitchToThread();
};
TgVOID tgTR_Sleep( C_TgUINT32 uiSleep_MS )
{
Sleep( uiSleep_MS );
};
TgVOID tgTR_Close( C_TgUINTPTR uiThread_Id )
{
while (WAIT_OBJECT_0 != WaitForSingleObject( (HANDLE)uiThread_Id, INFINITE ));
TgVERIFY( 0 != CloseHandle( (HANDLE)uiThread_Id ) );
};
TgUINTPTR tgTR_Query_Id()
{
return (GetCurrentThreadId());
};
static TgFLOAT64 s_fFreq;
static LARGE_INTEGER s_iStart;
static TgFLOAT32 s_fLast;
static TgFLOAT32 s_fElapsed;
static TgFLOAT32 s_fStop;
TgFLOAT32 tgTM_Query_Absolute_Time()
{
LARGE_INTEGER iTime;
QueryPerformanceCounter( &iTime );
return ((TgFLOAT32)(((TgFLOAT64)(iTime.QuadPart - s_iStart.QuadPart)) * s_fFreq));
};
TgFLOAT32 tgTM_Query_Time()
{
return (tgPM_FSEL_F32(-s_fStop, tgTM_Query_Absolute_Time(), s_fStop ));
};
TgFLOAT32 tgTM_Elapsed_Time()
{
return (s_fElapsed);
};
TgVOID tgTM_Init()
{
LARGE_INTEGER iPerf;
QueryPerformanceFrequency( &iPerf );
s_fFreq = 1.0 / (TgFLOAT64)iPerf.QuadPart;
tgTM_Reset();
};
TgVOID tgTM_Reset()
{
QueryPerformanceCounter( &s_iStart );
s_fLast = tgTM_Query_Absolute_Time();
s_fElapsed = 1.0F / 60.0F;
s_fStop = 0.0F;
};
TgVOID tgTM_Start()
{
if (!(s_fStop <= 0.0F))
{
s_fLast = tgTM_Query_Absolute_Time();
s_fStop = 0.0F;
};
};
TgVOID tgTM_Stop()
{
if (!(s_fStop > 0.0F))
{
s_fStop = s_fLast;
};
};
TgVOID tgTM_Update()
{
if (!(s_fStop > 0.0F))
{
C_TgFLOAT32 fTime = tgTM_Query_Absolute_Time();
s_fElapsed = tgCM_MAX_F32( TgEPS_F32, fTime - s_fLast );
s_fLast = fTime;
s_fStop = 0.0F;
};
};
TgVOID tgTM_Step( C_TgFLOAT32 fTimeAdvance )
{
s_fStop += fTimeAdvance;
};
static TgVOID File_Error( C_TgSINTPTR iFile )
{
const DWORD dwError = GetLastError();
BY_HANDLE_FILE_INFORMATION sData;
TCHAR szBuf[256];
LPVOID lpMsgBuf;
TgASSERT((TgSINTPTR)INVALID_HANDLE_VALUE != iFile);
GetFileInformationByHandle( (HANDLE)iFile, &sData );
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, 0, NULL
);
tgSZ_PrintF( szBuf, 256, TgT("File_Read failed with error %d: %s"), dwError, lpMsgBuf );
LocalFree( lpMsgBuf );
TgCRITICAL_MSGF( 0, TgT("%s\n"), szBuf );
OutputDebugString( szBuf );
TgCRITICAL( TgFALSE );
};
TgRESULT tgIO_File_Open( P_TgSINTPTR piFile, CPC_TgCHAR pszFile, ETgFILE_IO_ACCESS enAccess )
{
DWORD dwDesiredAccess=0, dwShareMode=0;
HANDLE hFile;
TgASSERT((0 != piFile) && (0 != pszFile));
switch (enAccess)
{
case ETgFILE_IO_ACCESS_INVALID:
return (TgE_FAIL);
case ETgFILE_IO_ACCESS_READ_SHARED:
dwShareMode = FILE_SHARE_READ;
case ETgFILE_IO_ACCESS_READ:
dwDesiredAccess = FILE_GENERIC_READ;
break;
case ETgFILE_IO_ACCESS_WRITE_SHARED:
dwShareMode = FILE_SHARE_WRITE;
case ETgFILE_IO_ACCESS_WRITE:
dwDesiredAccess = FILE_GENERIC_WRITE;
break;
case ETgFILE_IO_ACCESS_READ_WRITE_SHARED:
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
case ETgFILE_IO_ACCESS_READ_WRITE:
dwDesiredAccess = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
break;
default:
TgS_NO_DEFAULT(break);
};
hFile = CreateFile( pszFile, dwDesiredAccess, dwShareMode, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0 );
*piFile = (TgSINTPTR)hFile;
return (hFile != INVALID_HANDLE_VALUE ? TgS_OK : TgE_FAIL);
};
TgRESULT tgIO_File_Read( C_TgSINTPTR iFile, PC_TgVOID pDest, C_TgSIZE nBytesToRead )
{
DWORD nBytesRead;
TgASSERT((TgSINTPTR)INVALID_HANDLE_VALUE != iFile);
if (!(ReadFile( (HANDLE)iFile, pDest, (DWORD)nBytesToRead, &nBytesRead, NULL)))
{
File_Error( iFile );
};
return (nBytesRead <= nBytesToRead ? TgS_OK : TgE_FAIL);
};
TgRESULT tgIO_File_Write( C_TgSINTPTR iFile, CPC_TgVOID pSource, C_TgSIZE nBytesToWrite )
{
DWORD nBytesWrite;
TgASSERT((TgSINTPTR)INVALID_HANDLE_VALUE != iFile);
if (!(WriteFile( (HANDLE)iFile, pSource, (DWORD)nBytesToWrite, &nBytesWrite, NULL)))
{
File_Error( iFile );
};
return (nBytesWrite == nBytesToWrite ? TgS_OK : TgE_FAIL);
};
TgRESULT tgIO_File_Flush( C_TgSINTPTR iFile )
{
TgASSERT((TgSINTPTR)INVALID_HANDLE_VALUE != iFile);
TgVERIFY(0 != FlushFileBuffers( (HANDLE)iFile ));
return (TgS_OK);
};
TgRESULT tgIO_File_Close( C_TgSINTPTR iFile )
{
TgASSERT((TgSINTPTR)INVALID_HANDLE_VALUE != iFile);
TgVERIFY(0 != CloseHandle( (HANDLE)iFile ));
return (TgS_OK);
};
TgBOOL tgIO_File_Valid( C_TgSINTPTR iFile )
{
TgASSERT((TgSINTPTR)INVALID_HANDLE_VALUE != iFile);
return (INVALID_HANDLE_VALUE != (HANDLE)iFile);
};
TgRESULT tgIO_File_Seek( C_TgSINTPTR iFile, C_ETgIO_SEEK enSeek_Mode, C_TgSINTPTR iPos )
{
BOOL bSuccess = FALSE;
LARGE_INTEGER uiSet_Position;
TgASSERT((TgSINTPTR)INVALID_HANDLE_VALUE != iFile);
uiSet_Position.QuadPart = iPos;
switch (enSeek_Mode)
{
case ETgIO_SEEK_BEGIN:
bSuccess = SetFilePointerEx( (HANDLE)iFile, uiSet_Position, 0, FILE_BEGIN );
break;
case ETgIO_SEEK_END:
bSuccess = SetFilePointerEx( (HANDLE)iFile, uiSet_Position, 0, FILE_END );
break;
case ETgIO_SEEK_CURRENT:
bSuccess = SetFilePointerEx( (HANDLE)iFile, uiSet_Position, 0, FILE_CURRENT );
break;
default:
TgS_NO_DEFAULT(return (TgE_FAIL));
}
#if defined(_DEBUG)
{
LARGE_INTEGER uiNew_Position;
uiSet_Position.QuadPart = 0;
SetFilePointerEx( (HANDLE)iFile, uiSet_Position, &uiNew_Position, FILE_CURRENT );
bSuccess &= (TgSIZE)uiNew_Position.QuadPart <= tgIO_File_Size( iFile );
}
#endif
return (bSuccess ? TgS_OK : TgE_FAIL);
};
TgSIZE tgIO_File_Size( C_TgSINTPTR iFile )
{
DWORD uiHigh, uiLow;
TgASSERT((TgSINTPTR)INVALID_HANDLE_VALUE != iFile);
uiLow = GetFileSize( (HANDLE)iFile, &uiHigh );
return (((TgSIZE)uiHigh << 31) | uiLow);
};
TgRESULT tgIO_Directory_Make( CPC_TgCHAR pszPath )
{
return (CreateDirectory( pszPath, 0 ) ? TgS_OK : TgE_FAIL);
};
TgRESULT tgIO_Directory_Remove( CPC_TgCHAR pszPath )
{
return (RemoveDirectory( pszPath ) ? TgS_OK : TgE_FAIL);
};
TgBOOL tgIO_Directory_Exists( CPC_TgCHAR pszPath )
{
const DWORD dwAttrib = GetFileAttributes( pszPath );
return (~(DWORD)0 != dwAttrib && 0 != (FILE_ATTRIBUTE_DIRECTORY & dwAttrib) ? TgTRUE : TgFALSE);
};
TgRESULT tgIO_File_Delete( CPC_TgCHAR pszFile )
{
return (DeleteFile( pszFile ) ? TgS_OK : TgE_FAIL);
};
TgRESULT tgIO_File_Copy( CPC_TgCHAR pszExisting, CPC_TgCHAR pszDest )
{
return (CopyFile( pszExisting, pszDest, TgTRUE ) ? TgS_OK : TgE_FAIL);
};
TgRESULT tgIO_File_Move( CPC_TgCHAR pszExisting, CPC_TgCHAR pszDest )
{
return (MoveFile( pszExisting, pszDest ) ? TgS_OK : TgE_FAIL);
};
TgBOOL tgIO_File_Exists( CPC_TgCHAR pszFile )
{
const DWORD dwAttrib = GetFileAttributes( pszFile );
return (dwAttrib != -1 && dwAttrib != FILE_ATTRIBUTE_DIRECTORY ? TgTRUE : TgFALSE);
};
TgVOID tgAM_WRITE_FENCE()
{
_WriteBarrier();
};
TgVOID tgAM_READ_FENCE()
{
_ReadBarrier();
};
TgSINT32 tgAM32_ADD( TgATOMIC_INT32 *piTarget, C_TgSINT32 iVal )
{
#if defined(WIN32)
TgATOMIC_INT32 iCurrent_Value, iNew_Value;
do
{
iCurrent_Value = *piTarget;
iNew_Value = iCurrent_Value + iVal;
}
while (_InterlockedCompareExchange( piTarget, iNew_Value, iCurrent_Value ) != iCurrent_Value);
return (iNew_Value);
#else
return (_InterlockedAdd( (volatile LONG*)piTarget, iVal ));
#endif
};
TgSINT32 tgAM32_SUB( TgATOMIC_INT32 *piTarget, C_TgSINT32 iVal )
{
#if defined(WIN32)
TgATOMIC_INT32 iCurrent_Value, iNew_Value;
do
{
iCurrent_Value = *piTarget;
iNew_Value = iCurrent_Value - iVal;
}
while (_InterlockedCompareExchange( piTarget, iNew_Value, iCurrent_Value ) != iCurrent_Value);
return (iNew_Value);
#else
return (_InterlockedAdd( (volatile LONG*)piTarget, -iVal ));
#endif
};
TgSINT32 tgAM32_AND( TgATOMIC_INT32 *piTarget, C_TgSINT32 iVal )
{
return (_InterlockedAnd( (volatile LONG*)piTarget, iVal ));
};
TgSINT32 tgAM32_OR( TgATOMIC_INT32 *piTarget, C_TgSINT32 iVal )
{
return (_InterlockedOr( (volatile LONG*)piTarget, iVal ));
};
TgSINT32 tgAM32_INC( TgATOMIC_INT32 *piTarget )
{
return (_InterlockedIncrement( (volatile LONG*)piTarget ));
};
TgSINT32 tgAM32_DEC( TgATOMIC_INT32 *piTarget )
{
return (_InterlockedDecrement( (volatile LONG*)piTarget ));
};
TgSINT32 tgAM32_READ( TgATOMIC_INT32 *piTarget )
{
return (*(volatile LONG*)piTarget);
};
TgVOID tgAM32_WRITE( TgATOMIC_INT32 *piTarget, C_TgSINT32 iVal )
{
_InterlockedExchange( (volatile LONG*)piTarget, iVal );
};
TgSINT32 tgAM32_XCHG( TgATOMIC_INT32 *piTarget, C_TgSINT32 iVal )
{
return (_InterlockedExchange( (volatile LONG*)piTarget, iVal ));
};
TgSINT32 tgAM32_XCMP( TgATOMIC_INT32 *piTarget, C_TgSINT32 iVal, C_TgSINT32 iCmp )
{
return (_InterlockedCompareExchange( (volatile LONG*)piTarget, iVal, iCmp ));
};
#if defined(_WIN64)
TgSINT64 tgAM64_ADD( TgATOMIC_INT64 *piTarget, C_TgSINT64 iVal )
{
return (_InterlockedAdd64( (volatile LONGLONG*)piTarget, iVal ));
};
TgSINT64 tgAM64_SUB( TgATOMIC_INT64 *piTarget, C_TgSINT64 iVal )
{
return (_InterlockedAdd64( (volatile LONGLONG*)piTarget, -iVal ));
};
TgSINT64 tgAM64_AND( TgATOMIC_INT64 *piTarget, C_TgSINT64 iVal )
{
return (_InterlockedAnd64( (volatile LONGLONG*)piTarget, iVal ));
};
TgSINT64 tgAM64_OR( TgATOMIC_INT64 *piTarget, C_TgSINT64 iVal )
{
return (_InterlockedOr64( (volatile LONGLONG*)piTarget, iVal ));
};
TgSINT64 tgAM64_INC( TgATOMIC_INT64 *piTarget )
{
return (_InterlockedIncrement64( (volatile LONGLONG*)piTarget ));
};
TgSINT64 tgAM64_DEC( TgATOMIC_INT64 *piTarget )
{
return (_InterlockedDecrement64( (volatile LONGLONG*)piTarget ));
};
TgSINT64 tgAM64_READ( TgATOMIC_INT64 *piTarget )
{
return (*(volatile LONGLONG*)piTarget);
};
TgVOID tgAM64_WRITE( TgATOMIC_INT64 *piTarget, C_TgSINT64 iVal )
{
_InterlockedExchange64( (volatile LONGLONG*)piTarget, iVal );
};
TgSINT64 tgAM64_XCHG( TgATOMIC_INT64 *piTarget, C_TgSINT64 iVal )
{
return (_InterlockedExchange64( (volatile LONGLONG*)piTarget, iVal ));
};
TgSINT64 tgAM64_XCMP( TgATOMIC_INT64 *piTarget, C_TgSINT64 iVal, C_TgSINT64 iCmp )
{
return (_InterlockedCompareExchange64( (volatile LONGLONG*)piTarget, iVal, iCmp ));
};
#endif