amd64: fix multithread, fix vgui, fix physmodels
This commit is contained in:
parent
01413fdd71
commit
9ee21ecf90
@ -15,6 +15,7 @@
|
||||
#include "filesystem.h"
|
||||
#include "tier1/convar.h"
|
||||
#include "cdll_int.h"
|
||||
#include "vcrmode.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
@ -1150,4 +1151,4 @@ void CInfoDescription::WriteFileHeader( FileHandle_t fp )
|
||||
g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1973,39 +1973,18 @@ studiohdr_t *CMDLCache::UnserializeMDL( MDLHandle_t handle, void *pData, int nDa
|
||||
|
||||
// critical! store a back link to our data
|
||||
// this is fetched when re-establishing dependent cached data (vtx/vvd)
|
||||
#ifndef PLATFORM_64BITS
|
||||
pStudioHdrIn->SetVirtualModel( MDLHandleToVirtual( handle ) );
|
||||
#endif
|
||||
pStudioHdrIn->SetVirtualModel( MDLHandleToVirtual( handle ) );
|
||||
|
||||
MdlCacheMsg( "MDLCache: Alloc studiohdr %s\n", GetModelName( handle ) );
|
||||
|
||||
// allocate cache space
|
||||
MemAlloc_PushAllocDbgInfo( "Models:StudioHdr", 0);
|
||||
#ifdef PLATFORM_64BITS
|
||||
studiohdr_t *pHdr = (studiohdr_t *)AllocData( MDLCACHE_STUDIOHDR, pStudioHdrIn->length + sizeof(studiohdr_shim64_index) );
|
||||
#else
|
||||
studiohdr_t *pHdr = (studiohdr_t *)AllocData( MDLCACHE_STUDIOHDR, pStudioHdrIn->length );
|
||||
#endif
|
||||
MemAlloc_PopAllocDbgInfo();
|
||||
if ( !pHdr )
|
||||
return NULL;
|
||||
|
||||
#ifdef PLATFORM_64BITS
|
||||
// MoeMod : fix shim64 index
|
||||
studiohdr_shim64_index *pHdrIndex = (studiohdr_shim64_index *)(((byte *)pHdr)+ pStudioHdrIn->length);
|
||||
pHdrIndex->virtualModel = nullptr;
|
||||
pHdrIndex->animblockModel = nullptr;
|
||||
pHdrIndex->pVertexBase = nullptr;
|
||||
pHdrIndex->pIndexBase = nullptr;
|
||||
pStudioHdrIn->index_ptr_virtualModel = (byte *)&pHdrIndex->virtualModel - (byte *)pHdr;
|
||||
pStudioHdrIn->index_ptr_animblockModel = (byte *)&pHdrIndex->animblockModel - (byte *)pHdr;
|
||||
pStudioHdrIn->index_ptr_pVertexBase = (byte *)&pHdrIndex->pVertexBase - (byte *)pHdr;
|
||||
pStudioHdrIn->index_ptr_pIndexBase = (byte *)&pHdrIndex->pIndexBase - (byte *)pHdr;
|
||||
pStudioHdrIn->SetVirtualModel( MDLHandleToVirtual( handle ) );
|
||||
CacheData( &m_MDLDict[handle]->m_MDLCache, pHdr, pStudioHdrIn->length + sizeof(studiohdr_shim64_index), GetModelName( handle ), MDLCACHE_STUDIOHDR, MakeCacheID( handle, MDLCACHE_STUDIOHDR) );
|
||||
#else
|
||||
CacheData( &m_MDLDict[handle]->m_MDLCache, pHdr, pStudioHdrIn->length, GetModelName( handle ), MDLCACHE_STUDIOHDR, MakeCacheID( handle, MDLCACHE_STUDIOHDR) );
|
||||
#endif
|
||||
|
||||
if ( mod_lock_mdls_on_load.GetBool() )
|
||||
{
|
||||
@ -2103,27 +2082,7 @@ bool CMDLCache::ReadMDLFile( MDLHandle_t handle, const char *pMDLFileName, CUtlB
|
||||
|
||||
// critical! store a back link to our data
|
||||
// this is fetched when re-establishing dependent cached data (vtx/vvd)
|
||||
#if PLATFORM_64BITS
|
||||
int length = buf.Size();
|
||||
{
|
||||
studiohdr_shim64_index shim;
|
||||
buf.Put( &shim, sizeof(shim) );
|
||||
}
|
||||
studiohdr_shim64_index *pHdrIndex = (studiohdr_shim64_index *)(((byte *)buf.PeekGet())+ length);
|
||||
pStudioHdr = (studiohdr_t*)buf.PeekGet();
|
||||
|
||||
pHdrIndex->virtualModel = nullptr;
|
||||
pHdrIndex->animblockModel = nullptr;
|
||||
pHdrIndex->pVertexBase = nullptr;
|
||||
pHdrIndex->pIndexBase = nullptr;
|
||||
pStudioHdr->index_ptr_virtualModel = (byte *)&pHdrIndex->virtualModel - (byte *)pStudioHdr;
|
||||
pStudioHdr->index_ptr_animblockModel = (byte *)&pHdrIndex->animblockModel - (byte *)pStudioHdr;
|
||||
pStudioHdr->index_ptr_pVertexBase = (byte *)&pHdrIndex->pVertexBase - (byte *)pStudioHdr;
|
||||
pStudioHdr->index_ptr_pIndexBase = (byte *)&pHdrIndex->pIndexBase - (byte *)pStudioHdr;
|
||||
pStudioHdr->SetVirtualModel( MDLHandleToVirtual( handle ) );
|
||||
#else
|
||||
pStudioHdr->SetVirtualModel( MDLHandleToVirtual( handle ) );
|
||||
#endif
|
||||
pStudioHdr->SetVirtualModel( MDLHandleToVirtual( handle ) );
|
||||
|
||||
// Make sure all dependent files are valid
|
||||
if ( !VerifyHeaders( pStudioHdr ) )
|
||||
|
@ -288,7 +288,7 @@ bool CollisionBSPData_Load( const char *pName, CCollisionBSPData *pBSPData )
|
||||
CollisionBSPData_LoadPhysics( pBSPData );
|
||||
|
||||
COM_TimestampedLog( " CollisionBSPData_LoadDispInfo" );
|
||||
CollisionBSPData_LoadDispInfo( pBSPData );
|
||||
CollisionBSPData_LoadDispInfo( pBSPData );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -479,7 +479,7 @@ Handles cursor positioning, line wrapping, etc
|
||||
*/
|
||||
static bool g_fColorPrintf = false;
|
||||
static bool g_bInColorPrint = false;
|
||||
extern CThreadLocalInt<> g_bInSpew;
|
||||
extern CTHREADLOCALINT g_bInSpew;
|
||||
|
||||
void Con_Printf( const char *fmt, ... );
|
||||
|
||||
|
@ -924,14 +924,14 @@ void CDownloadManager::StartNewDownload()
|
||||
m_lastPercent = 0;
|
||||
|
||||
// Start the thread
|
||||
uintp threadID;
|
||||
uintp threadID;
|
||||
VCRHook_CreateThread(NULL, 0,
|
||||
#ifdef POSIX
|
||||
(void *)
|
||||
#endif
|
||||
DownloadThread, m_activeRequest, 0, &threadID );
|
||||
|
||||
ThreadDetach( ( ThreadHandle_t )threadID );
|
||||
ReleaseThreadHandle( ( ThreadHandle_t )threadID );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1072,14 +1072,14 @@ class CDownloadSystem : public IDownloadSystem
|
||||
public:
|
||||
virtual uintp CreateDownloadThread( RequestContext_t *pContext )
|
||||
{
|
||||
uintp nThreadID;
|
||||
uintp nThreadID;
|
||||
VCRHook_CreateThread(NULL, 0,
|
||||
#ifdef POSIX
|
||||
(void*)
|
||||
#endif
|
||||
DownloadThread, pContext, 0, (uintp *)&nThreadID );
|
||||
|
||||
ThreadDetach( ( ThreadHandle_t )nThreadID );
|
||||
ReleaseThreadHandle( ( ThreadHandle_t )nThreadID );
|
||||
return nThreadID;
|
||||
}
|
||||
};
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "host.h"
|
||||
#include "server.h"
|
||||
#include "networkstringtableclient.h"
|
||||
#include "vcrmode.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
@ -2003,7 +2003,7 @@ void R_DrawDecalsAllImmediate_GatherDecals( IMatRenderContext *pRenderContext, i
|
||||
|
||||
intp iHead = g_aDecalSortTrees[iSortTree].m_aDecalSortBuckets[iGroup][iTreeType].Element( iBucket ).m_iHead;
|
||||
|
||||
intp iElement = iHead;
|
||||
intp iElement = iHead;
|
||||
while ( iElement != g_aDecalSortPool.InvalidIndex() )
|
||||
{
|
||||
decal_t *pDecal = g_aDecalSortPool.Element( iElement );
|
||||
@ -2154,11 +2154,11 @@ void R_DrawDecalsAllImmediate( IMatRenderContext *pRenderContext, int iGroup, in
|
||||
{
|
||||
if ( g_aDecalSortTrees[iSortTree].m_aDecalSortBuckets[iGroup][iTreeType].Element( iBucket ).m_nCheckCount != nCheckCount )
|
||||
continue;
|
||||
|
||||
|
||||
intp iHead = g_aDecalSortTrees[iSortTree].m_aDecalSortBuckets[iGroup][iTreeType].Element( iBucket ).m_iHead;
|
||||
|
||||
|
||||
int nCount;
|
||||
intp iElement = iHead;
|
||||
intp iElement = iHead;
|
||||
while ( iElement != g_aDecalSortPool.InvalidIndex() )
|
||||
{
|
||||
decal_t *pDecal = g_aDecalSortPool.Element( iElement );
|
||||
@ -2330,7 +2330,7 @@ void R_DrawDecalsAll_GatherDecals( IMatRenderContext *pRenderContext, int iGroup
|
||||
if ( bucket.m_nCheckCount != nCheckCount )
|
||||
continue;
|
||||
|
||||
intp iHead = bucket.m_iHead;
|
||||
intp iHead = bucket.m_iHead;
|
||||
if ( !g_aDecalSortPool.IsValidIndex( iHead ) )
|
||||
continue;
|
||||
|
||||
@ -2647,7 +2647,7 @@ void R_DrawDecalsAll( IMatRenderContext *pRenderContext, int iGroup, int iTreeTy
|
||||
if ( bucket.m_nCheckCount != nCheckCount )
|
||||
continue;
|
||||
|
||||
int iHead = bucket.m_iHead;
|
||||
intp iHead = bucket.m_iHead;
|
||||
if ( !g_aDecalSortPool.IsValidIndex( iHead ) )
|
||||
continue;
|
||||
|
||||
@ -2666,7 +2666,7 @@ void R_DrawDecalsAll( IMatRenderContext *pRenderContext, int iGroup, int iTreeTy
|
||||
bool bBatchInit = true;
|
||||
|
||||
int nCount;
|
||||
int iElement = iHead;
|
||||
intp iElement = iHead;
|
||||
while ( iElement != g_aDecalSortPool.InvalidIndex() )
|
||||
{
|
||||
decal_t *pDecal = g_aDecalSortPool.Element( iElement );
|
||||
|
@ -282,7 +282,7 @@ private:
|
||||
CVoxelHash* m_pVoxelHash;
|
||||
CLeafList m_aLeafList; // Pool - Linked list(multilist) of leaves per entity.
|
||||
int m_TreeId;
|
||||
CThreadLocalPtr<CPartitionVisits> m_pVisits;
|
||||
CTHREADLOCALPTR(CPartitionVisits) m_pVisits;
|
||||
CSpatialPartition * m_pOwner;
|
||||
CUtlVector<unsigned short> m_AvailableVisitBits;
|
||||
unsigned short m_nNextVisitBit;
|
||||
@ -1775,7 +1775,7 @@ void CVoxelTree::Shutdown( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CVoxelTree::InsertIntoTree( SpatialPartitionHandle_t hPartition, const Vector& mins, const Vector& maxs )
|
||||
{
|
||||
bool bWasReading = ( m_pVisits != NULL );
|
||||
bool bWasReading = ( m_pVisits != static_cast<void*>(nullptr) );
|
||||
if ( bWasReading )
|
||||
{
|
||||
// If we're recursing in this thread, need to release our read lock to allow ourselves to write
|
||||
@ -1832,7 +1832,7 @@ void CVoxelTree::RemoveFromTree( SpatialPartitionHandle_t hPartition )
|
||||
int nLevel = info.m_nLevel[GetTreeId()];
|
||||
if ( nLevel >= 0 )
|
||||
{
|
||||
bool bWasReading = ( m_pVisits != NULL );
|
||||
bool bWasReading = ( m_pVisits != static_cast<void*>(nullptr) );
|
||||
if ( bWasReading )
|
||||
{
|
||||
// If we're recursing in this thread, need to release our read lock to allow ourselves to write
|
||||
|
@ -797,7 +797,7 @@ void Sys_ShutdownAuthentication( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Debug library spew output
|
||||
//-----------------------------------------------------------------------------
|
||||
CThreadLocalInt<> g_bInSpew;
|
||||
CTHREADLOCALINT g_bInSpew;
|
||||
|
||||
#include "tier1/fmtstr.h"
|
||||
|
||||
|
@ -367,7 +367,8 @@ void TextMessageParse( byte *pMemFile, int fileSize )
|
||||
|
||||
client_textmessage_t textMessages[ MAX_MESSAGES ];
|
||||
|
||||
int i, nameHeapSize, textHeapSize, messageSize, nameOffset;
|
||||
int i, nameHeapSize, textHeapSize, messageSize;
|
||||
intp nameOffset;
|
||||
|
||||
lastNamePos = 0;
|
||||
lineNumber = 0;
|
||||
@ -633,4 +634,4 @@ client_textmessage_t *TextMessageGet( const char *pName )
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "replay_internal.h"
|
||||
#include "replayserver.h"
|
||||
#include "replay/iserverengine.h"
|
||||
#include "vcrmode.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
@ -1804,7 +1804,7 @@ const char *CBaseFileSystem::GetWritePath( const char *pFilename, const char *pa
|
||||
//-----------------------------------------------------------------------------
|
||||
// Reads/writes files to utlbuffers. Attempts alignment fixups for optimal read
|
||||
//-----------------------------------------------------------------------------
|
||||
CThreadLocal<char *> g_pszReadFilename;
|
||||
CTHREADLOCAL(char *) g_pszReadFilename;
|
||||
bool CBaseFileSystem::ReadToBuffer( FileHandle_t fp, CUtlBuffer &buf, int nMaxBytes, FSAllocFunc_t pfnAlloc )
|
||||
{
|
||||
SetBufferSize( fp, 0 ); // TODO: what if it's a pack file? restore buffer size?
|
||||
|
@ -2331,7 +2331,16 @@ void CDetailObjectSystem::RenderFastSprites( const Vector &viewOrigin, const Vec
|
||||
color[2] = pquad->m_RGBColor[0][2];
|
||||
color[3] = pColorsCasted[MANTISSA_LSB_OFFSET];
|
||||
|
||||
DetailPropSpriteDict_t *pDict = pquad->m_pSpriteDefs[0];
|
||||
DetailPropSpriteDict_t *pDict;
|
||||
#ifdef PLATFORM_64BITS
|
||||
if( nSubIdx == 1 )
|
||||
pDict = ((FastSpriteQuadBuildoutBufferNonSIMDView_t*)((intp)pquad+4))->m_pSpriteDefs[0];
|
||||
else if( nSubIdx == 3 )
|
||||
pDict = ((FastSpriteQuadBuildoutBufferNonSIMDView_t*)((intp)pquad-4))->m_pSpriteDefs[0];
|
||||
else
|
||||
#endif
|
||||
pDict = pquad->m_pSpriteDefs[0];
|
||||
|
||||
|
||||
meshBuilder.Position3f( pquad->m_flX0[0], pquad->m_flY0[0], pquad->m_flZ0[0] );
|
||||
meshBuilder.Color4ubv( color );
|
||||
@ -2545,6 +2554,7 @@ void CDetailObjectSystem::RenderFastTranslucentDetailObjectsInLeaf( const Vector
|
||||
int nToDraw = MIN( nCount, nQuadsRemaining );
|
||||
nCount -= nToDraw;
|
||||
nQuadsRemaining -= nToDraw;
|
||||
|
||||
while( nToDraw-- )
|
||||
{
|
||||
// draw the sucker
|
||||
@ -2553,17 +2563,28 @@ void CDetailObjectSystem::RenderFastTranslucentDetailObjectsInLeaf( const Vector
|
||||
|
||||
FastSpriteQuadBuildoutBufferNonSIMDView_t const *pquad = pQuadBuffer+nSIMDIdx;
|
||||
|
||||
|
||||
// voodoo - since everything is in 4s, offset structure pointer by a couple of floats to handle sub-index
|
||||
pquad = (FastSpriteQuadBuildoutBufferNonSIMDView_t const *) ( ( (intp) ( pquad ) )+ ( nSubIdx << 2 ) );
|
||||
|
||||
uint8 const *pColorsCasted = reinterpret_cast<uint8 const *> ( pquad->m_Alpha );
|
||||
|
||||
|
||||
uint8 color[4];
|
||||
color[0] = pquad->m_RGBColor[0][0];
|
||||
color[1] = pquad->m_RGBColor[0][1];
|
||||
color[2] = pquad->m_RGBColor[0][2];
|
||||
color[3] = pColorsCasted[MANTISSA_LSB_OFFSET];
|
||||
|
||||
DetailPropSpriteDict_t *pDict = pquad->m_pSpriteDefs[0];
|
||||
DetailPropSpriteDict_t *pDict;
|
||||
#ifdef PLATFORM_64BITS
|
||||
if( nSubIdx == 1 )
|
||||
pDict = ((FastSpriteQuadBuildoutBufferNonSIMDView_t*)((intp)pquad+4))->m_pSpriteDefs[0];
|
||||
else if( nSubIdx == 3 )
|
||||
pDict = ((FastSpriteQuadBuildoutBufferNonSIMDView_t*)((intp)pquad-4))->m_pSpriteDefs[0];
|
||||
else
|
||||
#endif
|
||||
pDict = pquad->m_pSpriteDefs[0];
|
||||
|
||||
meshBuilder.Position3f( pquad->m_flX0[0], pquad->m_flY0[0], pquad->m_flZ0[0] );
|
||||
meshBuilder.Color4ubv( color );
|
||||
|
@ -731,7 +731,10 @@ CBaseCombatCharacter::CBaseCombatCharacter( void )
|
||||
}
|
||||
|
||||
// not standing on a nav area yet
|
||||
#ifdef MEXT_BOT
|
||||
m_lastNavArea = NULL;
|
||||
#endif
|
||||
|
||||
m_registeredNavTeam = TEAM_INVALID;
|
||||
|
||||
for (int i = 0; i < MAX_WEAPONS; i++)
|
||||
@ -3481,17 +3484,20 @@ void CBaseCombatCharacter::UpdateLastKnownArea( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseCombatCharacter::IsAreaTraversable( const CNavArea *area ) const
|
||||
{
|
||||
#ifdef NEXT_BOT
|
||||
return area ? !area->IsBlocked( GetTeamNumber() ) : false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Leaving the nav mesh
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatCharacter::ClearLastKnownArea( void )
|
||||
{
|
||||
#ifdef NEXT_BOT
|
||||
OnNavAreaChanged( NULL, m_lastNavArea );
|
||||
|
||||
|
||||
if ( m_lastNavArea )
|
||||
{
|
||||
m_lastNavArea->DecrementPlayerCount( m_registeredNavTeam, entindex() );
|
||||
@ -3499,21 +3505,22 @@ void CBaseCombatCharacter::ClearLastKnownArea( void )
|
||||
m_lastNavArea = NULL;
|
||||
m_registeredNavTeam = TEAM_INVALID;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handling editor removing the area we're standing upon
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseCombatCharacter::OnNavAreaRemoved( CNavArea *removedArea )
|
||||
{
|
||||
#ifdef NEXT_BOT
|
||||
if ( m_lastNavArea == removedArea )
|
||||
{
|
||||
ClearLastKnownArea();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Changing team, maintain associated data
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -400,11 +400,19 @@ public:
|
||||
void SetPreventWeaponPickup( bool bPrevent ) { m_bPreventWeaponPickup = bPrevent; }
|
||||
bool m_bPreventWeaponPickup;
|
||||
|
||||
virtual CNavArea *GetLastKnownArea( void ) const { return m_lastNavArea; } // return the last nav area the player occupied - NULL if unknown
|
||||
virtual bool IsAreaTraversable( const CNavArea *area ) const; // return true if we can use the given area
|
||||
virtual CNavArea *GetLastKnownArea( void ) const
|
||||
{
|
||||
#ifdef NEXT_BOT
|
||||
return m_lastNavArea;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} // return the last nav area the player occupied - NULL if unknown
|
||||
|
||||
virtual void ClearLastKnownArea( void );
|
||||
virtual void UpdateLastKnownArea( void ); // invoke this to update our last known nav area (since there is no think method chained to CBaseCombatCharacter)
|
||||
virtual void OnNavAreaChanged( CNavArea *enteredArea, CNavArea *leftArea ) { } // invoked (by UpdateLastKnownArea) when we enter a new nav area (or it is reset to NULL)
|
||||
virtual bool IsAreaTraversable( const CNavArea *area ) const; // return true if we can use the given area
|
||||
virtual void OnNavAreaRemoved( CNavArea *removedArea );
|
||||
|
||||
// -----------------------
|
||||
|
@ -1968,7 +1968,7 @@ void CNPC_Barnacle::OnTongueTipUpdated()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Barnacle::UpdateTongue( void )
|
||||
{
|
||||
if ( m_hTongueTip == NULL )
|
||||
if ( m_hTongueTip == NULL || m_hTongueTip->m_pSpring == NULL )
|
||||
return;
|
||||
|
||||
// Set the spring's length to that of the tongue's extension
|
||||
|
@ -150,8 +150,8 @@ void PointCameraSetupVisibility( CBaseEntity *pPlayer, int area, unsigned char *
|
||||
pCameraEnt->SetActive( false );
|
||||
}
|
||||
|
||||
int nNext;
|
||||
for ( int i = g_InfoCameraLinkList.Head(); i != g_InfoCameraLinkList.InvalidIndex(); i = nNext )
|
||||
intp nNext;
|
||||
for ( intp i = g_InfoCameraLinkList.Head(); i != g_InfoCameraLinkList.InvalidIndex(); i = nNext )
|
||||
{
|
||||
nNext = g_InfoCameraLinkList.Next( i );
|
||||
|
||||
|
@ -73,7 +73,6 @@ public:
|
||||
bool operator()( CBaseCombatCharacter *actor )
|
||||
{
|
||||
actor->OnNavAreaRemoved( m_deadArea );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -200,12 +199,12 @@ public:
|
||||
{
|
||||
#if PLATFORM_64BITS
|
||||
COMPILE_TIME_ASSERT( sizeof(CNavArea *) == 8 );
|
||||
int64 key[2] = { (int64)item.pAreas[0] + (int64)item.pAreas[1]->GetID(), (int64)item.pAreas[1] + (int64)item.pAreas[0]->GetID() };
|
||||
int64 key[2] = { (int64)(item.pAreas[0] + item.pAreas[1]->GetID()), (int64)(item.pAreas[1] + item.pAreas[0]->GetID()) };
|
||||
return Hash16( key );
|
||||
#else
|
||||
COMPILE_TIME_ASSERT( sizeof(CNavArea *) == 4 );
|
||||
int key[2] = { (int)(item.pAreas[0] + item.pAreas[1]->GetID()), (int)(item.pAreas[1] + item.pAreas[0]->GetID()) };
|
||||
return Hash8( key );
|
||||
return Hash8( key );
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
@ -45,7 +45,9 @@ class CShowZone : public IForEachNavArea
|
||||
public:
|
||||
virtual bool Inspect( const CNavArea *area )
|
||||
{
|
||||
#ifdef NEXT_BOT
|
||||
area->DrawFilled( 255, 255, 0, 255, 9999.9f );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -50,20 +50,22 @@ public:
|
||||
virtual void OnPostQuery( SpatialPartitionListMask_t listMask );
|
||||
|
||||
void AddEntity( CBaseEntity *pEntity );
|
||||
|
||||
|
||||
~CDirtySpatialPartitionEntityList();
|
||||
void LockPartitionForRead()
|
||||
{
|
||||
if ( m_readLockCount == 0 )
|
||||
int nThreadId = g_nThreadID;
|
||||
if ( m_nReadLockCount[nThreadId] == 0 )
|
||||
{
|
||||
m_partitionMutex.LockForRead();
|
||||
}
|
||||
m_readLockCount++;
|
||||
m_nReadLockCount[nThreadId]++;
|
||||
}
|
||||
void UnlockPartitionForRead()
|
||||
{
|
||||
m_readLockCount--;
|
||||
if ( m_readLockCount == 0 )
|
||||
int nThreadId = g_nThreadID;
|
||||
m_nReadLockCount[nThreadId]--;
|
||||
if ( m_nReadLockCount[nThreadId] == 0 )
|
||||
{
|
||||
m_partitionMutex.UnlockRead();
|
||||
}
|
||||
@ -71,6 +73,8 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
int m_nReadLockCount[MAX_THREADS_SUPPORTED];
|
||||
|
||||
CTSListWithFreeList<CBaseHandle> m_DirtyEntities;
|
||||
CThreadSpinRWLock m_partitionMutex;
|
||||
uint32 m_partitionWriteId;
|
||||
@ -106,7 +110,7 @@ void UpdateDirtySpatialPartitionEntities()
|
||||
CDirtySpatialPartitionEntityList::CDirtySpatialPartitionEntityList( char const *name ) : CAutoGameSystem( name )
|
||||
{
|
||||
m_DirtyEntities.Purge();
|
||||
m_readLockCount = 0;
|
||||
memset( m_nReadLockCount, 0, sizeof( m_nReadLockCount ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -164,7 +168,9 @@ void CDirtySpatialPartitionEntityList::OnPreQuery( SpatialPartitionListMask_t li
|
||||
if ( !( listMask & validMask ) )
|
||||
return;
|
||||
|
||||
if ( m_partitionWriteId != 0 && m_partitionWriteId == ThreadGetCurrentId() )
|
||||
int nThreadID = g_nThreadID;
|
||||
|
||||
if ( m_partitionWriteId != 0 && m_partitionWriteId == nThreadID + 1 )
|
||||
return;
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
@ -180,11 +186,11 @@ void CDirtySpatialPartitionEntityList::OnPreQuery( SpatialPartitionListMask_t li
|
||||
// or became dirty due to some other thread or callback. Updating them may cause corruption further up the
|
||||
// stack (e.g. partition iterator). Ignoring the state change should be safe since it happened after the
|
||||
// trace was requested or was unable to be resolved in a previous attempt (still dirty).
|
||||
if ( m_DirtyEntities.Count() && !m_readLockCount )
|
||||
if ( m_DirtyEntities.Count() && !m_nReadLockCount[nThreadID] )
|
||||
{
|
||||
CUtlVector< CBaseHandle > vecStillDirty;
|
||||
m_partitionMutex.LockForWrite();
|
||||
m_partitionWriteId = ThreadGetCurrentId();
|
||||
m_partitionWriteId = nThreadID + 1;
|
||||
CTSListWithFreeList<CBaseHandle>::Node_t *pCurrent, *pNext;
|
||||
while ( ( pCurrent = m_DirtyEntities.Detach() ) != NULL )
|
||||
{
|
||||
|
@ -1814,7 +1814,7 @@ CAmmoDef *GetAmmoDef()
|
||||
def.AddAmmoType("Thumper", DMG_SONIC, TRACER_NONE, 10, 10, 2, 0, 0 );
|
||||
def.AddAmmoType("Gravity", DMG_CLUB, TRACER_NONE, 0, 0, 8, 0, 0 );
|
||||
// def.AddAmmoType("Extinguisher", DMG_BURN, TRACER_NONE, 0, 0, 100, 0, 0 );
|
||||
def.AddAmmoType("Battery", DMG_CLUB, TRACER_NONE, NULL, NULL, NULL, 0, 0 );
|
||||
def.AddAmmoType("Battery", DMG_CLUB, TRACER_NONE, 0, 0, 0, 0, 0 );
|
||||
def.AddAmmoType("GaussEnergy", DMG_SHOCK, TRACER_NONE, "sk_jeep_gauss_damage", "sk_jeep_gauss_damage", "sk_max_gauss_round", BULLET_IMPULSE(650, 8000), 0 ); // hit like a 10kg weight at 400 in/s
|
||||
def.AddAmmoType("CombineCannon", DMG_BULLET, TRACER_LINE, "sk_npc_dmg_gunship_to_plr", "sk_npc_dmg_gunship", NULL, 1.5 * 750 * 12, 0 ); // hit like a 1.5kg weight at 750 ft/s
|
||||
def.AddAmmoType("AirboatGun", DMG_AIRBOAT, TRACER_LINE, "sk_plr_dmg_airboat", "sk_npc_dmg_airboat", NULL, BULLET_IMPULSE(10, 600), 0 );
|
||||
|
@ -43,7 +43,7 @@ struct PhysBlockHeader_t
|
||||
BEGIN_SIMPLE_DATADESC( PhysBlockHeader_t )
|
||||
DEFINE_FIELD( nSaved, FIELD_INTEGER ),
|
||||
// NOTE: We want to save the actual address here for remapping, so use an integer
|
||||
DEFINE_FIELD( pWorldObject, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( pWorldObject, FIELD_POINTER ),
|
||||
END_DATADESC()
|
||||
|
||||
#if defined(_STATIC_LINKED) && defined(CLIENT_DLL)
|
||||
|
@ -40,7 +40,7 @@ void CRagdollLowViolenceManager::SetLowViolence( const char *pMapName )
|
||||
|
||||
#if !defined( CLIENT_DLL )
|
||||
// the server doesn't worry about low violence during multiplayer games
|
||||
if ( g_pGameRules->IsMultiplayer() )
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
{
|
||||
m_bLowViolence = false;
|
||||
}
|
||||
|
@ -91,7 +91,8 @@ static int gSizes[FIELD_TYPECOUNT] =
|
||||
FIELD_SIZE( FIELD_MATERIALINDEX ),
|
||||
|
||||
FIELD_SIZE( FIELD_VECTOR2D ),
|
||||
FIELD_SIZE( FIELD_INTEGER64 ),
|
||||
FIELD_SIZE( FIELD_INTEGER64 ),
|
||||
FIELD_SIZE( FIELD_POINTER ),
|
||||
};
|
||||
|
||||
|
||||
@ -687,7 +688,7 @@ bool CSave::ShouldSaveField( const void *pData, typedescription_t *pField )
|
||||
int *pEHandle = (int *)pData;
|
||||
for ( int i = 0; i < pField->fieldSize; ++i, ++pEHandle )
|
||||
{
|
||||
if ( (*pEHandle) != 0xFFFFFFFF )
|
||||
if ( (*pEHandle) != INVALID_EHANDLE_INDEX )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -721,11 +722,11 @@ bool CSave::WriteBasicField( const char *pname, void *pData, datamap_t *pRootMap
|
||||
case FIELD_FLOAT:
|
||||
WriteFloat( pField->fieldName, (float *)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
|
||||
case FIELD_STRING:
|
||||
WriteString( pField->fieldName, (string_t *)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
|
||||
case FIELD_VECTOR:
|
||||
WriteVector( pField->fieldName, (Vector *)pData, pField->fieldSize );
|
||||
break;
|
||||
@ -1242,19 +1243,19 @@ bool CSave::WriteGameField( const char *pname, void *pData, datamap_t *pRootMap,
|
||||
case FIELD_CLASSPTR:
|
||||
WriteEntityPtr( pField->fieldName, (CBaseEntity **)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
|
||||
case FIELD_EDICT:
|
||||
WriteEdictPtr( pField->fieldName, (edict_t **)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
|
||||
case FIELD_EHANDLE:
|
||||
WriteEHandle( pField->fieldName, (EHANDLE *)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
|
||||
case FIELD_POSITION_VECTOR:
|
||||
WritePositionVector( pField->fieldName, (Vector *)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
|
||||
case FIELD_TIME:
|
||||
WriteTime( pField->fieldName, (float *)pData, pField->fieldSize );
|
||||
break;
|
||||
@ -1262,7 +1263,7 @@ bool CSave::WriteGameField( const char *pname, void *pData, datamap_t *pRootMap,
|
||||
case FIELD_TICK:
|
||||
WriteTick( pField->fieldName, (int *)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
|
||||
case FIELD_MODELINDEX:
|
||||
{
|
||||
int nModelIndex = *(int*)pData;
|
||||
@ -1298,7 +1299,7 @@ bool CSave::WriteGameField( const char *pname, void *pData, datamap_t *pRootMap,
|
||||
case FIELD_FUNCTION:
|
||||
WriteFunction( pRootMap, pField->fieldName, (inputfunc_t **)(char *)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
|
||||
case FIELD_VMATRIX:
|
||||
WriteVMatrix( pField->fieldName, (VMatrix *)pData, pField->fieldSize );
|
||||
break;
|
||||
@ -1314,6 +1315,10 @@ bool CSave::WriteGameField( const char *pname, void *pData, datamap_t *pRootMap,
|
||||
WriteInterval( pField->fieldName, (interval_t *)pData, pField->fieldSize );
|
||||
break;
|
||||
|
||||
case FIELD_POINTER:
|
||||
WriteData( pField->fieldName, sizeof(void*)*pField->fieldSize, (char *)pData );
|
||||
break;
|
||||
|
||||
default:
|
||||
Warning( "Bad field type\n" );
|
||||
Assert(0);
|
||||
@ -2154,6 +2159,10 @@ void CRestore::ReadGameField( const SaveRestoreRecordHeader_t &header, void *pDe
|
||||
ReadInterval( (interval_t *)pDest, pField->fieldSize, header.size );
|
||||
break;
|
||||
|
||||
case FIELD_POINTER:
|
||||
ReadData( (char *)pDest, sizeof(void*)*pField->fieldSize, header.size );
|
||||
break;
|
||||
|
||||
default:
|
||||
Warning( "Bad field type\n" );
|
||||
Assert(0);
|
||||
|
@ -14,7 +14,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
template <class UTLMAP, int KEY_TYPE, int FIELD_TYPE>
|
||||
template <class UTLMAP, intp KEY_TYPE, intp FIELD_TYPE>
|
||||
class CUtlMapDataOps : public CDefSaveRestoreOps
|
||||
{
|
||||
public:
|
||||
@ -169,7 +169,7 @@ public:
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <int KEYTYPE, int FIELD_TYPE>
|
||||
template <intp KEYTYPE, intp FIELD_TYPE>
|
||||
class CUtlMapDataopsInstantiator
|
||||
{
|
||||
public:
|
||||
|
@ -517,7 +517,7 @@ void CMaterialSystem::CleanUpErrorMaterial()
|
||||
//-----------------------------------------------------------------------------
|
||||
CMaterialSystem::CMaterialSystem()
|
||||
{
|
||||
m_nRenderThreadID = 0xFFFFFFFF;
|
||||
m_nRenderThreadID = (uintp)-1;
|
||||
m_hAsyncLoadFileCache = NULL;
|
||||
m_ShaderHInst = 0;
|
||||
m_pMaterialProxyFactory = NULL;
|
||||
@ -2785,8 +2785,8 @@ IMaterial* CMaterialSystem::FindMaterialEx( char const* pMaterialName, const cha
|
||||
{
|
||||
// We need lower-case symbols for this to work
|
||||
int nLen = Q_strlen( pMaterialName ) + 1;
|
||||
char *pFixedNameTemp = (char*)stackalloc( nLen );
|
||||
char *pTemp = (char*)stackalloc( nLen );
|
||||
char *pFixedNameTemp = (char*)malloc( nLen );
|
||||
char *pTemp = (char*)malloc( nLen );
|
||||
Q_strncpy( pFixedNameTemp, pMaterialName, nLen );
|
||||
Q_strlower( pFixedNameTemp );
|
||||
#ifdef POSIX
|
||||
@ -2888,6 +2888,9 @@ IMaterial* CMaterialSystem::FindMaterialEx( char const* pMaterialName, const cha
|
||||
}
|
||||
}
|
||||
|
||||
free(pTemp);
|
||||
free(pFixedNameTemp);
|
||||
|
||||
return g_pErrorMaterial->GetRealTimeVersion();
|
||||
}
|
||||
|
||||
@ -3547,7 +3550,7 @@ void CMaterialSystem::ThreadExecuteQueuedContext( CMatQueuedRenderContext *pCont
|
||||
m_pRenderContext.Set( &m_HardwareRenderContext );
|
||||
pContext->EndQueue( true );
|
||||
m_pRenderContext.Set( pSavedRenderContext );
|
||||
m_nRenderThreadID = 0xFFFFFFFF;
|
||||
m_nRenderThreadID = (uintp)-1;
|
||||
}
|
||||
|
||||
IThreadPool *CMaterialSystem::CreateMatQueueThreadPool()
|
||||
|
@ -572,7 +572,7 @@ public:
|
||||
MaterialLock_t Lock();
|
||||
void Unlock( MaterialLock_t );
|
||||
CMatCallQueue * GetRenderCallQueue();
|
||||
uint GetRenderThreadId() const { return m_nRenderThreadID; }
|
||||
ThreadId_t GetRenderThreadId() const { return m_nRenderThreadID; }
|
||||
void UnbindMaterial( IMaterial *pMaterial );
|
||||
|
||||
IMaterialProxy *DetermineProxyReplacements( IMaterial *pMaterial, KeyValues *pFallbackKeyValues );
|
||||
@ -617,7 +617,7 @@ private:
|
||||
|
||||
CMaterialDict m_MaterialDict;
|
||||
CMatLightmaps m_Lightmaps;
|
||||
CThreadLocal<IMatRenderContextInternal *> m_pRenderContext;
|
||||
CTHREADLOCAL(IMatRenderContextInternal *) m_pRenderContext;
|
||||
CMatRenderContext m_HardwareRenderContext;
|
||||
|
||||
CMatQueuedRenderContext m_QueuedRenderContexts[2];
|
||||
@ -698,7 +698,7 @@ private:
|
||||
|
||||
const char * m_pForcedTextureLoadPathID;
|
||||
FileCacheHandle_t m_hAsyncLoadFileCache;
|
||||
uint m_nRenderThreadID;
|
||||
ThreadId_t m_nRenderThreadID;
|
||||
bool m_bAllocatingRenderTargets;
|
||||
bool m_bInStubMode;
|
||||
bool m_bGeneratedConfig;
|
||||
|
@ -4039,7 +4039,7 @@ void CTexture::DeleteIfUnreferenced()
|
||||
if ( ThreadInMainThread() )
|
||||
{
|
||||
// Render thread better not be active or bad things can happen.
|
||||
Assert( MaterialSystem()->GetRenderThreadId() == 0xFFFFFFFF );
|
||||
Assert( MaterialSystem()->GetRenderThreadId() == (uintp)-1 );
|
||||
TextureManager()->RemoveTexture( this );
|
||||
return;
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ public:
|
||||
virtual CMatCallQueue *GetRenderCallQueue() = 0;
|
||||
|
||||
virtual void UnbindMaterial( IMaterial *pMaterial ) = 0;
|
||||
virtual uint GetRenderThreadId() const = 0 ;
|
||||
virtual ThreadId_t GetRenderThreadId() const = 0 ;
|
||||
|
||||
virtual IMaterialProxy *DetermineProxyReplacements( IMaterial *pMaterial, KeyValues *pFallbackKeyValues ) = 0;
|
||||
};
|
||||
|
@ -1819,7 +1819,7 @@ void CTextureManager::RestoreTexture( ITextureInternal* pTexture )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTextureManager::CleanupPossiblyUnreferencedTextures()
|
||||
{
|
||||
if ( !ThreadInMainThread() || MaterialSystem()->GetRenderThreadId() != 0xFFFFFFFF )
|
||||
if ( !ThreadInMainThread() || MaterialSystem()->GetRenderThreadId() != (uintp)-1 )
|
||||
{
|
||||
Assert( !"CTextureManager::CleanupPossiblyUnreferencedTextures should never be called here" );
|
||||
// This is catastrophically bad, don't do this. Someone needs to fix this. See JohnS or McJohn
|
||||
@ -2368,7 +2368,7 @@ void CTextureManager::RemoveTexture( ITextureInternal *pTexture )
|
||||
|
||||
Assert( pTexture->GetReferenceCount() <= 0 );
|
||||
|
||||
if ( !ThreadInMainThread() || MaterialSystem()->GetRenderThreadId() != 0xFFFFFFFF )
|
||||
if ( !ThreadInMainThread() || MaterialSystem()->GetRenderThreadId() != (uintp)-1 )
|
||||
{
|
||||
Assert( !"CTextureManager::RemoveTexture should never be called here");
|
||||
// This is catastrophically bad, don't do this. Someone needs to fix this.
|
||||
|
@ -125,7 +125,7 @@
|
||||
static ZRESULT lasterrorZ=ZR_OK;
|
||||
#else
|
||||
#include "tier0/threadtools.h"
|
||||
static CThreadLocalInt<ZRESULT> lasterrorZ;
|
||||
static CTHREADLOCALINTEGER(ZRESULT) lasterrorZ;
|
||||
#endif
|
||||
|
||||
typedef unsigned char uch; // unsigned 8-bit value
|
||||
|
@ -840,9 +840,9 @@ void CCoreDispInfo::InitDispInfo( int power, int minTess, float smoothingAngle,
|
||||
void CCoreDispInfo::InitDispInfo( int power, int minTess, float smoothingAngle, const CDispVert *pVerts,
|
||||
const CDispTri *pTris )
|
||||
{
|
||||
Vector vectors[MAX_DISPVERTS];
|
||||
float dists[MAX_DISPVERTS];
|
||||
float alphas[MAX_DISPVERTS];
|
||||
static Vector vectors[MAX_DISPVERTS];
|
||||
static float dists[MAX_DISPVERTS];
|
||||
static float alphas[MAX_DISPVERTS];
|
||||
|
||||
int nVerts = NUM_DISP_POWER_VERTS( power );
|
||||
for ( int i=0; i < nVerts; i++ )
|
||||
|
@ -62,9 +62,10 @@ typedef enum _fieldtypes
|
||||
FIELD_INTERVAL, // a start and range floating point interval ( e.g., 3.2->3.6 == 3.2 and 0.4 )
|
||||
FIELD_MODELINDEX, // a model index
|
||||
FIELD_MATERIALINDEX, // a material index (using the material precache string table)
|
||||
|
||||
|
||||
FIELD_VECTOR2D, // 2 floats
|
||||
FIELD_INTEGER64, // 64bit integer
|
||||
FIELD_INTEGER64, // 64bit integer
|
||||
FIELD_POINTER,
|
||||
|
||||
FIELD_TYPECOUNT, // MUST BE LAST
|
||||
} fieldtype_t;
|
||||
@ -94,7 +95,7 @@ public:
|
||||
#define FIELD_BITS( _fieldType ) (FIELD_SIZE( _fieldType ) * 8)
|
||||
|
||||
DECLARE_FIELD_SIZE( FIELD_FLOAT, sizeof(float) )
|
||||
DECLARE_FIELD_SIZE( FIELD_STRING, sizeof(int) )
|
||||
|
||||
DECLARE_FIELD_SIZE( FIELD_VECTOR, 3 * sizeof(float) )
|
||||
DECLARE_FIELD_SIZE( FIELD_VECTOR2D, 2 * sizeof(float) )
|
||||
DECLARE_FIELD_SIZE( FIELD_QUATERNION, 4 * sizeof(float))
|
||||
@ -103,14 +104,16 @@ DECLARE_FIELD_SIZE( FIELD_BOOLEAN, sizeof(char))
|
||||
DECLARE_FIELD_SIZE( FIELD_SHORT, sizeof(short))
|
||||
DECLARE_FIELD_SIZE( FIELD_CHARACTER, sizeof(char))
|
||||
DECLARE_FIELD_SIZE( FIELD_COLOR32, sizeof(int))
|
||||
DECLARE_FIELD_SIZE( FIELD_CLASSPTR, sizeof(int))
|
||||
DECLARE_FIELD_SIZE( FIELD_EHANDLE, sizeof(int))
|
||||
DECLARE_FIELD_SIZE( FIELD_STRING, sizeof(void*))
|
||||
DECLARE_FIELD_SIZE( FIELD_POINTER, sizeof(void*))
|
||||
DECLARE_FIELD_SIZE( FIELD_MODELNAME, sizeof(void*))
|
||||
DECLARE_FIELD_SIZE( FIELD_SOUNDNAME, sizeof(void*))
|
||||
DECLARE_FIELD_SIZE( FIELD_EHANDLE, sizeof(void*))
|
||||
DECLARE_FIELD_SIZE( FIELD_CLASSPTR, sizeof(void*))
|
||||
DECLARE_FIELD_SIZE( FIELD_EDICT, sizeof(int))
|
||||
DECLARE_FIELD_SIZE( FIELD_POSITION_VECTOR, 3 * sizeof(float))
|
||||
DECLARE_FIELD_SIZE( FIELD_TIME, sizeof(float))
|
||||
DECLARE_FIELD_SIZE( FIELD_TICK, sizeof(int))
|
||||
DECLARE_FIELD_SIZE( FIELD_MODELNAME, sizeof(int))
|
||||
DECLARE_FIELD_SIZE( FIELD_SOUNDNAME, sizeof(int))
|
||||
DECLARE_FIELD_SIZE( FIELD_INPUT, sizeof(int))
|
||||
#ifdef POSIX
|
||||
// pointer to members under gnuc are 8bytes if you have a virtual func
|
||||
|
@ -265,7 +265,7 @@ void SendProxy_UInt16ToInt32( const SendProp *pProp, const void *pStruct, const
|
||||
|
||||
void SendProxy_UInt32ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID)
|
||||
{
|
||||
memcpy( &pOut->m_Int, pData, sizeof(unsigned long) );
|
||||
memcpy( &pOut->m_Int, pData, sizeof(uint32) );
|
||||
}
|
||||
#ifdef SUPPORTS_INT64
|
||||
void SendProxy_UInt64ToInt64( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID)
|
||||
|
@ -48,7 +48,7 @@ struct Vertex_t
|
||||
|
||||
// for sw skinned verts, these are indices into the global list of bones
|
||||
// for hw skinned verts, these are hardware bone indices
|
||||
char boneID[MAX_NUM_BONES_PER_VERT];
|
||||
byte boneID[MAX_NUM_BONES_PER_VERT];
|
||||
};
|
||||
|
||||
enum StripHeaderFlags_t {
|
||||
|
@ -11,13 +11,14 @@
|
||||
|
||||
#include "datamap.h"
|
||||
|
||||
|
||||
typedef struct phyheader_s
|
||||
{
|
||||
DECLARE_BYTESWAP_DATADESC();
|
||||
int size;
|
||||
int id;
|
||||
int solidCount;
|
||||
long checkSum; // checksum of source .mdl file
|
||||
int checkSum; // checksum of source .mdl file
|
||||
} phyheader_t;
|
||||
|
||||
#endif // PHYFILE_H
|
||||
|
@ -2433,7 +2433,7 @@ struct studiohdr_t
|
||||
void* VertexBase() const { return pVertexBase; }
|
||||
void SetVertexBase( void* ptr ) { pVertexBase = ptr; }
|
||||
void* IndexBase() const { return pIndexBase; }
|
||||
void SetIndexBase( void* ptr ) { pIndexBase = ptr; } }
|
||||
void SetIndexBase( void* ptr ) { pIndexBase = ptr; }
|
||||
#endif
|
||||
|
||||
// NOTE: No room to add stuff? Up the .mdl file format version
|
||||
|
@ -1500,7 +1500,7 @@ inline void ConstructThreeArg( T* pMemory, P1 const& arg1, P2 const& arg2, P3 co
|
||||
template <class T>
|
||||
inline T* CopyConstruct( T* pMemory, T const& src )
|
||||
{
|
||||
return reinterpret_cast<T*>(::new( pMemory ) T(src));
|
||||
return ::new( pMemory ) T(src);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
File diff suppressed because it is too large
Load Diff
653
public/tier0/threadtools.inl
Normal file
653
public/tier0/threadtools.inl
Normal file
@ -0,0 +1,653 @@
|
||||
#ifndef THREADTOOLS_INL
|
||||
#define THREADTOOLS_INL
|
||||
|
||||
// This file is included in threadtools.h for PS3 and threadtools.cpp for all other platforms
|
||||
//
|
||||
// Do not #include other files here
|
||||
|
||||
#ifndef _PS3
|
||||
// this is defined in the .cpp for the PS3 to avoid introducing a dependency for files including the header
|
||||
CTHREADLOCALPTR(CThread) g_pCurThread;
|
||||
|
||||
#define INLINE_ON_PS3
|
||||
#else
|
||||
// Inlining these functions on PS3 (which are called across PRX boundaries) saves us over 1ms per frame
|
||||
#define INLINE_ON_PS3 inline
|
||||
#endif
|
||||
|
||||
INLINE_ON_PS3 CThread::CThread() :
|
||||
#ifdef _WIN32
|
||||
m_hThread( NULL ),
|
||||
m_threadId( 0 ),
|
||||
#elif defined( _PS3 ) || defined(_POSIX)
|
||||
m_threadId( 0 ),
|
||||
m_threadZombieId( 0 ) ,
|
||||
#endif
|
||||
m_result( 0 ),
|
||||
m_flags( 0 )
|
||||
{
|
||||
m_szName[0] = 0;
|
||||
m_NotSuspendedEvent.Set();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
INLINE_ON_PS3 CThread::~CThread()
|
||||
{
|
||||
#ifdef MSVC
|
||||
if (m_hThread)
|
||||
#elif defined(POSIX) && !defined( _PS3 )
|
||||
if ( m_threadId )
|
||||
#endif
|
||||
{
|
||||
if ( IsAlive() )
|
||||
{
|
||||
Msg( "Illegal termination of worker thread! Threads must negotiate an end to the thread before the CThread object is destroyed.\n" );
|
||||
#ifdef _WIN32
|
||||
|
||||
DoNewAssertDialog( __FILE__, __LINE__, "Illegal termination of worker thread! Threads must negotiate an end to the thread before the CThread object is destroyed.\n" );
|
||||
#endif
|
||||
if ( GetCurrentCThread() == this )
|
||||
{
|
||||
Stop(); // BUGBUG: Alfred - this doesn't make sense, this destructor fires from the hosting thread not the thread itself!!
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(POSIX) || defined( _PS3 )
|
||||
if ( m_threadZombieId )
|
||||
{
|
||||
// just clean up zombie threads immediately (the destructor is fired from the hosting thread)
|
||||
Join();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
INLINE_ON_PS3 const char *CThread::GetName()
|
||||
{
|
||||
AUTO_LOCK( m_Lock );
|
||||
if ( !m_szName[0] )
|
||||
{
|
||||
#if defined( _WIN32 )
|
||||
_snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p/%p)", this, m_hThread );
|
||||
#elif defined( _PS3 )
|
||||
snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p)", this );
|
||||
#elif defined( POSIX )
|
||||
_snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p/0x%p)", this, m_threadId );
|
||||
#endif
|
||||
m_szName[sizeof(m_szName) - 1] = 0;
|
||||
}
|
||||
return m_szName;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
INLINE_ON_PS3 void CThread::SetName(const char *pszName)
|
||||
{
|
||||
AUTO_LOCK( m_Lock );
|
||||
strncpy( m_szName, pszName, sizeof(m_szName) - 1 );
|
||||
m_szName[sizeof(m_szName) - 1] = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Functions for the other threads
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Start thread running - error if already running
|
||||
INLINE_ON_PS3 bool CThread::Start( unsigned nBytesStack, ThreadPriorityEnum_t nPriority )
|
||||
{
|
||||
AUTO_LOCK( m_Lock );
|
||||
|
||||
if ( IsAlive() )
|
||||
{
|
||||
AssertMsg( 0, "Tried to create a thread that has already been created!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bInitSuccess = false;
|
||||
CThreadEvent createComplete;
|
||||
ThreadInit_t init = { this, &createComplete, &bInitSuccess };
|
||||
|
||||
#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
|
||||
{
|
||||
int iValidEntries = GetCallStack_Fast( init.ParentStackTrace, ARRAYSIZE( init.ParentStackTrace ), 0 );
|
||||
for( int i = iValidEntries; i < ARRAYSIZE( init.ParentStackTrace ); ++i )
|
||||
{
|
||||
init.ParentStackTrace[i] = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
m_hThread = (HANDLE)CreateThread( NULL,
|
||||
nBytesStack,
|
||||
(LPTHREAD_START_ROUTINE)GetThreadProc(),
|
||||
new ThreadInit_t(init),
|
||||
nBytesStack ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0,
|
||||
(LPDWORD)&m_threadId );
|
||||
|
||||
if( nPriority != TP_PRIORITY_DEFAULT )
|
||||
{
|
||||
SetThreadPriority( m_hThread, nPriority );
|
||||
}
|
||||
|
||||
if ( !m_hThread )
|
||||
{
|
||||
AssertMsg1( 0, "Failed to create thread (error 0x%x)", GetLastError() );
|
||||
return false;
|
||||
}
|
||||
#elif PLATFORM_PS3
|
||||
// On the PS3, a stack size of 0 doesn't imply a default stack size, so we need to force it to our
|
||||
// own default size.
|
||||
if ( nBytesStack == 0 )
|
||||
{
|
||||
nBytesStack = PS3_SYS_PPU_THREAD_COMMON_STACK_SIZE;
|
||||
}
|
||||
|
||||
//The thread is about to begin
|
||||
m_threadEnd.Reset();
|
||||
|
||||
// sony documentation:
|
||||
// "If the PPU thread is not joined by sys_ppu_thread_join() after exit,
|
||||
// it should always be created as non-joinable (not specifying
|
||||
// SYS_PPU_THREAD_CREATE_JOINABLE). Otherwise, some resources are left
|
||||
// allocated after termination of the PPU thread as if memory leaks."
|
||||
const char* threadName=m_szName;
|
||||
if ( sys_ppu_thread_create( &m_threadId,
|
||||
(void(*)(uint64_t))GetThreadProc(),
|
||||
(uint64_t)(new ThreadInit_t( init )),
|
||||
nPriority,
|
||||
nBytesStack,
|
||||
SYS_PPU_THREAD_CREATE_JOINABLE ,
|
||||
threadName ) != CELL_OK )
|
||||
{
|
||||
AssertMsg1( 0, "Failed to create thread (error 0x%x)", errno );
|
||||
return false;
|
||||
}
|
||||
|
||||
bInitSuccess = true;
|
||||
#elif PLATFORM_POSIX
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init( &attr );
|
||||
pthread_attr_setstacksize( &attr, MAX( nBytesStack, 1024u*1024 ) );
|
||||
//lwss - fix memory leak here
|
||||
m_threadInit = ThreadInit_t( init );
|
||||
//if ( pthread_create( &m_threadId, &attr, (void *(*)(void *))GetThreadProc(), new ThreadInit_t( init ) ) != 0 )
|
||||
if ( pthread_create( &m_threadId, &attr, (void *(*)(void *))GetThreadProc(), &m_threadInit ) != 0 )
|
||||
//lwss end
|
||||
{
|
||||
AssertMsg1( 0, "Failed to create thread (error 0x%x)", GetLastError() );
|
||||
return false;
|
||||
}
|
||||
bInitSuccess = true;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if ( !WaitForCreateComplete( &createComplete ) )
|
||||
{
|
||||
Msg( "Thread failed to initialize\n" );
|
||||
#ifdef _WIN32
|
||||
CloseHandle( m_hThread );
|
||||
m_hThread = NULL;
|
||||
#elif defined( _PS3 )
|
||||
m_threadEnd.Set();
|
||||
m_threadId = NULL;
|
||||
m_threadZombieId = 0;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !bInitSuccess )
|
||||
{
|
||||
Msg( "Thread failed to initialize\n" );
|
||||
#ifdef _WIN32
|
||||
CloseHandle( m_hThread );
|
||||
m_hThread = NULL;
|
||||
#elif defined(POSIX) && !defined( _PS3 )
|
||||
m_threadId = 0;
|
||||
m_threadZombieId = 0;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if ( !m_hThread )
|
||||
{
|
||||
Msg( "Thread exited immediately\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
AddThreadHandleToIDMap( m_hThread, m_threadId );
|
||||
return !!m_hThread;
|
||||
#elif defined(POSIX)
|
||||
return !!m_threadId;
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
//
|
||||
// Return true if the thread has been created and hasn't yet exited
|
||||
//
|
||||
|
||||
INLINE_ON_PS3 bool CThread::IsAlive()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
DWORD dwExitCode;
|
||||
return (
|
||||
m_hThread
|
||||
&& GetExitCodeThread(m_hThread, &dwExitCode)
|
||||
&& dwExitCode == STILL_ACTIVE );
|
||||
#elif defined(POSIX)
|
||||
return !!m_threadId;
|
||||
#endif
|
||||
}
|
||||
|
||||
// This method causes the current thread to wait until this thread
|
||||
// is no longer alive.
|
||||
INLINE_ON_PS3 bool CThread::Join( unsigned timeout )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if ( m_hThread )
|
||||
#elif defined(POSIX)
|
||||
if ( m_threadId || m_threadZombieId )
|
||||
#endif
|
||||
{
|
||||
AssertMsg(GetCurrentCThread() != this, _T("Thread cannot be joined with self"));
|
||||
|
||||
#ifdef _WIN32
|
||||
return ThreadJoin( (ThreadHandle_t)m_hThread, timeout );
|
||||
#elif defined(POSIX)
|
||||
bool ret = ThreadJoin( (ThreadHandle_t)(m_threadId ? m_threadId : m_threadZombieId), timeout );
|
||||
m_threadZombieId = 0;
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
INLINE_ON_PS3 ThreadHandle_t CThread::GetThreadHandle()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (ThreadHandle_t)m_hThread;
|
||||
#else
|
||||
return (ThreadHandle_t)m_threadId;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
INLINE_ON_PS3 int CThread::GetResult()
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Functions for both this, and maybe, and other threads
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Forcibly, abnormally, but relatively cleanly stop the thread
|
||||
//
|
||||
|
||||
INLINE_ON_PS3 void CThread::Stop(int exitCode)
|
||||
{
|
||||
if ( !IsAlive() )
|
||||
return;
|
||||
|
||||
if ( GetCurrentCThread() == this )
|
||||
{
|
||||
#if !defined( _PS3 )
|
||||
m_result = exitCode;
|
||||
if ( !( m_flags & SUPPORT_STOP_PROTOCOL ) )
|
||||
{
|
||||
OnExit();
|
||||
g_pCurThread = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
CloseHandle( m_hThread );
|
||||
RemoveThreadHandleToIDMap( m_hThread );
|
||||
m_hThread = NULL;
|
||||
#else
|
||||
m_threadId = 0;
|
||||
m_threadZombieId = 0;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exitCode;
|
||||
}
|
||||
#else
|
||||
AssertMsg( false, "Called CThread::Stop() for a platform that doesn't have it!\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
AssertMsg( 0, "Only thread can stop self: Use a higher-level protocol");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
// Get the priority
|
||||
INLINE_ON_PS3 int CThread::GetPriority() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetThreadPriority(m_hThread);
|
||||
#elif defined( _PS3 )
|
||||
return ThreadGetPriority( (ThreadHandle_t) m_threadId );
|
||||
#elif defined(POSIX)
|
||||
struct sched_param thread_param;
|
||||
int policy;
|
||||
pthread_getschedparam( m_threadId, &policy, &thread_param );
|
||||
return thread_param.sched_priority;
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
// Set the priority
|
||||
INLINE_ON_PS3 bool CThread::SetPriority(int priority)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return ThreadSetPriority( (ThreadHandle_t)m_hThread, priority );
|
||||
#else
|
||||
return ThreadSetPriority( (ThreadHandle_t)m_threadId, priority );
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
// Suspend a thread
|
||||
INLINE_ON_PS3 unsigned CThread::Suspend()
|
||||
{
|
||||
AssertMsg( ThreadGetCurrentId() == (ThreadId_t)m_threadId, "Cannot call CThread::Suspend from outside thread" );
|
||||
|
||||
if ( ThreadGetCurrentId() != (ThreadId_t)m_threadId )
|
||||
{
|
||||
DebuggerBreakIfDebugging();
|
||||
}
|
||||
|
||||
m_NotSuspendedEvent.Reset();
|
||||
m_NotSuspendedEvent.Wait();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
INLINE_ON_PS3 unsigned CThread::Resume()
|
||||
{
|
||||
if ( m_NotSuspendedEvent.Check() )
|
||||
{
|
||||
DevWarning( "Called Resume() on a thread that is not suspended!\n" );
|
||||
}
|
||||
m_NotSuspendedEvent.Set();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
// Force hard-termination of thread. Used for critical failures.
|
||||
INLINE_ON_PS3 bool CThread::Terminate(int exitCode)
|
||||
{
|
||||
#if defined( _X360 )
|
||||
AssertMsg( 0, "Cannot terminate a thread on the Xbox!" );
|
||||
return false;
|
||||
#elif defined( _WIN32 )
|
||||
// I hope you know what you're doing!
|
||||
if (!TerminateThread(m_hThread, exitCode))
|
||||
return false;
|
||||
CloseHandle( m_hThread );
|
||||
RemoveThreadHandleToIDMap( m_hThread );
|
||||
m_hThread = NULL;
|
||||
#elif defined( _PS3 )
|
||||
m_threadEnd.Set();
|
||||
m_threadId = NULL;
|
||||
#elif defined(POSIX)
|
||||
pthread_kill( m_threadId, SIGKILL );
|
||||
m_threadId = 0;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Global methods
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Get the Thread object that represents the current thread, if any.
|
||||
// Can return NULL if the current thread was not created using
|
||||
// CThread
|
||||
//
|
||||
|
||||
INLINE_ON_PS3 CThread *CThread::GetCurrentCThread()
|
||||
{
|
||||
#ifdef _PS3
|
||||
return GetCurThreadPS3();
|
||||
#else
|
||||
return g_pCurThread;
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
//
|
||||
// Offer a context switch. Under Win32, equivalent to Sleep(0)
|
||||
//
|
||||
|
||||
#ifdef Yield
|
||||
#undef Yield
|
||||
#endif
|
||||
INLINE_ON_PS3 void CThread::Yield()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::Sleep(0);
|
||||
#elif defined( _PS3 )
|
||||
// sys_ppu_thread_yield doesn't seem to function properly, so sleep instead.
|
||||
sys_timer_usleep( 60 );
|
||||
#elif defined(POSIX)
|
||||
sched_yield();
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
//
|
||||
// This method causes the current thread to yield and not to be
|
||||
// scheduled for further execution until a certain amount of real
|
||||
// time has elapsed, more or less. Duration is in milliseconds
|
||||
|
||||
INLINE_ON_PS3 void CThread::Sleep( unsigned duration )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::Sleep(duration);
|
||||
#elif defined (_PS3)
|
||||
sys_timer_usleep( duration * 1000 );
|
||||
#elif defined(POSIX)
|
||||
usleep( duration * 1000 );
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
// Optional pre-run call, with ability to fail-create. Note Init()
|
||||
// is forced synchronous with Start()
|
||||
INLINE_ON_PS3 bool CThread::Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
#if defined( _PS3 )
|
||||
INLINE_ON_PS3 int CThread::Run()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif // _PS3
|
||||
|
||||
// Called when the thread exits
|
||||
INLINE_ON_PS3 void CThread::OnExit() { }
|
||||
|
||||
// Allow for custom start waiting
|
||||
INLINE_ON_PS3 bool CThread::WaitForCreateComplete( CThreadEvent *pEvent )
|
||||
{
|
||||
// Force serialized thread creation...
|
||||
if (!pEvent->Wait(60000))
|
||||
{
|
||||
AssertMsg( 0, "Probably deadlock or failure waiting for thread to initialize." );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE_ON_PS3 bool CThread::IsThreadRunning()
|
||||
{
|
||||
#ifdef _PS3
|
||||
// ThreadIsThreadIdRunning() doesn't work on PS3 if the thread is in a zombie state
|
||||
return m_eventTheadExit.Check();
|
||||
#else
|
||||
return ThreadIsThreadIdRunning( (ThreadId_t)m_threadId );
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
INLINE_ON_PS3 CThread::ThreadProc_t CThread::GetThreadProc()
|
||||
{
|
||||
return ThreadProc;
|
||||
}
|
||||
|
||||
INLINE_ON_PS3 void CThread::ThreadProcRunWithMinidumpHandler( void *pv )
|
||||
{
|
||||
ThreadInit_t *pInit = reinterpret_cast<ThreadInit_t*>(pv);
|
||||
pInit->pThread->m_result = pInit->pThread->Run();
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
unsigned long STDCALL CThread::ThreadProc(LPVOID pv)
|
||||
#else
|
||||
INLINE_ON_PS3 void* CThread::ThreadProc(LPVOID pv)
|
||||
#endif
|
||||
{
|
||||
#if defined( POSIX ) || defined( _PS3 )
|
||||
ThreadInit_t *pInit = reinterpret_cast<ThreadInit_t*>(pv);
|
||||
#else
|
||||
std::auto_ptr<ThreadInit_t> pInit((ThreadInit_t *)pv);
|
||||
#endif
|
||||
|
||||
#ifdef _X360
|
||||
// Make sure all threads are consistent w.r.t floating-point math
|
||||
SetupFPUControlWord();
|
||||
#endif
|
||||
AllocateThreadID();
|
||||
|
||||
CThread *pThread = pInit->pThread;
|
||||
#ifdef _PS3
|
||||
SetCurThreadPS3( pThread );
|
||||
#else
|
||||
g_pCurThread = pThread;
|
||||
#endif
|
||||
|
||||
pThread->m_pStackBase = AlignValue( &pThread, 4096 );
|
||||
|
||||
pInit->pThread->m_result = -1;
|
||||
|
||||
#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
|
||||
CStackTop_ReferenceParentStack stackTop( pInit->ParentStackTrace, ARRAYSIZE( pInit->ParentStackTrace ) );
|
||||
#endif
|
||||
|
||||
bool bInitSuccess = true;
|
||||
if ( pInit->pfInitSuccess )
|
||||
*(pInit->pfInitSuccess) = false;
|
||||
|
||||
#ifdef _PS3
|
||||
*(pInit->pfInitSuccess) = pInit->pThread->Init();
|
||||
#else
|
||||
try
|
||||
{
|
||||
bInitSuccess = pInit->pThread->Init();
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
pInit->pInitCompleteEvent->Set();
|
||||
throw;
|
||||
}
|
||||
#endif // _PS3
|
||||
|
||||
if ( pInit->pfInitSuccess )
|
||||
*(pInit->pfInitSuccess) = bInitSuccess;
|
||||
pInit->pInitCompleteEvent->Set();
|
||||
if (!bInitSuccess)
|
||||
return 0;
|
||||
|
||||
if ( !Plat_IsInDebugSession() && (pInit->pThread->m_flags & SUPPORT_STOP_PROTOCOL) )
|
||||
{
|
||||
#ifndef _PS3
|
||||
try
|
||||
#endif
|
||||
{
|
||||
pInit->pThread->m_result = pInit->pThread->Run();
|
||||
}
|
||||
|
||||
#ifndef _PS3
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined( _WIN32 )
|
||||
CatchAndWriteMiniDumpForVoidPtrFn( ThreadProcRunWithMinidumpHandler, pv, false );
|
||||
#else
|
||||
pInit->pThread->m_result = pInit->pThread->Run();
|
||||
#endif
|
||||
}
|
||||
|
||||
pInit->pThread->OnExit();
|
||||
#ifdef _PS3
|
||||
SetCurThreadPS3( NULL );
|
||||
#else
|
||||
g_pCurThread = NULL;
|
||||
#endif
|
||||
FreeThreadID();
|
||||
|
||||
AUTO_LOCK( pThread->m_Lock );
|
||||
#ifdef _WIN32
|
||||
CloseHandle( pThread->m_hThread );
|
||||
RemoveThreadHandleToIDMap( pThread->m_hThread );
|
||||
pThread->m_hThread = NULL;
|
||||
#elif defined( _PS3 )
|
||||
pThread->m_threadZombieId = pThread->m_threadId;
|
||||
pThread->m_threadEnd.Set();
|
||||
pThread->m_threadId = 0;
|
||||
#elif defined(POSIX)
|
||||
pThread->m_threadZombieId = pThread->m_threadId;
|
||||
pThread->m_threadId = 0;
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
pThread->m_ExitEvent.Set();
|
||||
#ifdef _PS3
|
||||
{
|
||||
pThread->m_Lock.Unlock();
|
||||
sys_ppu_thread_exit( pInit->pThread->m_result );
|
||||
// reacquire the lock in case thread exit didn't actually exit the thread, so that
|
||||
// AUTO_LOCK won't double-unlock the lock (to keep it paired)
|
||||
pThread->m_Lock.Lock();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined( POSIX )|| defined( _PS3 )
|
||||
return (void*)(uintp)pInit->pThread->m_result;
|
||||
#else
|
||||
return pInit->pThread->m_result;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // THREADTOOLS_INL
|
@ -36,15 +36,38 @@
|
||||
|
||||
#if defined( PLATFORM_64BITS )
|
||||
|
||||
#if defined (PLATFORM_WINDOWS)
|
||||
//typedef __m128i int128;
|
||||
//inline int128 int128_zero() { return _mm_setzero_si128(); }
|
||||
#else // PLATFORM_WINDOWS
|
||||
typedef __int128_t int128;
|
||||
#define int128_zero() 0
|
||||
#endif// PLATFORM_WINDOWS
|
||||
|
||||
#define TSLIST_HEAD_ALIGNMENT 16
|
||||
#define TSLIST_NODE_ALIGNMENT 16
|
||||
|
||||
#ifdef POSIX
|
||||
inline bool ThreadInterlockedAssignIf128( int128 volatile * pDest, const int128 &value, const int128 &comparand )
|
||||
{
|
||||
// We do not want the original comparand modified by the swap
|
||||
// so operate on a local copy.
|
||||
int128 local_comparand = comparand;
|
||||
return __sync_bool_compare_and_swap( pDest, local_comparand, value );
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool ThreadInterlockedAssignIf64x128( volatile int128 *pDest, const int128 &value, const int128 &comperand )
|
||||
{ return ThreadInterlockedAssignIf128( pDest, value, comperand ); }
|
||||
{
|
||||
return ThreadInterlockedAssignIf128( pDest, value, comperand );
|
||||
}
|
||||
#else
|
||||
#define TSLIST_HEAD_ALIGNMENT 8
|
||||
#define TSLIST_NODE_ALIGNMENT 8
|
||||
inline bool ThreadInterlockedAssignIf64x128( volatile int64 *pDest, const int64 value, const int64 comperand )
|
||||
{ return ThreadInterlockedAssignIf64( pDest, value, comperand ); }
|
||||
{
|
||||
return ThreadInterlockedAssignIf64( pDest, value, comperand );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -99,13 +122,13 @@ union TSLIST_HEAD_ALIGN TSLHead_t
|
||||
// because Sequence can be pretty much random. We could operate on both of them separately,
|
||||
// but it could perhaps (?) lead to problems with store forwarding. I don't know 'cause I didn't
|
||||
// performance-test or design original code, I'm just making it work on PowerPC.
|
||||
#ifdef VALVE_BIG_ENDIAN
|
||||
#ifdef VALVE_BIG_ENDIAN
|
||||
int16 Sequence;
|
||||
int16 Depth;
|
||||
#else
|
||||
#else
|
||||
int16 Depth;
|
||||
int16 Sequence;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef PLATFORM_64BITS
|
||||
int32 Padding;
|
||||
#endif
|
||||
@ -132,33 +155,33 @@ class CTSListBase
|
||||
public:
|
||||
|
||||
// override new/delete so we can guarantee 8-byte aligned allocs
|
||||
static void * operator new( size_t size )
|
||||
static void * operator new(size_t size)
|
||||
{
|
||||
CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
|
||||
CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
|
||||
static void * operator new(size_t size, int nBlockUse, const char *pFileName, int nLine)
|
||||
{
|
||||
CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
|
||||
CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
static void operator delete( void *p)
|
||||
static void operator delete(void *p)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
|
||||
static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
|
||||
static void operator delete(void *p, int nBlockUse, const char *pFileName, int nLine)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
|
||||
private:
|
||||
// These ain't gonna work
|
||||
static void * operator new[] ( size_t size );
|
||||
static void operator delete [] ( void *p);
|
||||
|
||||
static void * operator new[]( size_t size );
|
||||
static void operator delete[]( void *p );
|
||||
|
||||
public:
|
||||
|
||||
CTSListBase()
|
||||
@ -204,22 +227,22 @@ public:
|
||||
TSLHead_t oldHead;
|
||||
TSLHead_t newHead;
|
||||
|
||||
#if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
|
||||
#if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
|
||||
__lwsync(); // write-release barrier
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_64BITS
|
||||
newHead.value.Padding = 0;
|
||||
#endif
|
||||
for (;;)
|
||||
for ( ;; )
|
||||
{
|
||||
oldHead.value64x128 = m_Head.value64x128;
|
||||
pNode->Next = oldHead.value.Next;
|
||||
newHead.value.Next = pNode;
|
||||
|
||||
|
||||
newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence + 0x10001;
|
||||
|
||||
|
||||
|
||||
|
||||
if ( ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) )
|
||||
{
|
||||
break;
|
||||
@ -231,7 +254,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((no_sanitize("address"))) TSLNodeBase_t *Pop()
|
||||
TSLNodeBase_t *Pop()
|
||||
{
|
||||
#ifdef USE_NATIVE_SLIST
|
||||
#ifdef _X360
|
||||
@ -248,21 +271,21 @@ public:
|
||||
#ifdef PLATFORM_64BITS
|
||||
newHead.value.Padding = 0;
|
||||
#endif
|
||||
for (;;)
|
||||
for ( ;; )
|
||||
{
|
||||
oldHead.value64x128 = m_Head.value64x128;
|
||||
if ( !oldHead.value.Next )
|
||||
return NULL;
|
||||
|
||||
newHead.value.Next = oldHead.value.Next->Next;
|
||||
newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence - 1;
|
||||
newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence - 1;
|
||||
|
||||
|
||||
if ( ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) )
|
||||
{
|
||||
#if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
|
||||
__lwsync(); // read-acquire barrier
|
||||
#endif
|
||||
#if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
|
||||
__lwsync(); // read-acquire barrier
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
ThreadPause();
|
||||
@ -301,7 +324,7 @@ public:
|
||||
// I didn't construct this code. In any case, leaving it as is on big-endian
|
||||
newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence & 0xffff0000;
|
||||
|
||||
} while( !ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) );
|
||||
} while ( !ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) );
|
||||
|
||||
return (TSLNodeBase_t *)oldHead.value.Next;
|
||||
#endif
|
||||
@ -315,7 +338,7 @@ public:
|
||||
int Count() const
|
||||
{
|
||||
#ifdef USE_NATIVE_SLIST
|
||||
return QueryDepthSList( const_cast<TSLHead_t*>( &m_Head ) );
|
||||
return QueryDepthSList( const_cast<TSLHead_t*>(&m_Head) );
|
||||
#else
|
||||
return m_Head.value.Depth;
|
||||
#endif
|
||||
@ -349,7 +372,7 @@ public:
|
||||
// similar to CTSSimpleList except that it allocates it's own pool objects
|
||||
// and frees them on destruct. Also it does not overlay the TSNodeBase_t memory
|
||||
// on T's memory
|
||||
template< class T >
|
||||
template< class T >
|
||||
class TSLIST_HEAD_ALIGN CTSPool : public CTSListBase
|
||||
{
|
||||
// packs the node and the item (T) into a single struct and pools those
|
||||
@ -380,7 +403,7 @@ public:
|
||||
void PutObject( T *pInfo )
|
||||
{
|
||||
char *pElem = (char *)pInfo;
|
||||
pElem -= offsetof(simpleTSPoolStruct_t,elem);
|
||||
pElem -= offsetof( simpleTSPoolStruct_t, elem );
|
||||
simpleTSPoolStruct_t *pNode = (simpleTSPoolStruct_t *)pElem;
|
||||
|
||||
CTSListBase::Push( pNode );
|
||||
@ -414,25 +437,25 @@ public:
|
||||
Node_t( const T &init ) : elem( init ) {}
|
||||
T elem;
|
||||
|
||||
// override new/delete so we can guarantee 8-byte aligned allocs
|
||||
static void * operator new( size_t size )
|
||||
{
|
||||
Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_NODE_ALIGNMENT, __FILE__, __LINE__ );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
// override new/delete so we can guarantee 8-byte aligned allocs
|
||||
static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
|
||||
static void * operator new(size_t size)
|
||||
{
|
||||
Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_NODE_ALIGNMENT, pFileName, nLine );
|
||||
Node_t *pNode = (Node_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_NODE_ALIGNMENT, __FILE__, __LINE__ );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
static void operator delete( void *p)
|
||||
{
|
||||
// override new/delete so we can guarantee 8-byte aligned allocs
|
||||
static void * operator new(size_t size, int nBlockUse, const char *pFileName, int nLine)
|
||||
{
|
||||
Node_t *pNode = (Node_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_NODE_ALIGNMENT, pFileName, nLine );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
static void operator delete(void *p)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
|
||||
}
|
||||
static void operator delete(void *p, int nBlockUse, const char *pFileName, int nLine)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
@ -476,7 +499,7 @@ public:
|
||||
Push( new Node_t( init ) );
|
||||
}
|
||||
|
||||
bool PopItem( T *pResult)
|
||||
bool PopItem( T *pResult )
|
||||
{
|
||||
Node_t *pNode = Pop();
|
||||
if ( !pNode )
|
||||
@ -564,7 +587,7 @@ public:
|
||||
Push( pNode );
|
||||
}
|
||||
|
||||
bool PopItem( T *pResult)
|
||||
bool PopItem( T *pResult )
|
||||
{
|
||||
Node_t *pNode = Pop();
|
||||
if ( !pNode )
|
||||
@ -608,37 +631,37 @@ class TSLIST_HEAD_ALIGN CTSQueue
|
||||
public:
|
||||
|
||||
// override new/delete so we can guarantee 8-byte aligned allocs
|
||||
static void * operator new( size_t size )
|
||||
static void * operator new(size_t size)
|
||||
{
|
||||
CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
|
||||
CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
// override new/delete so we can guarantee 8-byte aligned allocs
|
||||
static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
|
||||
static void * operator new(size_t size, int nBlockUse, const char *pFileName, int nLine)
|
||||
{
|
||||
CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
|
||||
CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
static void operator delete( void *p)
|
||||
static void operator delete(void *p)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
|
||||
static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
|
||||
static void operator delete(void *p, int nBlockUse, const char *pFileName, int nLine)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
|
||||
private:
|
||||
// These ain't gonna work
|
||||
static void * operator new[] ( size_t size ) throw()
|
||||
static void * operator new[]( size_t size ) throw()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void operator delete [] ( void *p)
|
||||
static void operator delete []( void *p )
|
||||
{
|
||||
}
|
||||
|
||||
@ -647,24 +670,24 @@ public:
|
||||
struct TSLIST_NODE_ALIGN Node_t
|
||||
{
|
||||
// override new/delete so we can guarantee 8-byte aligned allocs
|
||||
static void * operator new( size_t size )
|
||||
static void * operator new(size_t size)
|
||||
{
|
||||
Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
|
||||
Node_t *pNode = (Node_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
|
||||
static void * operator new(size_t size, int nBlockUse, const char *pFileName, int nLine)
|
||||
{
|
||||
Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
|
||||
Node_t *pNode = (Node_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
static void operator delete( void *p)
|
||||
static void operator delete(void *p)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
|
||||
static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
|
||||
static void operator delete(void *p, int nBlockUse, const char *pFileName, int nLine)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
@ -679,13 +702,13 @@ public:
|
||||
union TSLIST_HEAD_ALIGN NodeLink_t
|
||||
{
|
||||
// override new/delete so we can guarantee 8-byte aligned allocs
|
||||
static void * operator new( size_t size )
|
||||
static void * operator new(size_t size)
|
||||
{
|
||||
NodeLink_t *pNode = (NodeLink_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
|
||||
NodeLink_t *pNode = (NodeLink_t *)MemAlloc_AllocAlignedFileLine( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
|
||||
return pNode;
|
||||
}
|
||||
|
||||
static void operator delete( void *p)
|
||||
static void operator delete(void *p)
|
||||
{
|
||||
MemAlloc_FreeAligned( p );
|
||||
}
|
||||
@ -740,12 +763,12 @@ public:
|
||||
}
|
||||
|
||||
Node_t *pNode;
|
||||
while ( ( pNode = Pop() ) != NULL )
|
||||
while ( (pNode = Pop()) != NULL )
|
||||
{
|
||||
delete pNode;
|
||||
}
|
||||
|
||||
while ( ( pNode = (Node_t *)m_FreeNodes.Pop() ) != NULL )
|
||||
while ( (pNode = (Node_t *)m_FreeNodes.Pop()) != NULL )
|
||||
{
|
||||
delete pNode;
|
||||
}
|
||||
@ -765,7 +788,7 @@ public:
|
||||
}
|
||||
|
||||
Node_t *pNode;
|
||||
while ( ( pNode = Pop() ) != NULL )
|
||||
while ( (pNode = Pop()) != NULL )
|
||||
{
|
||||
m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
|
||||
}
|
||||
@ -846,7 +869,7 @@ public:
|
||||
|
||||
pNode->pNext = End();
|
||||
|
||||
for (;;)
|
||||
for ( ;; )
|
||||
{
|
||||
oldTail.value.sequence = m_Tail.value.sequence;
|
||||
oldTail.value.pNode = m_Tail.value.pNode;
|
||||
@ -870,7 +893,7 @@ public:
|
||||
|
||||
Node_t *Pop()
|
||||
{
|
||||
#define TSQUEUE_BAD_NODE_LINK ( (Node_t *)INT_TO_POINTER( 0xdeadbeef ) )
|
||||
#define TSQUEUE_BAD_NODE_LINK ( (Node_t *)INT_TO_POINTER( 0xdeadbeef ) )
|
||||
NodeLink_t * volatile pHead = &m_Head;
|
||||
NodeLink_t * volatile pTail = &m_Tail;
|
||||
Node_t * volatile * pHeadNode = &m_Head.value.pNode;
|
||||
@ -883,17 +906,17 @@ public:
|
||||
intp tailSequence;
|
||||
T elem;
|
||||
|
||||
for (;;)
|
||||
for ( ;; )
|
||||
{
|
||||
head.value.sequence = *pHeadSequence; // must grab sequence first, which allows condition below to ensure pNext is valid
|
||||
ThreadMemoryBarrier(); // need a barrier to prevent reordering of these assignments
|
||||
head.value.pNode = *pHeadNode;
|
||||
tailSequence = pTail->value.sequence;
|
||||
pNext = head.value.pNode->pNext;
|
||||
head.value.pNode = *pHeadNode;
|
||||
tailSequence = pTail->value.sequence;
|
||||
pNext = head.value.pNode->pNext;
|
||||
|
||||
// Checking pNext only to force optimizer to not reorder the assignment
|
||||
// to pNext and the compare of the sequence
|
||||
if ( !pNext || head.value.sequence != *pHeadSequence )
|
||||
if ( !pNext || head.value.sequence != *pHeadSequence )
|
||||
continue;
|
||||
|
||||
if ( bTestOptimizer )
|
||||
@ -916,7 +939,7 @@ public:
|
||||
FinishPush( pNext, oldTail );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if ( pNext != End() )
|
||||
{
|
||||
elem = pNext->elem; // NOTE: next could be a freed node here, by design
|
||||
@ -991,7 +1014,7 @@ private:
|
||||
NodeLink_t m_Tail;
|
||||
|
||||
CInterlockedInt m_Count;
|
||||
|
||||
|
||||
CTSListBase m_FreeNodes;
|
||||
} TSLIST_NODE_ALIGN_POST;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
@ -14,21 +14,33 @@
|
||||
|
||||
#include "utlrbtree.h"
|
||||
#include "utlvector.h"
|
||||
#include "utlbuffer.h"
|
||||
#include "generichash.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Allocates memory for strings, checking for duplicates first,
|
||||
// reusing exising strings if duplicate found.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
enum StringPoolCase_t
|
||||
{
|
||||
StringPoolCaseInsensitive,
|
||||
StringPoolCaseSensitive
|
||||
};
|
||||
|
||||
class CStringPool
|
||||
{
|
||||
public:
|
||||
CStringPool();
|
||||
CStringPool( StringPoolCase_t caseSensitivity = StringPoolCaseInsensitive );
|
||||
~CStringPool();
|
||||
|
||||
unsigned int Count() const;
|
||||
|
||||
const char * Allocate( const char *pszValue );
|
||||
// This feature is deliberately not supported because it's pretty dangerous
|
||||
// given current uses of CStringPool, which assume they can copy string pointers without
|
||||
// any refcounts.
|
||||
//void Free( const char *pszValue );
|
||||
void FreeAll();
|
||||
|
||||
// searches for a string already in the pool
|
||||
@ -48,14 +60,15 @@ protected:
|
||||
//
|
||||
// At some point this should replace CStringPool
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCountedStringPool
|
||||
template<class T>
|
||||
class CCountedStringPoolBase
|
||||
{
|
||||
public: // HACK, hash_item_t structure should not be public.
|
||||
|
||||
struct hash_item_t
|
||||
{
|
||||
char* pString;
|
||||
unsigned short nNextElement;
|
||||
T nNextElement;
|
||||
unsigned char nReferenceCount;
|
||||
unsigned char pad;
|
||||
};
|
||||
@ -67,13 +80,14 @@ public: // HACK, hash_item_t structure should not be public.
|
||||
HASH_TABLE_SIZE = 1024
|
||||
};
|
||||
|
||||
CUtlVector<unsigned short> m_HashTable; // Points to each element
|
||||
CUtlVector<T> m_HashTable; // Points to each element
|
||||
CUtlVector<hash_item_t> m_Elements;
|
||||
unsigned short m_FreeListStart;
|
||||
T m_FreeListStart;
|
||||
StringPoolCase_t m_caseSensitivity;
|
||||
|
||||
public:
|
||||
CCountedStringPool();
|
||||
virtual ~CCountedStringPool();
|
||||
CCountedStringPoolBase( StringPoolCase_t caseSensitivity = StringPoolCaseInsensitive );
|
||||
virtual ~CCountedStringPoolBase();
|
||||
|
||||
void FreeAll();
|
||||
|
||||
@ -82,10 +96,416 @@ public:
|
||||
void DereferenceString( const char* pIntrinsic );
|
||||
|
||||
// These are only reliable if there are less than 64k strings in your string pool
|
||||
unsigned short FindStringHandle( const char* pIntrinsic );
|
||||
unsigned short ReferenceStringHandle( const char* pIntrinsic );
|
||||
char *HandleToString( unsigned short handle );
|
||||
T FindStringHandle( const char* pIntrinsic );
|
||||
T ReferenceStringHandle( const char* pIntrinsic );
|
||||
char *HandleToString( T handle );
|
||||
void SpewStrings();
|
||||
unsigned Hash( const char *pszKey );
|
||||
|
||||
bool SaveToBuffer( CUtlBuffer &buffer );
|
||||
bool RestoreFromBuffer( CUtlBuffer &buffer );
|
||||
|
||||
// Debug helper method to validate that we didn't overflow
|
||||
void VerifyNotOverflowed( unsigned int value );
|
||||
};
|
||||
|
||||
typedef CCountedStringPoolBase<unsigned short> CCountedStringPool;
|
||||
|
||||
template<class T>
|
||||
inline CCountedStringPoolBase<T>::CCountedStringPoolBase( StringPoolCase_t caseSensitivity )
|
||||
{
|
||||
MEM_ALLOC_CREDIT();
|
||||
m_HashTable.EnsureCount(HASH_TABLE_SIZE);
|
||||
|
||||
for( int i = 0; i < m_HashTable.Count(); i++ )
|
||||
{
|
||||
m_HashTable[i] = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
m_FreeListStart = INVALID_ELEMENT;
|
||||
m_Elements.AddToTail();
|
||||
m_Elements[0].pString = NULL;
|
||||
m_Elements[0].nReferenceCount = 0;
|
||||
m_Elements[0].nNextElement = INVALID_ELEMENT;
|
||||
|
||||
m_caseSensitivity = caseSensitivity;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline CCountedStringPoolBase<T>::~CCountedStringPoolBase()
|
||||
{
|
||||
FreeAll();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void CCountedStringPoolBase<T>::FreeAll()
|
||||
{
|
||||
int i;
|
||||
|
||||
// Reset the hash table:
|
||||
for( i = 0; i < m_HashTable.Count(); i++ )
|
||||
{
|
||||
m_HashTable[i] = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
// Blow away the free list:
|
||||
m_FreeListStart = INVALID_ELEMENT;
|
||||
|
||||
for( i = 0; i < m_Elements.Count(); i++ )
|
||||
{
|
||||
if( m_Elements[i].pString )
|
||||
{
|
||||
delete [] m_Elements[i].pString;
|
||||
m_Elements[i].pString = NULL;
|
||||
m_Elements[i].nReferenceCount = 0;
|
||||
m_Elements[i].nNextElement = INVALID_ELEMENT;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all but the invalid element:
|
||||
m_Elements.RemoveAll();
|
||||
m_Elements.AddToTail();
|
||||
m_Elements[0].pString = NULL;
|
||||
m_Elements[0].nReferenceCount = 0;
|
||||
m_Elements[0].nNextElement = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline unsigned CCountedStringPoolBase<T>::Hash( const char *pszKey )
|
||||
{
|
||||
if ( m_caseSensitivity == StringPoolCaseInsensitive )
|
||||
{
|
||||
return HashStringCaseless( pszKey );
|
||||
}
|
||||
return HashString( pszKey );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T CCountedStringPoolBase<T>::FindStringHandle( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return INVALID_ELEMENT;
|
||||
|
||||
T nHashBucketIndex = ( Hash( pIntrinsic ) %HASH_TABLE_SIZE);
|
||||
T nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// Does the bucket already exist?
|
||||
if( nCurrentBucket != INVALID_ELEMENT )
|
||||
{
|
||||
for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
return nCurrentBucket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline char* CCountedStringPoolBase<T>::FindString( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return NULL;
|
||||
|
||||
// Yes, this will be NULL on failure.
|
||||
return m_Elements[FindStringHandle(pIntrinsic)].pString;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T CCountedStringPoolBase<T>::ReferenceStringHandle( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return INVALID_ELEMENT;
|
||||
|
||||
T nHashBucketIndex = ( Hash( pIntrinsic ) % HASH_TABLE_SIZE);
|
||||
T nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// Does the bucket already exist?
|
||||
if( nCurrentBucket != INVALID_ELEMENT )
|
||||
{
|
||||
for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
// Anyone who hits 65k references is permanant
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE )
|
||||
{
|
||||
m_Elements[nCurrentBucket].nReferenceCount ++ ;
|
||||
}
|
||||
return nCurrentBucket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_FreeListStart != INVALID_ELEMENT )
|
||||
{
|
||||
nCurrentBucket = m_FreeListStart;
|
||||
m_FreeListStart = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int newElement = m_Elements.AddToTail();
|
||||
VerifyNotOverflowed( newElement );
|
||||
nCurrentBucket = newElement;
|
||||
}
|
||||
|
||||
m_Elements[nCurrentBucket].nReferenceCount = 1;
|
||||
|
||||
// Insert at the beginning of the bucket:
|
||||
m_Elements[nCurrentBucket].nNextElement = m_HashTable[ nHashBucketIndex ];
|
||||
m_HashTable[ nHashBucketIndex ] = nCurrentBucket;
|
||||
|
||||
m_Elements[nCurrentBucket].pString = new char[Q_strlen( pIntrinsic ) + 1];
|
||||
Q_strcpy( m_Elements[nCurrentBucket].pString, pIntrinsic );
|
||||
|
||||
return nCurrentBucket;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void CCountedStringPoolBase<unsigned short>::VerifyNotOverflowed( unsigned int value ) { Assert( value < 0xffff ); }
|
||||
|
||||
template<>
|
||||
inline void CCountedStringPoolBase<unsigned int>::VerifyNotOverflowed( unsigned int value ) {}
|
||||
|
||||
template<class T>
|
||||
inline char* CCountedStringPoolBase<T>::ReferenceString( const char* pIntrinsic )
|
||||
{
|
||||
if(!pIntrinsic)
|
||||
return NULL;
|
||||
|
||||
return m_Elements[ReferenceStringHandle( pIntrinsic)].pString;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void CCountedStringPoolBase<T>::DereferenceString( const char* pIntrinsic )
|
||||
{
|
||||
// If we get a NULL pointer, just return
|
||||
if (!pIntrinsic)
|
||||
return;
|
||||
|
||||
T nHashBucketIndex = (Hash( pIntrinsic ) % m_HashTable.Count());
|
||||
T nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// If there isn't anything in the bucket, just return.
|
||||
if ( nCurrentBucket == INVALID_ELEMENT )
|
||||
return;
|
||||
|
||||
for( T previous = INVALID_ELEMENT; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
// Anyone who hits 65k references is permanant
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE )
|
||||
{
|
||||
m_Elements[nCurrentBucket].nReferenceCount --;
|
||||
}
|
||||
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount == 0 )
|
||||
{
|
||||
if( previous == INVALID_ELEMENT )
|
||||
{
|
||||
m_HashTable[nHashBucketIndex] = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Elements[previous].nNextElement = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
|
||||
delete [] m_Elements[nCurrentBucket].pString;
|
||||
m_Elements[nCurrentBucket].pString = NULL;
|
||||
m_Elements[nCurrentBucket].nReferenceCount = 0;
|
||||
|
||||
m_Elements[nCurrentBucket].nNextElement = m_FreeListStart;
|
||||
m_FreeListStart = nCurrentBucket;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
previous = nCurrentBucket;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline char* CCountedStringPoolBase<T>::HandleToString( T handle )
|
||||
{
|
||||
return m_Elements[handle].pString;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void CCountedStringPoolBase<T>::SpewStrings()
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < m_Elements.Count(); i++ )
|
||||
{
|
||||
char* string = m_Elements[i].pString;
|
||||
|
||||
Msg("String %d: ref:%d %s\n", i, m_Elements[i].nReferenceCount, string == NULL? "EMPTY - ok for slot zero only!" : string);
|
||||
}
|
||||
|
||||
Msg("\n%d total counted strings.", m_Elements.Count());
|
||||
}
|
||||
|
||||
#define STRING_POOL_VERSION MAKEID( 'C', 'S', 'P', '1' )
|
||||
#define MAX_STRING_SAVE 1024
|
||||
|
||||
template<>
|
||||
inline bool CCountedStringPoolBase<unsigned short>::SaveToBuffer( CUtlBuffer &buffer )
|
||||
{
|
||||
if ( m_Elements.Count() <= 1 )
|
||||
{
|
||||
// pool is empty, saving nothing
|
||||
// caller can check put position of buffer to detect
|
||||
return true;
|
||||
}
|
||||
|
||||
// signature/version
|
||||
buffer.PutInt( STRING_POOL_VERSION );
|
||||
|
||||
buffer.PutUnsignedShort( m_FreeListStart );
|
||||
|
||||
buffer.PutInt( m_HashTable.Count() );
|
||||
for ( int i = 0; i < m_HashTable.Count(); i++ )
|
||||
{
|
||||
buffer.PutUnsignedShort( m_HashTable[i] );
|
||||
}
|
||||
|
||||
buffer.PutInt( m_Elements.Count() );
|
||||
for ( int i = 1; i < m_Elements.Count(); i++ )
|
||||
{
|
||||
buffer.PutUnsignedShort( m_Elements[i].nNextElement );
|
||||
buffer.PutUnsignedChar( m_Elements[i].nReferenceCount );
|
||||
|
||||
const char *pString = m_Elements[i].pString;
|
||||
if ( strlen( pString ) >= MAX_STRING_SAVE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
buffer.PutString( pString ? pString : "" );
|
||||
}
|
||||
|
||||
return buffer.IsValid();
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool CCountedStringPoolBase<unsigned short>::RestoreFromBuffer( CUtlBuffer &buffer )
|
||||
{
|
||||
int signature = buffer.GetInt();
|
||||
if ( signature != STRING_POOL_VERSION )
|
||||
{
|
||||
// wrong version
|
||||
return false;
|
||||
}
|
||||
|
||||
FreeAll();
|
||||
|
||||
m_FreeListStart = buffer.GetUnsignedShort();
|
||||
|
||||
int hashCount = buffer.GetInt();
|
||||
m_HashTable.SetCount( hashCount );
|
||||
|
||||
for ( int i = 0; i < hashCount; i++ )
|
||||
{
|
||||
m_HashTable[i] = buffer.GetUnsignedShort();
|
||||
}
|
||||
|
||||
int tableCount = buffer.GetInt();
|
||||
if ( tableCount > 1 )
|
||||
{
|
||||
m_Elements.AddMultipleToTail( tableCount-1 );
|
||||
}
|
||||
|
||||
char tempString[MAX_STRING_SAVE];
|
||||
for ( int i = 1; i < tableCount; i++ )
|
||||
{
|
||||
m_Elements[i].nNextElement = buffer.GetUnsignedShort();
|
||||
m_Elements[i].nReferenceCount = buffer.GetUnsignedChar();
|
||||
buffer.GetString( tempString, sizeof( tempString ) );
|
||||
m_Elements[i].pString = strdup( tempString );
|
||||
}
|
||||
|
||||
return buffer.IsValid();
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool CCountedStringPoolBase<unsigned int>::SaveToBuffer( CUtlBuffer &buffer )
|
||||
{
|
||||
if ( m_Elements.Count() <= 1 )
|
||||
{
|
||||
// pool is empty, saving nothing
|
||||
// caller can check put position of buffer to detect
|
||||
return true;
|
||||
}
|
||||
|
||||
// signature/version
|
||||
buffer.PutInt( STRING_POOL_VERSION );
|
||||
|
||||
buffer.PutUnsignedInt( m_FreeListStart );
|
||||
|
||||
buffer.PutInt( m_HashTable.Count() );
|
||||
for ( int i = 0; i < m_HashTable.Count(); i++ )
|
||||
{
|
||||
buffer.PutUnsignedInt( m_HashTable[i] );
|
||||
}
|
||||
|
||||
buffer.PutInt( m_Elements.Count() );
|
||||
for ( int i = 1; i < m_Elements.Count(); i++ )
|
||||
{
|
||||
buffer.PutUnsignedInt( m_Elements[i].nNextElement );
|
||||
buffer.PutUnsignedChar( m_Elements[i].nReferenceCount );
|
||||
|
||||
const char *pString = m_Elements[i].pString;
|
||||
if ( strlen( pString ) >= MAX_STRING_SAVE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
buffer.PutString( pString ? pString : "" );
|
||||
}
|
||||
|
||||
return buffer.IsValid();
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool CCountedStringPoolBase<unsigned int>::RestoreFromBuffer( CUtlBuffer &buffer )
|
||||
{
|
||||
int signature = buffer.GetInt();
|
||||
if ( signature != STRING_POOL_VERSION )
|
||||
{
|
||||
// wrong version
|
||||
return false;
|
||||
}
|
||||
|
||||
FreeAll();
|
||||
|
||||
m_FreeListStart = buffer.GetUnsignedInt();
|
||||
|
||||
int hashCount = buffer.GetInt();
|
||||
m_HashTable.SetCount( hashCount );
|
||||
|
||||
for ( int i = 0; i < hashCount; i++ )
|
||||
{
|
||||
m_HashTable[i] = buffer.GetUnsignedInt();
|
||||
}
|
||||
|
||||
int tableCount = buffer.GetInt();
|
||||
if ( tableCount > 1 )
|
||||
{
|
||||
m_Elements.AddMultipleToTail( tableCount-1 );
|
||||
}
|
||||
|
||||
char tempString[MAX_STRING_SAVE];
|
||||
for ( int i = 1; i < tableCount; i++ )
|
||||
{
|
||||
m_Elements[i].nNextElement = buffer.GetUnsignedInt();
|
||||
m_Elements[i].nReferenceCount = buffer.GetUnsignedChar();
|
||||
buffer.GetString( tempString, sizeof( tempString ) );
|
||||
m_Elements[i].pString = strdup( tempString );
|
||||
}
|
||||
|
||||
return buffer.IsValid();
|
||||
}
|
||||
#endif // STRINGPOOL_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//====== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
@ -14,6 +14,8 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "unitlib/unitlib.h" // just here for tests - remove before checking in!!!
|
||||
|
||||
#include "tier1/utlmemory.h"
|
||||
#include "tier1/byteswap.h"
|
||||
#include <stdarg.h>
|
||||
@ -102,11 +104,48 @@ CUtlCharConversion *GetNoEscCharConversion();
|
||||
SetOverflowFuncs( static_cast <UtlBufferOverflowFunc_t>( _get ), static_cast <UtlBufferOverflowFunc_t>( _put ) )
|
||||
|
||||
|
||||
|
||||
typedef unsigned short ushort;
|
||||
|
||||
template < class A >
|
||||
static const char *GetFmtStr( int nRadix = 10, bool bPrint = true ) { Assert( 0 ); return ""; }
|
||||
#if defined( LINUX ) || defined( __clang__ ) || ( defined( _MSC_VER ) && _MSC_VER >= 1900 )
|
||||
template <> const char *GetFmtStr< short > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hd"; }
|
||||
template <> const char *GetFmtStr< ushort > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hu"; }
|
||||
template <> const char *GetFmtStr< int > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%d"; }
|
||||
template <> const char *GetFmtStr< uint > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 || nRadix == 16 ); return nRadix == 16 ? "%x" : "%u"; }
|
||||
template <> const char *GetFmtStr< int64 > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%lld"; }
|
||||
template <> const char *GetFmtStr< float > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%f"; }
|
||||
template <> const char *GetFmtStr< double > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return bPrint ? "%.15lf" : "%lf"; } // force Printf to print DBL_DIG=15 digits of precision for doubles - defaults to FLT_DIG=6
|
||||
#else
|
||||
template <> static const char *GetFmtStr< short > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hd"; }
|
||||
template <> static const char *GetFmtStr< ushort > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hu"; }
|
||||
template <> static const char *GetFmtStr< int > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%d"; }
|
||||
template <> static const char *GetFmtStr< uint > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 || nRadix == 16 ); return nRadix == 16 ? "%x" : "%u"; }
|
||||
template <> static const char *GetFmtStr< int64 > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%lld"; }
|
||||
template <> static const char *GetFmtStr< float > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%f"; }
|
||||
template <> static const char *GetFmtStr< double > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return bPrint ? "%.15lf" : "%lf"; } // force Printf to print DBL_DIG=15 digits of precision for doubles - defaults to FLT_DIG=6
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// Command parsing..
|
||||
//-----------------------------------------------------------------------------
|
||||
class CUtlBuffer
|
||||
{
|
||||
// Brian has on his todo list to revisit this as there are issues in some cases with CUtlVector using operator = instead of copy construtor in InsertMultiple, etc.
|
||||
// The unsafe case is something like this:
|
||||
// CUtlVector< CUtlBuffer > vecFoo;
|
||||
//
|
||||
// CUtlBuffer buf;
|
||||
// buf.Put( xxx );
|
||||
// vecFoo.Insert( buf );
|
||||
//
|
||||
// This will cause memory corruption when vecFoo is cleared
|
||||
//
|
||||
//private:
|
||||
// // Disallow copying
|
||||
// CUtlBuffer( const CUtlBuffer & );// { Assert( 0 ); }
|
||||
// CUtlBuffer &operator=( const CUtlBuffer & );// { Assert( 0 ); return *this; }
|
||||
|
||||
public:
|
||||
enum SeekType_t
|
||||
{
|
||||
@ -132,7 +171,19 @@ public:
|
||||
CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
|
||||
CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 );
|
||||
// This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param.
|
||||
CUtlBuffer( const void *pBuffer, int size, bool crap );
|
||||
CUtlBuffer( const void *pBuffer, int size, bool crap ) = delete;
|
||||
|
||||
// UtlBuffer objects should not be copyable; we do a slow copy if you use this but it asserts.
|
||||
// (REI: I'd like to delete these but we have some python bindings that currently rely on being able to copy these objects)
|
||||
CUtlBuffer( const CUtlBuffer& ); // = delete;
|
||||
CUtlBuffer& operator= ( const CUtlBuffer& ); // = delete;
|
||||
|
||||
#if VALVE_CPP11
|
||||
// UtlBuffer is non-copyable (same as CUtlMemory), but it is moveable. We would like to declare these with '= default'
|
||||
// but unfortunately VS2013 isn't fully C++11 compliant, so we have to manually declare these in the boilerplate way.
|
||||
CUtlBuffer( CUtlBuffer&& moveFrom ); // = default;
|
||||
CUtlBuffer& operator= ( CUtlBuffer&& moveFrom ); // = default;
|
||||
#endif
|
||||
|
||||
unsigned char GetFlags() const;
|
||||
|
||||
@ -143,11 +194,15 @@ public:
|
||||
// Makes sure we've got at least this much memory
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Access for direct read into buffer
|
||||
void * AccessForDirectRead( int nBytes );
|
||||
|
||||
// Attaches the buffer to external memory....
|
||||
void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
|
||||
bool IsExternallyAllocated() const;
|
||||
// Takes ownership of the passed memory, including freeing it when this buffer is destroyed.
|
||||
void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 );
|
||||
void *Detach();
|
||||
void* DetachMemory();
|
||||
|
||||
// copies data from another buffer
|
||||
void CopyBuffer( const CUtlBuffer &buffer );
|
||||
@ -156,9 +211,10 @@ public:
|
||||
void Swap( CUtlBuffer &buf );
|
||||
void Swap( CUtlMemory<uint8> &mem );
|
||||
|
||||
|
||||
FORCEINLINE void ActivateByteSwappingIfBigEndian( void )
|
||||
{
|
||||
if ( IsX360() )
|
||||
if ( ( IsX360() || IsPS3() ) )
|
||||
ActivateByteSwapping( true );
|
||||
}
|
||||
|
||||
@ -174,6 +230,9 @@ public:
|
||||
// Clears out the buffer; frees memory
|
||||
void Purge();
|
||||
|
||||
// Dump the buffer to stdout
|
||||
void Spew( );
|
||||
|
||||
// Read stuff out.
|
||||
// Binary mode: it'll just read the bits directly in, and characters will be
|
||||
// read for strings until a null character is reached.
|
||||
@ -185,28 +244,25 @@ public:
|
||||
unsigned short GetUnsignedShort( );
|
||||
int GetInt( );
|
||||
int64 GetInt64( );
|
||||
int GetIntHex( );
|
||||
unsigned int GetIntHex( );
|
||||
unsigned int GetUnsignedInt( );
|
||||
uint64 GetUnsignedInt64( );
|
||||
float GetFloat( );
|
||||
double GetDouble( );
|
||||
void * GetPtr();
|
||||
template <size_t maxLenInChars> void GetString( char( &pString )[maxLenInChars] )
|
||||
{
|
||||
GetStringInternal( pString, maxLenInChars );
|
||||
}
|
||||
|
||||
void GetString( char *pString, size_t maxLenInChars )
|
||||
{
|
||||
GetStringInternal( pString, maxLenInChars );
|
||||
}
|
||||
void * GetPtr();
|
||||
void GetString( char* pString, int nMaxChars );
|
||||
bool Get( void* pMem, int size );
|
||||
void GetLine( char* pLine, int nMaxChars );
|
||||
|
||||
void GetStringManualCharCount( char *pString, size_t maxLenInChars )
|
||||
{
|
||||
GetStringInternal( pString, maxLenInChars );
|
||||
GetString( pString, maxLenInChars );
|
||||
}
|
||||
|
||||
void Get( void* pMem, int size );
|
||||
void GetLine( char* pLine, int nMaxChars = 0 );
|
||||
template <size_t maxLenInChars> void GetString( char( &pString )[maxLenInChars] )
|
||||
{
|
||||
GetString( pString, maxLenInChars );
|
||||
}
|
||||
|
||||
// Used for getting objects that have a byteswap datadesc defined
|
||||
template <typename T> void GetObjects( T *dest, int count = 1 );
|
||||
@ -238,7 +294,7 @@ public:
|
||||
|
||||
// Just like scanf, but doesn't work in binary mode
|
||||
int Scanf( SCANF_FORMAT_STRING const char* pFmt, ... );
|
||||
int VaScanf( const char* pFmt, va_list list );
|
||||
int VaScanf( const char* pFmt, va_list list );
|
||||
|
||||
// Eats white space, advances Get index
|
||||
void EatWhiteSpace();
|
||||
@ -270,16 +326,16 @@ public:
|
||||
// PutString will not write a terminating character
|
||||
void PutChar( char c );
|
||||
void PutUnsignedChar( unsigned char uc );
|
||||
void PutUint64( uint64 ub );
|
||||
void PutInt16( int16 s16 );
|
||||
void PutShort( short s );
|
||||
void PutUnsignedShort( unsigned short us );
|
||||
void PutInt( int i );
|
||||
void PutInt64( int64 i );
|
||||
void PutUnsignedInt( unsigned int u );
|
||||
void PutUnsignedInt64( uint64 u );
|
||||
void PutUint64( uint64 u );
|
||||
void PutFloat( float f );
|
||||
void PutDouble( double d );
|
||||
void PutPtr( void * ); // Writes the pointer, not the pointed to
|
||||
void PutPtr( void * ); // Writes the pointer, not the pointed to
|
||||
void PutString( const char* pString );
|
||||
void Put( const void* pMem, int size );
|
||||
|
||||
@ -318,8 +374,8 @@ public:
|
||||
// Buffer base
|
||||
const void* Base() const;
|
||||
void* Base();
|
||||
// Returns the base as a const char*, only valid in text mode.
|
||||
const char *String() const;
|
||||
|
||||
const void* String() const;
|
||||
|
||||
// memory allocation size, does *not* reflect size written or read,
|
||||
// use TellPut or TellGet for that
|
||||
@ -352,6 +408,12 @@ public:
|
||||
// Temporarily disables pretty print
|
||||
void EnableTabs( bool bEnable );
|
||||
|
||||
#if !defined( _GAMECONSOLE )
|
||||
// Swap my internal memory with another buffer,
|
||||
// and copy all of its other members
|
||||
void SwapCopy( CUtlBuffer &other ) ;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// error flags
|
||||
enum
|
||||
@ -371,7 +433,10 @@ protected:
|
||||
bool CheckPut( int size );
|
||||
bool CheckGet( int size );
|
||||
|
||||
// NOTE: Pass in nPut here even though it is just a copy of m_Put. This is almost always called immediately
|
||||
// after modifying m_Put and this lets it stay in a register
|
||||
void AddNullTermination( );
|
||||
void AddNullTermination( int nPut );
|
||||
|
||||
// Methods to help with pretty-printing
|
||||
bool WasLastCharacterCR();
|
||||
@ -400,16 +465,18 @@ protected:
|
||||
// Call this to peek arbitrarily long into memory. It doesn't fail unless
|
||||
// it can't read *anything* new
|
||||
bool CheckArbitraryPeekGet( int nOffset, int &nIncrement );
|
||||
void GetStringInternal( char *pString, size_t maxLenInChars );
|
||||
|
||||
template <typename T> void GetType( T& dest, const char *pszFmt );
|
||||
template <typename T> void GetType( T& dest );
|
||||
template <typename T> void GetTypeBin( T& dest );
|
||||
template <typename T> bool GetTypeText( T &value, int nRadix = 10 );
|
||||
template <typename T> void GetObject( T *src );
|
||||
|
||||
template <typename T> void PutType( T src, const char *pszFmt );
|
||||
template <typename T> void PutType( T src );
|
||||
template <typename T> void PutTypeBin( T src );
|
||||
template <typename T> void PutObject( T *src );
|
||||
|
||||
// be sure to also update the copy constructor
|
||||
// and SwapCopy() when adding members.
|
||||
CUtlMemory<unsigned char> m_Memory;
|
||||
int m_Get;
|
||||
int m_Put;
|
||||
@ -417,7 +484,7 @@ protected:
|
||||
unsigned char m_Error;
|
||||
unsigned char m_Flags;
|
||||
unsigned char m_Reserved;
|
||||
#if defined( _X360 )
|
||||
#if defined( _GAMECONSOLE )
|
||||
unsigned char pad;
|
||||
#endif
|
||||
|
||||
@ -605,7 +672,7 @@ inline void CUtlBuffer::GetObject( T *dest )
|
||||
{
|
||||
if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
|
||||
{
|
||||
Q_memcpy( dest, PeekGet(), sizeof( T ) );
|
||||
*dest = *(T *)PeekGet();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -615,7 +682,7 @@ inline void CUtlBuffer::GetObject( T *dest )
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_memset( dest, 0, sizeof(T) );
|
||||
Q_memset( &dest, 0, sizeof(T) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -637,18 +704,18 @@ inline void CUtlBuffer::GetTypeBin( T &dest )
|
||||
{
|
||||
if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
|
||||
{
|
||||
Q_memcpy(&dest, PeekGet(), sizeof(T) );
|
||||
dest = *(T *)PeekGet();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Byteswap.SwapBufferToTargetEndian<T>( &dest, (T*)PeekGet() );
|
||||
}
|
||||
m_Get += sizeof(T);
|
||||
}
|
||||
m_Get += sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -656,8 +723,8 @@ inline void CUtlBuffer::GetTypeBin< float >( float &dest )
|
||||
{
|
||||
if ( CheckGet( sizeof( float ) ) )
|
||||
{
|
||||
uintptr_t pData = (uintptr_t)PeekGet();
|
||||
if ( IsX360() && ( pData & 0x03 ) )
|
||||
uintp pData = (uintp)PeekGet();
|
||||
if ( ( IsX360() || IsPS3() ) && ( pData & 0x03 ) )
|
||||
{
|
||||
// handle unaligned read
|
||||
((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
|
||||
@ -668,22 +735,148 @@ inline void CUtlBuffer::GetTypeBin< float >( float &dest )
|
||||
else
|
||||
{
|
||||
// aligned read
|
||||
Q_memcpy( &dest, (void*)pData, sizeof(float) );
|
||||
dest = *(float *)pData;
|
||||
}
|
||||
if ( m_Byteswap.IsSwappingBytes() )
|
||||
{
|
||||
m_Byteswap.SwapBufferToTargetEndian< float >( &dest, &dest );
|
||||
}
|
||||
m_Get += sizeof( float );
|
||||
}
|
||||
m_Get += sizeof( float );
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void CUtlBuffer::GetTypeBin< double >( double &dest )
|
||||
{
|
||||
if ( CheckGet( sizeof( double ) ) )
|
||||
{
|
||||
uintp pData = (uintp)PeekGet();
|
||||
if ( ( IsX360() || IsPS3() ) && ( pData & 0x07 ) )
|
||||
{
|
||||
// handle unaligned read
|
||||
((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
|
||||
((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1];
|
||||
((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2];
|
||||
((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3];
|
||||
((unsigned char*)&dest)[4] = ((unsigned char*)pData)[4];
|
||||
((unsigned char*)&dest)[5] = ((unsigned char*)pData)[5];
|
||||
((unsigned char*)&dest)[6] = ((unsigned char*)pData)[6];
|
||||
((unsigned char*)&dest)[7] = ((unsigned char*)pData)[7];
|
||||
}
|
||||
else
|
||||
{
|
||||
// aligned read
|
||||
dest = *(double *)pData;
|
||||
}
|
||||
if ( m_Byteswap.IsSwappingBytes() )
|
||||
{
|
||||
m_Byteswap.SwapBufferToTargetEndian< double >( &dest, &dest );
|
||||
}
|
||||
m_Get += sizeof( double );
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template < class T >
|
||||
inline T StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
Assert( 0 );
|
||||
*ppEnd = pString;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int8 StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
return ( int8 )strtol( pString, ppEnd, nRadix );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint8 StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
return ( uint8 )strtoul( pString, ppEnd, nRadix );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int16 StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
return ( int16 )strtol( pString, ppEnd, nRadix );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint16 StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
return ( uint16 )strtoul( pString, ppEnd, nRadix );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int32 StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
return ( int32 )strtol( pString, ppEnd, nRadix );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint32 StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
return ( uint32 )strtoul( pString, ppEnd, nRadix );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int64 StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
#if defined(_PS3) || defined(POSIX)
|
||||
return ( int64 )strtoll( pString, ppEnd, nRadix );
|
||||
#else // !_PS3
|
||||
return ( int64 )_strtoi64( pString, ppEnd, nRadix );
|
||||
#endif // _PS3
|
||||
}
|
||||
|
||||
template <>
|
||||
inline float StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
NOTE_UNUSED( nRadix );
|
||||
return ( float )strtod( pString, ppEnd );
|
||||
}
|
||||
|
||||
template <>
|
||||
inline double StringToNumber( char *pString, char **ppEnd, int nRadix )
|
||||
{
|
||||
NOTE_UNUSED( nRadix );
|
||||
return ( double )strtod( pString, ppEnd );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool CUtlBuffer::GetTypeText( T &value, int nRadix /*= 10*/ )
|
||||
{
|
||||
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
|
||||
int nLength = 128;
|
||||
if ( !CheckArbitraryPeekGet( 0, nLength ) )
|
||||
{
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
char *pStart = (char*)PeekGet();
|
||||
char* pEnd = pStart;
|
||||
value = StringToNumber< T >( pStart, &pEnd, nRadix );
|
||||
|
||||
int nBytesRead = (int)( pEnd - pStart );
|
||||
if ( nBytesRead == 0 )
|
||||
return false;
|
||||
|
||||
m_Get += nBytesRead;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void CUtlBuffer::GetType( T &dest, const char *pszFmt )
|
||||
inline void CUtlBuffer::GetType( T &dest )
|
||||
{
|
||||
if (!IsText())
|
||||
{
|
||||
@ -691,93 +884,115 @@ inline void CUtlBuffer::GetType( T &dest, const char *pszFmt )
|
||||
}
|
||||
else
|
||||
{
|
||||
dest = 0;
|
||||
Scanf( pszFmt, &dest );
|
||||
GetTypeText( dest );
|
||||
}
|
||||
}
|
||||
|
||||
inline char CUtlBuffer::GetChar( )
|
||||
{
|
||||
// LEGACY WARNING: this behaves differently than GetUnsignedChar()
|
||||
char c;
|
||||
GetType( c, "%c" );
|
||||
GetTypeBin( c ); // always reads as binary
|
||||
return c;
|
||||
}
|
||||
|
||||
inline unsigned char CUtlBuffer::GetUnsignedChar( )
|
||||
{
|
||||
// LEGACY WARNING: this behaves differently than GetChar()
|
||||
unsigned char c;
|
||||
GetType( c, "%u" );
|
||||
if (!IsText())
|
||||
{
|
||||
GetTypeBin( c );
|
||||
}
|
||||
else
|
||||
{
|
||||
c = ( unsigned char )GetUnsignedShort();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
inline short CUtlBuffer::GetShort( )
|
||||
{
|
||||
short s;
|
||||
GetType( s, "%d" );
|
||||
GetType( s );
|
||||
return s;
|
||||
}
|
||||
|
||||
inline unsigned short CUtlBuffer::GetUnsignedShort( )
|
||||
{
|
||||
unsigned short s;
|
||||
GetType( s, "%u" );
|
||||
GetType( s );
|
||||
return s;
|
||||
}
|
||||
|
||||
inline int CUtlBuffer::GetInt( )
|
||||
{
|
||||
int i;
|
||||
GetType( i, "%d" );
|
||||
GetType( i );
|
||||
return i;
|
||||
}
|
||||
|
||||
inline int64 CUtlBuffer::GetInt64( )
|
||||
{
|
||||
int64 i;
|
||||
GetType( i, "%lld" );
|
||||
GetType( i );
|
||||
return i;
|
||||
}
|
||||
|
||||
inline int CUtlBuffer::GetIntHex( )
|
||||
inline unsigned int CUtlBuffer::GetIntHex( )
|
||||
{
|
||||
int i;
|
||||
GetType( i, "%x" );
|
||||
uint i;
|
||||
if (!IsText())
|
||||
{
|
||||
GetTypeBin( i );
|
||||
}
|
||||
else
|
||||
{
|
||||
GetTypeText( i, 16 );
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
inline unsigned int CUtlBuffer::GetUnsignedInt( )
|
||||
{
|
||||
unsigned int u;
|
||||
GetType( u, "%u" );
|
||||
return u;
|
||||
unsigned int i;
|
||||
GetType( i );
|
||||
return i;
|
||||
}
|
||||
|
||||
inline uint64 CUtlBuffer::GetUnsignedInt64()
|
||||
{
|
||||
uint64 i;
|
||||
GetType( i );
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
inline float CUtlBuffer::GetFloat( )
|
||||
{
|
||||
float f;
|
||||
GetType( f, "%f" );
|
||||
GetType( f );
|
||||
return f;
|
||||
}
|
||||
|
||||
inline void *CUtlBuffer::GetPtr( )
|
||||
{
|
||||
void *p;
|
||||
// LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
|
||||
#ifndef PLATFORM_64BITS
|
||||
p = ( void* )GetUnsignedInt();
|
||||
#else
|
||||
p = ( void* )GetInt64();
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
inline double CUtlBuffer::GetDouble( )
|
||||
{
|
||||
double d;
|
||||
GetType( d, "%f" );
|
||||
GetType( d );
|
||||
return d;
|
||||
}
|
||||
|
||||
inline void *CUtlBuffer::GetPtr( )
|
||||
{
|
||||
void *p;
|
||||
// LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
|
||||
#if !defined(X64BITS) && !defined(PLATFORM_64BITS)
|
||||
p = ( void* )GetUnsignedInt();
|
||||
#else
|
||||
p = ( void* )GetInt64();
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Where am I writing?
|
||||
@ -835,14 +1050,14 @@ inline void CUtlBuffer::PutObject( T *src )
|
||||
{
|
||||
if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
|
||||
{
|
||||
Q_memcpy( PeekPut(), src, sizeof( T ) );
|
||||
*(T *)PeekPut() = *src;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Byteswap.SwapFieldsToTargetEndian<T>( (T*)PeekPut(), src );
|
||||
}
|
||||
m_Put += sizeof(T);
|
||||
AddNullTermination();
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
}
|
||||
|
||||
@ -864,19 +1079,93 @@ inline void CUtlBuffer::PutTypeBin( T src )
|
||||
{
|
||||
if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
|
||||
{
|
||||
Q_memcpy( PeekPut(), &src, sizeof( T ) );
|
||||
*(T *)PeekPut() = src;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Byteswap.SwapBufferToTargetEndian<T>( (T*)PeekPut(), &src );
|
||||
}
|
||||
m_Put += sizeof(T);
|
||||
AddNullTermination();
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
}
|
||||
|
||||
#if defined( _GAMECONSOLE )
|
||||
template <>
|
||||
inline void CUtlBuffer::PutTypeBin< float >( float src )
|
||||
{
|
||||
if ( CheckPut( sizeof( src ) ) )
|
||||
{
|
||||
if ( m_Byteswap.IsSwappingBytes() )
|
||||
{
|
||||
m_Byteswap.SwapBufferToTargetEndian<float>( &src, &src );
|
||||
}
|
||||
|
||||
//
|
||||
// Write the data
|
||||
//
|
||||
unsigned pData = (unsigned)PeekPut();
|
||||
if ( pData & 0x03 )
|
||||
{
|
||||
// handle unaligned write
|
||||
byte* dst = (byte*)pData;
|
||||
byte* srcPtr = (byte*)&src;
|
||||
dst[0] = srcPtr[0];
|
||||
dst[1] = srcPtr[1];
|
||||
dst[2] = srcPtr[2];
|
||||
dst[3] = srcPtr[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
*(float *)pData = src;
|
||||
}
|
||||
|
||||
m_Put += sizeof(float);
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void CUtlBuffer::PutTypeBin< double >( double src )
|
||||
{
|
||||
if ( CheckPut( sizeof( src ) ) )
|
||||
{
|
||||
if ( m_Byteswap.IsSwappingBytes() )
|
||||
{
|
||||
m_Byteswap.SwapBufferToTargetEndian<double>( &src, &src );
|
||||
}
|
||||
|
||||
//
|
||||
// Write the data
|
||||
//
|
||||
unsigned pData = (unsigned)PeekPut();
|
||||
if ( pData & 0x07 )
|
||||
{
|
||||
// handle unaligned write
|
||||
byte* dst = (byte*)pData;
|
||||
byte* srcPtr = (byte*)&src;
|
||||
dst[0] = srcPtr[0];
|
||||
dst[1] = srcPtr[1];
|
||||
dst[2] = srcPtr[2];
|
||||
dst[3] = srcPtr[3];
|
||||
dst[4] = srcPtr[4];
|
||||
dst[5] = srcPtr[5];
|
||||
dst[6] = srcPtr[6];
|
||||
dst[7] = srcPtr[7];
|
||||
}
|
||||
else
|
||||
{
|
||||
*(double *)pData = src;
|
||||
}
|
||||
|
||||
m_Put += sizeof(double);
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline void CUtlBuffer::PutType( T src, const char *pszFmt )
|
||||
inline void CUtlBuffer::PutType( T src )
|
||||
{
|
||||
if (!IsText())
|
||||
{
|
||||
@ -884,7 +1173,7 @@ inline void CUtlBuffer::PutType( T src, const char *pszFmt )
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf( pszFmt, src );
|
||||
Printf( GetFmtStr< T >(), src );
|
||||
}
|
||||
}
|
||||
|
||||
@ -952,68 +1241,74 @@ inline void CUtlBuffer::PutChar( char c )
|
||||
|
||||
inline void CUtlBuffer::PutUnsignedChar( unsigned char c )
|
||||
{
|
||||
PutType( c, "%u" );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutUint64( uint64 ub )
|
||||
{
|
||||
PutType( ub, "%llu" );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutInt16( int16 s16 )
|
||||
{
|
||||
PutType( s16, "%d" );
|
||||
if (!IsText())
|
||||
{
|
||||
PutTypeBin( c );
|
||||
}
|
||||
else
|
||||
{
|
||||
PutUnsignedShort( c );
|
||||
}
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutShort( short s )
|
||||
{
|
||||
PutType( s, "%d" );
|
||||
PutType( s );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutUnsignedShort( unsigned short s )
|
||||
{
|
||||
PutType( s, "%u" );
|
||||
PutType( s );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutInt( int i )
|
||||
{
|
||||
PutType( i, "%d" );
|
||||
PutType( i );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutInt64( int64 i )
|
||||
{
|
||||
PutType( i, "%llu" );
|
||||
PutType( i );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutUnsignedInt( unsigned int u )
|
||||
{
|
||||
PutType( u, "%u" );
|
||||
PutType( u );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutUnsignedInt64( uint64 i )
|
||||
{
|
||||
PutType( i );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutUint64( uint64 i )
|
||||
{
|
||||
PutType( i );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutFloat( float f )
|
||||
{
|
||||
PutType( f, "%f" );
|
||||
PutType( f );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutDouble( double d )
|
||||
{
|
||||
PutType( d, "%f" );
|
||||
PutType( d );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutPtr( void *p )
|
||||
{
|
||||
// LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
|
||||
if (!IsText())
|
||||
{
|
||||
PutTypeBin( p );
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf( "0x%p", p );
|
||||
}
|
||||
// LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
|
||||
if (!IsText())
|
||||
{
|
||||
PutTypeBin( p );
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf( "0x%p", p );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Am I a text buffer?
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1062,26 +1357,25 @@ inline bool CUtlBuffer::IsReadOnly() const
|
||||
//-----------------------------------------------------------------------------
|
||||
// Buffer base and size
|
||||
//-----------------------------------------------------------------------------
|
||||
inline const void* CUtlBuffer::Base() const
|
||||
{
|
||||
return m_Memory.Base();
|
||||
inline const void* CUtlBuffer::Base() const
|
||||
{
|
||||
return m_Memory.Base();
|
||||
}
|
||||
|
||||
inline void* CUtlBuffer::Base()
|
||||
{
|
||||
return m_Memory.Base();
|
||||
return m_Memory.Base();
|
||||
}
|
||||
|
||||
// Returns the base as a const char*, only valid in text mode.
|
||||
inline const char *CUtlBuffer::String() const
|
||||
inline const void* CUtlBuffer::String() const
|
||||
{
|
||||
Assert( IsText() );
|
||||
return reinterpret_cast<const char*>( m_Memory.Base() );
|
||||
}
|
||||
|
||||
inline int CUtlBuffer::Size() const
|
||||
{
|
||||
return m_Memory.NumAllocated();
|
||||
inline int CUtlBuffer::Size() const
|
||||
{
|
||||
return m_Memory.NumAllocated();
|
||||
}
|
||||
|
||||
|
||||
@ -1095,7 +1389,7 @@ inline void CUtlBuffer::Clear()
|
||||
m_Error = 0;
|
||||
m_nOffset = 0;
|
||||
m_nMaxPut = -1;
|
||||
AddNullTermination();
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::Purge()
|
||||
@ -1108,6 +1402,58 @@ inline void CUtlBuffer::Purge()
|
||||
m_Memory.Purge();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void *CUtlBuffer::AccessForDirectRead( int nBytes )
|
||||
{
|
||||
Assert( m_Get == 0 && m_Put == 0 && m_nMaxPut == 0 );
|
||||
EnsureCapacity( nBytes );
|
||||
m_nMaxPut = nBytes;
|
||||
return Base();
|
||||
}
|
||||
|
||||
inline void *CUtlBuffer::Detach()
|
||||
{
|
||||
void *p = m_Memory.Detach();
|
||||
Clear();
|
||||
return p;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void CUtlBuffer::Spew( )
|
||||
{
|
||||
SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
|
||||
|
||||
char pTmpLine[1024];
|
||||
while( IsValid() && GetBytesRemaining() )
|
||||
{
|
||||
V_memset( pTmpLine, 0, sizeof(pTmpLine) );
|
||||
Get( pTmpLine, MIN( ( size_t )GetBytesRemaining(), sizeof(pTmpLine)-1 ) );
|
||||
Msg( _T( "%s" ), pTmpLine );
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(_GAMECONSOLE)
|
||||
inline void CUtlBuffer::SwapCopy( CUtlBuffer &other )
|
||||
{
|
||||
m_Get = other.m_Get;
|
||||
m_Put = other.m_Put;
|
||||
m_Error = other.m_Error;
|
||||
m_Flags = other.m_Flags;
|
||||
m_Reserved = other.m_Reserved;
|
||||
m_nTab = other.m_nTab;
|
||||
m_nMaxPut = other.m_nMaxPut;
|
||||
m_nOffset = other.m_nOffset;
|
||||
m_GetOverflowFunc = other.m_GetOverflowFunc;
|
||||
m_PutOverflowFunc = other.m_PutOverflowFunc;
|
||||
m_Byteswap = other.m_Byteswap;
|
||||
|
||||
m_Memory.Swap( other.m_Memory );
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void CUtlBuffer::CopyBuffer( const CUtlBuffer &buffer )
|
||||
{
|
||||
CopyBuffer( buffer.Base(), buffer.TellPut() );
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright <EFBFBD> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Linked list container class
|
||||
//
|
||||
@ -26,6 +26,9 @@
|
||||
#define FOR_EACH_LL( listName, iteratorName ) \
|
||||
for( auto iteratorName=(listName).Head(); (listName).IsUtlLinkedList && iteratorName != (listName).InvalidIndex(); iteratorName = (listName).Next( iteratorName ) )
|
||||
|
||||
#define FOR_EACH_LL_BACK( listName, iteratorName ) \
|
||||
for( auto iteratorName=(listName).Tail(); (listName).IsUtlLinkedList && iteratorName != (listName).InvalidIndex(); iteratorName = (listName).Previous( iteratorName ) )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class CUtlLinkedList:
|
||||
// description:
|
||||
@ -65,12 +68,15 @@ public:
|
||||
typedef S IndexType_t; // should really be called IndexStorageType_t, but that would be a huge change
|
||||
typedef I IndexLocalType_t;
|
||||
typedef M MemoryAllocator_t;
|
||||
static const bool IsUtlLinkedList = true; // Used to match this at compiletime
|
||||
enum { IsUtlLinkedList = true }; // Used to match this at compiletime
|
||||
|
||||
// constructor, destructor
|
||||
CUtlLinkedList( int growSize = 0, int initSize = 0 );
|
||||
~CUtlLinkedList();
|
||||
|
||||
CUtlLinkedList( const CUtlLinkedList& ) = delete;
|
||||
CUtlLinkedList& operator=( const CUtlLinkedList& ) = delete;
|
||||
|
||||
// gets particular elements
|
||||
T& Element( I i );
|
||||
T const& Element( I i ) const;
|
||||
@ -115,6 +121,9 @@ public:
|
||||
I Alloc( bool multilist = false );
|
||||
void Free( I elem );
|
||||
|
||||
// Identify the owner of this linked list's memory:
|
||||
void SetAllocOwner( const char *pszAllocOwner );
|
||||
|
||||
// list modification
|
||||
void LinkBefore( I before, I elem );
|
||||
void LinkAfter( I after, I elem );
|
||||
@ -348,16 +357,13 @@ protected:
|
||||
typedef UtlLinkedListElem_t<T, S> ListElem_t;
|
||||
|
||||
// constructs the class
|
||||
I AllocInternal( bool multilist = false );
|
||||
I AllocInternal( bool multilist = false ) RESTRICT;
|
||||
void ConstructList();
|
||||
|
||||
// Gets at the list element....
|
||||
ListElem_t& InternalElement( I i ) { return m_Memory[i]; }
|
||||
ListElem_t const& InternalElement( I i ) const { return m_Memory[i]; }
|
||||
|
||||
// copy constructors not allowed
|
||||
CUtlLinkedList( CUtlLinkedList<T, S, ML, I, M> const& list ) { Assert(0); }
|
||||
|
||||
M m_Memory;
|
||||
I m_Head;
|
||||
I m_Tail;
|
||||
@ -379,17 +385,10 @@ protected:
|
||||
{
|
||||
m_pElements = m_Memory.Base();
|
||||
}
|
||||
|
||||
private:
|
||||
// Faster version of Next that can only be used from tested code internal
|
||||
// to this class, such as Find(). It avoids the cost of checking the index
|
||||
// validity, which is a big win on debug builds.
|
||||
I PrivateNext( I i ) const;
|
||||
};
|
||||
|
||||
|
||||
// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
|
||||
// MoeMod : CUtlFixedMemory uses intp as index type
|
||||
template < class T >
|
||||
class CUtlFixedLinkedList : public CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > >
|
||||
{
|
||||
@ -397,25 +396,24 @@ public:
|
||||
CUtlFixedLinkedList( int growSize = 0, int initSize = 0 )
|
||||
: CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > >( growSize, initSize ) {}
|
||||
|
||||
typedef CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > > BaseClass;
|
||||
bool IsValidIndex( intp i ) const
|
||||
{
|
||||
if ( !BaseClass::Memory().IsIdxValid( i ) )
|
||||
if ( !this->Memory().IsIdxValid( i ) )
|
||||
return false;
|
||||
|
||||
#ifdef _DEBUG // it's safe to skip this here, since the only way to get indices after m_LastAlloc is to use MaxElementIndex
|
||||
if ( BaseClass::Memory().IsIdxAfter( i, this->m_LastAlloc ) )
|
||||
if ( this->Memory().IsIdxAfter( i, this->m_LastAlloc ) )
|
||||
{
|
||||
Assert( 0 );
|
||||
return false; // don't read values that have been allocated, but not constructed
|
||||
}
|
||||
#endif
|
||||
|
||||
return ( BaseClass::Memory()[ i ].m_Previous != i ) || ( BaseClass::Memory()[ i ].m_Next == i );
|
||||
return ( this->Memory()[ i ].m_Previous != i ) || ( this->Memory()[ i ].m_Next == i );
|
||||
}
|
||||
|
||||
private:
|
||||
intp MaxElementIndex() const { Assert( 0 ); return BaseClass::InvalidIndex(); } // fixedmemory containers don't support iteration from 0..maxelements-1
|
||||
int MaxElementIndex() const { Assert( 0 ); return this->InvalidIndex(); } // fixedmemory containers don't support iteration from 0..maxelements-1
|
||||
void ResetDbgInfo() {}
|
||||
};
|
||||
|
||||
@ -439,8 +437,10 @@ template <class T, class S, bool ML, class I, class M>
|
||||
CUtlLinkedList<T,S,ML,I,M>::CUtlLinkedList( int growSize, int initSize ) :
|
||||
m_Memory( growSize, initSize ), m_LastAlloc( m_Memory.InvalidIterator() )
|
||||
{
|
||||
#if !defined( PLATFORM_WINDOWS_PC64 ) && !defined( PLATFORM_64BITS )
|
||||
// Prevent signed non-int datatypes
|
||||
COMPILE_TIME_ASSERT( sizeof(S) == sizeof(M::InvalidIndex()) || ( ( (S)-1 ) > 0 ) );
|
||||
COMPILE_TIME_ASSERT( sizeof(S) == 4 || ( ( (S)-1 ) > 0 ) );
|
||||
#endif
|
||||
ConstructList();
|
||||
ResetDbgInfo();
|
||||
}
|
||||
@ -540,21 +540,13 @@ inline I CUtlLinkedList<T,S,ML,I,M>::Next( I i ) const
|
||||
return InternalElement(i).m_Next;
|
||||
}
|
||||
|
||||
template <class T, class S, bool ML, class I, class M>
|
||||
inline I CUtlLinkedList<T,S,ML,I,M>::PrivateNext( I i ) const
|
||||
{
|
||||
return InternalElement(i).m_Next;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Are nodes in the list or valid?
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(push)
|
||||
#pragma warning( disable: 4310 ) // Allows "(I)(S)M::INVALID_INDEX" below
|
||||
#endif
|
||||
template <class T, class S, bool ML, class I, class M>
|
||||
inline bool CUtlLinkedList<T,S,ML,I,M>::IndexInRange( I index ) // Static method
|
||||
{
|
||||
@ -565,17 +557,17 @@ inline bool CUtlLinkedList<T,S,ML,I,M>::IndexInRange( I index ) // Static method
|
||||
|
||||
// Do some static checks here:
|
||||
// 'I' needs to be able to store 'S'
|
||||
COMPILE_TIME_ASSERT( sizeof(I) >= sizeof(S) );
|
||||
// These COMPILE_TIME_ASSERT checks need to be in individual scopes to avoid build breaks
|
||||
// on MacOS and Linux due to a gcc bug.
|
||||
{ COMPILE_TIME_ASSERT( sizeof(I) >= sizeof(S) ); }
|
||||
// 'S' should be unsigned (to avoid signed arithmetic errors for plausibly exhaustible ranges)
|
||||
COMPILE_TIME_ASSERT( ( sizeof(S) > 2 ) || ( ( (S)-1 ) > 0 ) );
|
||||
{ COMPILE_TIME_ASSERT( ( sizeof(S) > 2 ) || ( ( (S)-1 ) > 0 ) ); }
|
||||
// M::INVALID_INDEX should be storable in S to avoid ambiguities (e.g. with 65536)
|
||||
COMPILE_TIME_ASSERT( ( M::INVALID_INDEX == -1 ) || ( M::INVALID_INDEX == (S)M::INVALID_INDEX ) );
|
||||
{ COMPILE_TIME_ASSERT( ( M::INVALID_INDEX == -1 ) || ( M::INVALID_INDEX == (S)M::INVALID_INDEX ) ); }
|
||||
|
||||
return ( ( (S)index == index ) && ( (S)index != InvalidIndex() ) );
|
||||
}
|
||||
#ifdef _WIN32
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class T, class S, bool ML, class I, class M>
|
||||
inline bool CUtlLinkedList<T,S,ML,I,M>::IsValidIndex( I i ) const
|
||||
@ -626,6 +618,12 @@ void CUtlLinkedList<T,S,ML,I,M>::SetGrowSize( int growSize )
|
||||
ResetDbgInfo();
|
||||
}
|
||||
|
||||
template< class T, class S, bool ML, class I, class M >
|
||||
void CUtlLinkedList<T,S,ML,I,M>::SetAllocOwner( const char *pszAllocOwner )
|
||||
{
|
||||
m_Memory.SetAllocOwner( pszAllocOwner );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Deallocate memory
|
||||
@ -665,7 +663,7 @@ void CUtlLinkedList<T,S,ML,I,M>::PurgeAndDeleteElements()
|
||||
// Node allocation/deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class S, bool ML, class I, class M>
|
||||
I CUtlLinkedList<T,S,ML,I,M>::AllocInternal( bool multilist )
|
||||
I CUtlLinkedList<T,S,ML,I,M>::AllocInternal( bool multilist ) RESTRICT
|
||||
{
|
||||
Assert( !multilist || ML );
|
||||
#ifdef MULTILIST_PEDANTIC_ASSERTS
|
||||
@ -798,7 +796,7 @@ inline I CUtlLinkedList<T,S,ML,I,M>::AddToHead( )
|
||||
template <class T, class S, bool ML, class I, class M>
|
||||
inline I CUtlLinkedList<T,S,ML,I,M>::AddToTail( )
|
||||
{
|
||||
return InsertBefore( InvalidIndex() );
|
||||
return InsertBefore( InvalidIndex() );
|
||||
}
|
||||
|
||||
|
||||
@ -860,9 +858,7 @@ inline I CUtlLinkedList<T,S,ML,I,M>::AddToTail( T const& src )
|
||||
template<class T, class S, bool ML, class I, class M>
|
||||
I CUtlLinkedList<T,S,ML,I,M>::Find( const T &src ) const
|
||||
{
|
||||
// Cache the invalidIndex to avoid two levels of function calls on each iteration.
|
||||
I invalidIndex = InvalidIndex();
|
||||
for ( I i=Head(); i != invalidIndex; i = PrivateNext( i ) )
|
||||
for ( I i=Head(); i != InvalidIndex(); i = Next( i ) )
|
||||
{
|
||||
if ( Element( i ) == src )
|
||||
return i;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
@ -17,22 +17,21 @@
|
||||
#include "tier0/dbg.h"
|
||||
#include <string.h>
|
||||
#include "tier0/platform.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
#include "tier0/memalloc.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning (disable:4100)
|
||||
#pragma warning (disable:4514)
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifdef UTLMEMORY_TRACK
|
||||
#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlMemory", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
|
||||
#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlMemory", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
|
||||
#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "||Sum of all UtlMemory||", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
|
||||
#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "||Sum of all UtlMemory||", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
|
||||
#else
|
||||
#define UTLMEMORY_TRACK_ALLOC() ((void)0)
|
||||
#define UTLMEMORY_TRACK_FREE() ((void)0)
|
||||
@ -46,6 +45,8 @@
|
||||
template< class T, class I = int >
|
||||
class CUtlMemory
|
||||
{
|
||||
template< class A, class B> friend class CUtlVector;
|
||||
template< class A, size_t B> friend class CUtlVectorFixedGrowableCompat;
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlMemory( int nGrowSize = 0, int nInitSize = 0 );
|
||||
@ -53,6 +54,12 @@ public:
|
||||
CUtlMemory( const T* pMemory, int numElements );
|
||||
~CUtlMemory();
|
||||
|
||||
CUtlMemory( const CUtlMemory& ) = delete;
|
||||
CUtlMemory& operator=( const CUtlMemory& ) = delete;
|
||||
|
||||
CUtlMemory( CUtlMemory&& moveFrom );
|
||||
CUtlMemory& operator=( CUtlMemory&& moveFrom );
|
||||
|
||||
// Set the size by which the memory grows
|
||||
void Init( int nGrowSize = 0, int nInitSize = 0 );
|
||||
|
||||
@ -92,8 +99,9 @@ public:
|
||||
// Attaches the buffer to external memory....
|
||||
void SetExternalBuffer( T* pMemory, int numElements );
|
||||
void SetExternalBuffer( const T* pMemory, int numElements );
|
||||
// Takes ownership of the passed memory, including freeing it when this buffer is destroyed.
|
||||
void AssumeMemory( T *pMemory, int nSize );
|
||||
T* Detach();
|
||||
void *DetachMemory();
|
||||
|
||||
// Fast swap
|
||||
void Swap( CUtlMemory< T, I > &mem );
|
||||
@ -212,8 +220,7 @@ public:
|
||||
CUtlMemoryFixed( T* pMemory, int numElements ) { Assert( 0 ); }
|
||||
|
||||
// Can we use this index?
|
||||
// Use unsigned math to improve performance
|
||||
bool IsIdxValid( int i ) const { return (size_t)i < SIZE; }
|
||||
bool IsIdxValid( int i ) const { return (i >= 0) && (i < SIZE); }
|
||||
|
||||
// Specify the invalid ('null') index that we'll only return on failure
|
||||
static const int INVALID_INDEX = -1; // For use with COMPILE_TIME_ASSERT
|
||||
@ -224,11 +231,10 @@ public:
|
||||
const T* Base() const { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); }
|
||||
|
||||
// element access
|
||||
// Use unsigned math and inlined checks to improve performance.
|
||||
T& operator[]( int i ) { Assert( (size_t)i < SIZE ); return Base()[i]; }
|
||||
const T& operator[]( int i ) const { Assert( (size_t)i < SIZE ); return Base()[i]; }
|
||||
T& Element( int i ) { Assert( (size_t)i < SIZE ); return Base()[i]; }
|
||||
const T& Element( int i ) const { Assert( (size_t)i < SIZE ); return Base()[i]; }
|
||||
T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
const T& Element( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
|
||||
// Attaches the buffer to external memory....
|
||||
void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
|
||||
@ -274,12 +280,7 @@ private:
|
||||
char m_Memory[ SIZE*sizeof(T) + nAlignment ];
|
||||
};
|
||||
|
||||
#if defined(POSIX)
|
||||
// From Chris Green: Memory is a little fuzzy but I believe this class did
|
||||
// something fishy with respect to msize and alignment that was OK under our
|
||||
// allocator, the glibc allocator, etc but not the valgrind one (which has no
|
||||
// padding because it detects all forms of head/tail overwrite, including
|
||||
// writing 1 byte past a 1 byte allocation).
|
||||
#ifdef _LINUX
|
||||
#define REMEMBER_ALLOC_SIZE_FOR_VALGRIND 1
|
||||
#endif
|
||||
|
||||
@ -445,6 +446,44 @@ template< class T, class I >
|
||||
CUtlMemory<T,I>::~CUtlMemory()
|
||||
{
|
||||
Purge();
|
||||
|
||||
#ifdef _DEBUG
|
||||
m_pMemory = reinterpret_cast< T* >( 0xFEFEBAAD );
|
||||
m_nAllocationCount = 0x7BADF00D;
|
||||
#endif
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
CUtlMemory<T,I>::CUtlMemory( CUtlMemory&& moveFrom )
|
||||
: m_pMemory(moveFrom.m_pMemory)
|
||||
, m_nAllocationCount(moveFrom.m_nAllocationCount)
|
||||
, m_nGrowSize(moveFrom.m_nGrowSize)
|
||||
{
|
||||
moveFrom.m_pMemory = nullptr;
|
||||
moveFrom.m_nAllocationCount = 0;
|
||||
moveFrom.m_nGrowSize = 0;
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
CUtlMemory<T,I>& CUtlMemory<T,I>::operator=( CUtlMemory&& moveFrom )
|
||||
{
|
||||
// Copy member variables to locals before purge to handle self-assignment
|
||||
T* pMemory = moveFrom.m_pMemory;
|
||||
int nAllocationCount = moveFrom.m_nAllocationCount;
|
||||
int nGrowSize = moveFrom.m_nGrowSize;
|
||||
|
||||
moveFrom.m_pMemory = nullptr;
|
||||
moveFrom.m_nAllocationCount = 0;
|
||||
moveFrom.m_nGrowSize = 0;
|
||||
|
||||
// If this is a self-assignment, Purge() is a no-op here
|
||||
Purge();
|
||||
|
||||
m_pMemory = pMemory;
|
||||
m_nAllocationCount = nAllocationCount;
|
||||
m_nGrowSize = nGrowSize;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
@ -493,7 +532,7 @@ void CUtlMemory<T,I>::ConvertToGrowableMemory( int nGrowSize )
|
||||
|
||||
int nNumBytes = m_nAllocationCount * sizeof(T);
|
||||
T *pMemory = (T*)malloc( nNumBytes );
|
||||
memcpy( (void*)pMemory, (void*)m_pMemory, nNumBytes );
|
||||
memcpy( pMemory, m_pMemory, nNumBytes );
|
||||
m_pMemory = pMemory;
|
||||
}
|
||||
else
|
||||
@ -543,6 +582,24 @@ void CUtlMemory<T,I>::AssumeMemory( T* pMemory, int numElements )
|
||||
m_nAllocationCount = numElements;
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
void *CUtlMemory<T,I>::DetachMemory()
|
||||
{
|
||||
if ( IsExternallyAllocated() )
|
||||
return NULL;
|
||||
|
||||
void *pMemory = m_pMemory;
|
||||
m_pMemory = 0;
|
||||
m_nAllocationCount = 0;
|
||||
return pMemory;
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline T* CUtlMemory<T,I>::Detach()
|
||||
{
|
||||
return (T*)DetachMemory();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element access
|
||||
@ -550,35 +607,31 @@ void CUtlMemory<T,I>::AssumeMemory( T* pMemory, int numElements )
|
||||
template< class T, class I >
|
||||
inline T& CUtlMemory<T,I>::operator[]( I i )
|
||||
{
|
||||
// Avoid function calls in the asserts to improve debug build performance
|
||||
Assert( m_nGrowSize != EXTERNAL_CONST_BUFFER_MARKER ); //Assert( !IsReadOnly() );
|
||||
Assert( (uint32)i < (uint32)m_nAllocationCount );
|
||||
return m_pMemory[(uint32)i];
|
||||
Assert( !IsReadOnly() );
|
||||
Assert( IsIdxValid(i) );
|
||||
return m_pMemory[i];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline const T& CUtlMemory<T,I>::operator[]( I i ) const
|
||||
{
|
||||
// Avoid function calls in the asserts to improve debug build performance
|
||||
Assert( (uint32)i < (uint32)m_nAllocationCount );
|
||||
return m_pMemory[(uint32)i];
|
||||
Assert( IsIdxValid(i) );
|
||||
return m_pMemory[i];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline T& CUtlMemory<T,I>::Element( I i )
|
||||
{
|
||||
// Avoid function calls in the asserts to improve debug build performance
|
||||
Assert( m_nGrowSize != EXTERNAL_CONST_BUFFER_MARKER ); //Assert( !IsReadOnly() );
|
||||
Assert( (uint32)i < (uint32)m_nAllocationCount );
|
||||
return m_pMemory[(uint32)i];
|
||||
Assert( !IsReadOnly() );
|
||||
Assert( IsIdxValid(i) );
|
||||
return m_pMemory[i];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline const T& CUtlMemory<T,I>::Element( I i ) const
|
||||
{
|
||||
// Avoid function calls in the asserts to improve debug build performance
|
||||
Assert( (uint32)i < (uint32)m_nAllocationCount );
|
||||
return m_pMemory[(uint32)i];
|
||||
Assert( IsIdxValid(i) );
|
||||
return m_pMemory[i];
|
||||
}
|
||||
|
||||
|
||||
@ -651,10 +704,10 @@ inline int CUtlMemory<T,I>::Count() const
|
||||
template< class T, class I >
|
||||
inline bool CUtlMemory<T,I>::IsIdxValid( I i ) const
|
||||
{
|
||||
// If we always cast 'i' and 'm_nAllocationCount' to unsigned then we can
|
||||
// do our range checking with a single comparison instead of two. This gives
|
||||
// a modest speedup in debug builds.
|
||||
return (uint32)i < (uint32)m_nAllocationCount;
|
||||
// GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0).
|
||||
// We get the warning even if we cast inside the expression. It only goes away if we assign to another variable.
|
||||
long x = i;
|
||||
return ( x >= 0 ) && ( x < m_nAllocationCount );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -672,6 +725,11 @@ inline int UtlMemory_CalcNewAllocationCount( int nAllocationCount, int nGrowSize
|
||||
{
|
||||
// Compute an allocation which is at least as big as a cache line...
|
||||
nAllocationCount = (31 + nBytesItem) / nBytesItem;
|
||||
// If the requested amount is larger then compute an allocation which
|
||||
// is exactly the right size. Otherwise we can end up with wasted memory
|
||||
// when CUtlVector::EnsureCount(n) is called.
|
||||
if ( nAllocationCount < nNewSize )
|
||||
nAllocationCount = nNewSize;
|
||||
}
|
||||
|
||||
while (nAllocationCount < nNewSize)
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose: Defines a symbol table
|
||||
//
|
||||
@ -13,9 +13,13 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#include "tier0/threadtools.h"
|
||||
#include "tier1/utlrbtree.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "tier1/utllinkedlist.h"
|
||||
#include "tier1/stringpool.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -24,6 +28,7 @@
|
||||
class CUtlSymbolTable;
|
||||
class CUtlSymbolTableMT;
|
||||
|
||||
#define FILENAMEHANDLE_INVALID 0
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This is a symbol, which is a easier way of dealing with strings.
|
||||
@ -52,14 +57,19 @@ public:
|
||||
bool IsValid() const { return m_Id != UTL_INVAL_SYMBOL; }
|
||||
|
||||
// Gets at the symbol
|
||||
operator UtlSymId_t const() const { return m_Id; }
|
||||
operator UtlSymId_t () const { return m_Id; }
|
||||
|
||||
// Gets the string associated with the symbol
|
||||
const char* String( ) const;
|
||||
|
||||
// Modules can choose to disable the static symbol table so to prevent accidental use of them.
|
||||
static void DisableStaticSymbolTable();
|
||||
|
||||
|
||||
// Methods with explicit locking mechanism. Only use for optimization reasons.
|
||||
static void LockTableForRead();
|
||||
static void UnlockTableForRead();
|
||||
const char * StringNoLock() const;
|
||||
|
||||
protected:
|
||||
UtlSymId_t m_Id;
|
||||
|
||||
@ -85,13 +95,17 @@ protected:
|
||||
// of strings to symbols and back. The symbol class itself contains
|
||||
// a static version of this class for creating global strings, but this
|
||||
// class can also be instanced to create local symbol tables.
|
||||
//
|
||||
// This class stores the strings in a series of string pools. The first
|
||||
// two bytes of each string are decorated with a hash to speed up
|
||||
// comparisons.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CUtlSymbolTable
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlSymbolTable( int growSize = 0, int initSize = 32, bool caseInsensitive = false );
|
||||
CUtlSymbolTable( int growSize = 0, int initSize = 16, bool caseInsensitive = false );
|
||||
~CUtlSymbolTable();
|
||||
|
||||
// Finds and/or creates a symbol based on the string
|
||||
@ -102,6 +116,11 @@ public:
|
||||
|
||||
// Look up the string associated with a particular symbol
|
||||
const char* String( CUtlSymbol id ) const;
|
||||
|
||||
inline bool HasElement(const char* pStr) const
|
||||
{
|
||||
return Find(pStr) != UTL_INVAL_SYMBOL;
|
||||
}
|
||||
|
||||
// Remove all symbols in the table.
|
||||
void RemoveAll();
|
||||
@ -111,6 +130,10 @@ public:
|
||||
return m_Lookup.Count();
|
||||
}
|
||||
|
||||
// We store one of these at the beginning of every string to speed
|
||||
// up comparisons.
|
||||
typedef unsigned short hashDecoration_t;
|
||||
|
||||
protected:
|
||||
class CStringPoolIndex
|
||||
{
|
||||
@ -120,10 +143,8 @@ protected:
|
||||
}
|
||||
|
||||
inline CStringPoolIndex( unsigned short iPool, unsigned short iOffset )
|
||||
{
|
||||
m_iPool = iPool;
|
||||
m_iOffset = iOffset;
|
||||
}
|
||||
: m_iPool(iPool), m_iOffset(iOffset)
|
||||
{}
|
||||
|
||||
inline bool operator==( const CStringPoolIndex &other ) const
|
||||
{
|
||||
@ -158,7 +179,9 @@ protected:
|
||||
};
|
||||
|
||||
CTree m_Lookup;
|
||||
|
||||
bool m_bInsensitive;
|
||||
mutable unsigned short m_nUserSearchStringHash;
|
||||
mutable const char* m_pUserSearchString;
|
||||
|
||||
// stores the string data
|
||||
@ -167,11 +190,14 @@ protected:
|
||||
private:
|
||||
int FindPoolWithSpace( int len ) const;
|
||||
const char* StringFromIndex( const CStringPoolIndex &index ) const;
|
||||
const char* DecoratedStringFromIndex( const CStringPoolIndex &index ) const;
|
||||
|
||||
friend class CLess;
|
||||
friend class CSymbolHash;
|
||||
|
||||
};
|
||||
|
||||
class CUtlSymbolTableMT : private CUtlSymbolTable
|
||||
class CUtlSymbolTableMT : public CUtlSymbolTable
|
||||
{
|
||||
public:
|
||||
CUtlSymbolTableMT( int growSize = 0, int initSize = 32, bool caseInsensitive = false )
|
||||
@ -189,9 +215,9 @@ public:
|
||||
|
||||
CUtlSymbol Find( const char* pString ) const
|
||||
{
|
||||
m_lock.LockForRead();
|
||||
m_lock.LockForWrite();
|
||||
CUtlSymbol result = CUtlSymbolTable::Find( pString );
|
||||
m_lock.UnlockRead();
|
||||
m_lock.UnlockWrite();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -202,9 +228,24 @@ public:
|
||||
m_lock.UnlockRead();
|
||||
return pszResult;
|
||||
}
|
||||
|
||||
|
||||
const char * StringNoLock( CUtlSymbol id ) const
|
||||
{
|
||||
return CUtlSymbolTable::String( id );
|
||||
}
|
||||
|
||||
void LockForRead()
|
||||
{
|
||||
m_lock.LockForRead();
|
||||
}
|
||||
|
||||
void UnlockForRead()
|
||||
{
|
||||
m_lock.UnlockRead();
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#ifdef WIN32
|
||||
mutable CThreadSpinRWLock m_lock;
|
||||
#else
|
||||
mutable CThreadRWLock m_lock;
|
||||
@ -225,7 +266,6 @@ private:
|
||||
// The handle is a CUtlSymbol for the dirname and the same for the filename, the accessor
|
||||
// copies them into a static char buffer for return.
|
||||
typedef void* FileNameHandle_t;
|
||||
#define FILENAMEHANDLE_INVALID 0
|
||||
|
||||
// Symbol table for more efficiently storing filenames by breaking paths and filenames apart.
|
||||
// Refactored from BaseFileSystem.h
|
||||
@ -238,32 +278,104 @@ class CUtlFilenameSymbolTable
|
||||
{
|
||||
FileNameHandleInternal_t()
|
||||
{
|
||||
path = 0;
|
||||
file = 0;
|
||||
COMPILE_TIME_ASSERT( sizeof( *this ) == sizeof( FileNameHandle_t ) );
|
||||
COMPILE_TIME_ASSERT( sizeof( value ) == 4 );
|
||||
value = 0;
|
||||
|
||||
#ifdef PLATFORM_64BITS
|
||||
pad = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// We pack the path and file values into a single 32 bit value. We were running
|
||||
// out of space with the two 16 bit values (more than 64k files) so instead of increasing
|
||||
// the total size we split the underlying pool into two (paths and files) and
|
||||
// use a smaller path string pool and a larger file string pool.
|
||||
unsigned int value;
|
||||
|
||||
#ifdef PLATFORM_64BITS
|
||||
// some padding to make sure we are the same size as FileNameHandle_t on 64 bit.
|
||||
unsigned int pad;
|
||||
#endif
|
||||
|
||||
static const unsigned int cNumBitsInPath = 12;
|
||||
static const unsigned int cNumBitsInFile = 32 - cNumBitsInPath;
|
||||
|
||||
static const unsigned int cMaxPathValue = 1 << cNumBitsInPath;
|
||||
static const unsigned int cMaxFileValue = 1 << cNumBitsInFile;
|
||||
|
||||
static const unsigned int cPathBitMask = cMaxPathValue - 1;
|
||||
static const unsigned int cFileBitMask = cMaxFileValue - 1;
|
||||
|
||||
// Part before the final '/' character
|
||||
unsigned short path;
|
||||
unsigned int GetPath() const { return ((value >> cNumBitsInFile) & cPathBitMask); }
|
||||
void SetPath( unsigned int path ) { Assert( path < cMaxPathValue ); value = ((value & cFileBitMask) | ((path & cPathBitMask) << cNumBitsInFile)); }
|
||||
|
||||
// Part after the final '/', including extension
|
||||
unsigned short file;
|
||||
unsigned int GetFile() const { return (value & cFileBitMask); }
|
||||
void SetFile( unsigned int file ) { Assert( file < cMaxFileValue ); value = ((value & (cPathBitMask << cNumBitsInFile)) | (file & cFileBitMask)); }
|
||||
};
|
||||
|
||||
class HashTable;
|
||||
|
||||
public:
|
||||
CUtlFilenameSymbolTable();
|
||||
~CUtlFilenameSymbolTable();
|
||||
FileNameHandle_t FindOrAddFileName( const char *pFileName );
|
||||
FileNameHandle_t FindFileName( const char *pFileName );
|
||||
int PathIndex(const FileNameHandle_t &handle) { return (( const FileNameHandleInternal_t * )&handle)->path; }
|
||||
int PathIndex( const FileNameHandle_t &handle ) { return (( const FileNameHandleInternal_t * )&handle)->GetPath(); }
|
||||
bool String( const FileNameHandle_t& handle, char *buf, int buflen );
|
||||
void RemoveAll();
|
||||
void SpewStrings();
|
||||
bool SaveToBuffer( CUtlBuffer &buffer );
|
||||
bool RestoreFromBuffer( CUtlBuffer &buffer );
|
||||
|
||||
private:
|
||||
//CCountedStringPool m_StringPool;
|
||||
HashTable* m_Strings;
|
||||
CCountedStringPoolBase<unsigned short> m_PathStringPool;
|
||||
CCountedStringPoolBase<unsigned int> m_FileStringPool;
|
||||
mutable CThreadSpinRWLock m_lock;
|
||||
};
|
||||
|
||||
// This creates a simple class that includes the underlying CUtlSymbol
|
||||
// as a private member and then instances a private symbol table to
|
||||
// manage those symbols. Avoids the possibility of the code polluting the
|
||||
// 'global'/default symbol table, while letting the code look like
|
||||
// it's just using = and .String() to look at CUtlSymbol type objects
|
||||
//
|
||||
// NOTE: You can't pass these objects between .dlls in an interface (also true of CUtlSymbol of course)
|
||||
//
|
||||
#define DECLARE_PRIVATE_SYMBOLTYPE( typename ) \
|
||||
class typename \
|
||||
{ \
|
||||
public: \
|
||||
typename(); \
|
||||
typename( const char* pStr ); \
|
||||
typename& operator=( typename const& src ); \
|
||||
bool operator==( typename const& src ) const; \
|
||||
const char* String( ) const; \
|
||||
private: \
|
||||
CUtlSymbol m_SymbolId; \
|
||||
};
|
||||
|
||||
// Put this in the .cpp file that uses the above typename
|
||||
#define IMPLEMENT_PRIVATE_SYMBOLTYPE( typename ) \
|
||||
static CUtlSymbolTable g_##typename##SymbolTable; \
|
||||
typename::typename() \
|
||||
{ \
|
||||
m_SymbolId = UTL_INVAL_SYMBOL; \
|
||||
} \
|
||||
typename::typename( const char* pStr ) \
|
||||
{ \
|
||||
m_SymbolId = g_##typename##SymbolTable.AddString( pStr ); \
|
||||
} \
|
||||
typename& typename::operator=( typename const& src ) \
|
||||
{ \
|
||||
m_SymbolId = src.m_SymbolId; \
|
||||
return *this; \
|
||||
} \
|
||||
bool typename::operator==( typename const& src ) const \
|
||||
{ \
|
||||
return ( m_SymbolId == src.m_SymbolId ); \
|
||||
} \
|
||||
const char* typename::String( ) const \
|
||||
{ \
|
||||
return g_##typename##SymbolTable.String( m_SymbolId ); \
|
||||
}
|
||||
|
||||
#endif // UTLSYMBOL_H
|
||||
|
@ -94,7 +94,6 @@ public:
|
||||
virtual const char *GetResourceName(void) { return m_pResourceName; }
|
||||
|
||||
virtual void PanelAdded(Panel* panel);
|
||||
virtual void PanelRemoved(Panel* panel);
|
||||
|
||||
virtual bool MousePressed(MouseCode code,Panel* panel);
|
||||
virtual bool MouseReleased(MouseCode code,Panel* panel);
|
||||
|
@ -191,7 +191,7 @@ public:
|
||||
// and execute or execute pFunctor right after completing current job and
|
||||
// before looking for another job.
|
||||
//-----------------------------------------------------
|
||||
virtual void ExecuteHighPriorityFunctor( CFunctor *pFunctor ) = 0;
|
||||
// virtual void ExecuteHighPriorityFunctor( CFunctor *pFunctor ) = 0;
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Add an function object to the queue (master thread)
|
||||
|
@ -115,7 +115,7 @@ StudioDecalHandle_t CStudioRender::CreateDecalList( studiohwdata_t *pHardwareDat
|
||||
|
||||
// NOTE: This function is called directly without queueing
|
||||
m_DecalMutex.Lock();
|
||||
int handle = m_DecalList.AddToTail();
|
||||
intp handle = m_DecalList.AddToTail();
|
||||
m_DecalMutex.Unlock();
|
||||
|
||||
m_DecalList[handle].m_pHardwareData = pHardwareData;
|
||||
|
@ -20,11 +20,23 @@
|
||||
|
||||
const tchar* GetProcessorVendorId();
|
||||
|
||||
static bool cpuid(unsigned long function, unsigned long& out_eax, unsigned long& out_ebx, unsigned long& out_ecx, unsigned long& out_edx)
|
||||
static bool cpuid(uint32 function, uint32& out_eax, uint32& out_ebx, uint32& out_ecx, uint32& out_edx)
|
||||
{
|
||||
#if defined (__arm__) || defined (__arm64__) || defined( _X360 )
|
||||
return false;
|
||||
#elif defined(GNUC)
|
||||
|
||||
#if defined(PLATFORM_64BITS)
|
||||
asm("mov %%rbx, %%rsi\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchg %%rsi, %%rbx"
|
||||
: "=a" (out_eax),
|
||||
"=S" (out_ebx),
|
||||
"=c" (out_ecx),
|
||||
"=d" (out_edx)
|
||||
: "a" (function)
|
||||
);
|
||||
#else
|
||||
asm("mov %%ebx, %%esi\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchg %%esi, %%ebx"
|
||||
@ -34,7 +46,9 @@ static bool cpuid(unsigned long function, unsigned long& out_eax, unsigned long&
|
||||
"=d" (out_edx)
|
||||
: "a" (function)
|
||||
);
|
||||
#endif
|
||||
return true;
|
||||
|
||||
#elif defined(_WIN64)
|
||||
int pCPUInfo[4];
|
||||
__cpuid( pCPUInfo, (int)function );
|
||||
@ -45,7 +59,7 @@ static bool cpuid(unsigned long function, unsigned long& out_eax, unsigned long&
|
||||
return true;
|
||||
#else
|
||||
bool retval = true;
|
||||
unsigned long local_eax, local_ebx, local_ecx, local_edx;
|
||||
uint32 local_eax, local_ebx, local_ecx, local_edx;
|
||||
_asm pushad;
|
||||
|
||||
__try
|
||||
@ -83,7 +97,7 @@ static bool CheckMMXTechnology(void)
|
||||
#if defined( _X360 ) || defined( _PS3 )
|
||||
return true;
|
||||
#else
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
uint32 eax,ebx,edx,unused;
|
||||
if ( !cpuid(1,eax,ebx,unused,edx) )
|
||||
return false;
|
||||
|
||||
@ -151,7 +165,7 @@ static bool CheckSSETechnology(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
uint32 eax,ebx,edx,unused;
|
||||
if ( !cpuid(1,eax,ebx,unused,edx) ) {
|
||||
return false;
|
||||
}
|
||||
@ -165,7 +179,7 @@ static bool CheckSSE2Technology(void)
|
||||
#if defined( _X360 ) || defined( _PS3 ) || defined(__SANITIZE_ADDRESS__) || defined (__arm__)
|
||||
return false;
|
||||
#else
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
uint32 eax,ebx,edx,unused;
|
||||
if ( !cpuid(1,eax,ebx,unused,edx) )
|
||||
return false;
|
||||
|
||||
@ -178,7 +192,7 @@ bool CheckSSE3Technology(void)
|
||||
#if defined( _X360 ) || defined( _PS3 ) || defined(__SANITIZE_ADDRESS__) || defined (__arm__)
|
||||
return false;
|
||||
#else
|
||||
unsigned long eax,ebx,edx,ecx;
|
||||
uint32 eax,ebx,edx,ecx;
|
||||
if( !cpuid(1,eax,ebx,ecx,edx) )
|
||||
return false;
|
||||
|
||||
@ -193,7 +207,7 @@ bool CheckSSSE3Technology(void)
|
||||
#else
|
||||
// SSSE 3 is implemented by both Intel and AMD
|
||||
// detection is done the same way for both vendors
|
||||
unsigned long eax,ebx,edx,ecx;
|
||||
uint32 eax,ebx,edx,ecx;
|
||||
if( !cpuid(1,eax,ebx,ecx,edx) )
|
||||
return false;
|
||||
|
||||
@ -209,7 +223,7 @@ bool CheckSSE41Technology(void)
|
||||
// SSE 4.1 is implemented by both Intel and AMD
|
||||
// detection is done the same way for both vendors
|
||||
|
||||
unsigned long eax,ebx,edx,ecx;
|
||||
uint32 eax,ebx,edx,ecx;
|
||||
if( !cpuid(1,eax,ebx,ecx,edx) )
|
||||
return false;
|
||||
|
||||
@ -228,7 +242,7 @@ bool CheckSSE42Technology(void)
|
||||
if ( 0 != V_tier0_stricmp( pchVendor, "GenuineIntel" ) )
|
||||
return false;
|
||||
|
||||
unsigned long eax,ebx,edx,ecx;
|
||||
uint32 eax,ebx,edx,ecx;
|
||||
if( !cpuid(1,eax,ebx,ecx,edx) )
|
||||
return false;
|
||||
|
||||
@ -248,7 +262,7 @@ bool CheckSSE4aTechnology( void )
|
||||
if ( 0 != V_tier0_stricmp( pchVendor, "AuthenticAMD" ) )
|
||||
return false;
|
||||
|
||||
unsigned long eax,ebx,edx,ecx;
|
||||
uint32 eax,ebx,edx,ecx;
|
||||
if( !cpuid( 0x80000001,eax,ebx,ecx,edx) )
|
||||
return false;
|
||||
|
||||
@ -262,7 +276,7 @@ static bool Check3DNowTechnology(void)
|
||||
#if defined( _X360 ) || defined( _PS3 ) || defined (__arm__) || defined(__SANITIZE_ADDRESS__)
|
||||
return false;
|
||||
#else
|
||||
unsigned long eax, unused;
|
||||
uint32 eax, unused;
|
||||
if ( !cpuid(0x80000000,eax,unused,unused,unused) )
|
||||
return false;
|
||||
|
||||
@ -282,7 +296,7 @@ static bool CheckCMOVTechnology()
|
||||
#if defined( _X360 ) || defined( _PS3 ) || defined (__arm__) || defined(__SANITIZE_ADDRESS__)
|
||||
return false;
|
||||
#else
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
uint32 eax,ebx,edx,unused;
|
||||
if ( !cpuid(1,eax,ebx,unused,edx) )
|
||||
return false;
|
||||
|
||||
@ -295,7 +309,7 @@ static bool CheckFCMOVTechnology(void)
|
||||
#if defined( _X360 ) || defined( _PS3 ) || defined (__arm__) || defined(__SANITIZE_ADDRESS__)
|
||||
return false;
|
||||
#else
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
uint32 eax,ebx,edx,unused;
|
||||
if ( !cpuid(1,eax,ebx,unused,edx) )
|
||||
return false;
|
||||
|
||||
@ -308,7 +322,7 @@ static bool CheckRDTSCTechnology(void)
|
||||
#if defined( _X360 ) || defined( _PS3 ) || defined (__arm__) || defined(__SANITIZE_ADDRESS__)
|
||||
return false;
|
||||
#else
|
||||
unsigned long eax,ebx,edx,unused;
|
||||
uint32 eax,ebx,edx,unused;
|
||||
if ( !cpuid(1,eax,ebx,unused,edx) )
|
||||
return false;
|
||||
|
||||
@ -324,7 +338,7 @@ const tchar* GetProcessorVendorId()
|
||||
#elif defined ( __arm__ )
|
||||
return "ARM";
|
||||
#else
|
||||
unsigned long unused, VendorIDRegisters[3];
|
||||
uint32 unused, VendorIDRegisters[3];
|
||||
|
||||
static tchar VendorID[13];
|
||||
|
||||
@ -365,7 +379,7 @@ static bool HTSupported(void)
|
||||
const unsigned int EXT_FAMILY_ID = 0x0f00000; // EAX[23:20] - Bit 23 thru 20 contains extended family processor id
|
||||
const unsigned int PENTIUM4_ID = 0x0f00; // Pentium 4 family processor id
|
||||
|
||||
unsigned long unused,
|
||||
uint32 unused,
|
||||
reg_eax = 0,
|
||||
reg_edx = 0,
|
||||
vendor_id[3] = {0, 0, 0};
|
||||
@ -393,7 +407,7 @@ static uint8 LogicalProcessorsPerPackage(void)
|
||||
// EBX[23:16] indicate number of logical processors per package
|
||||
const unsigned NUM_LOGICAL_BITS = 0x00FF0000;
|
||||
|
||||
unsigned long unused, reg_ebx = 0;
|
||||
uint32 unused, reg_ebx = 0;
|
||||
|
||||
if ( !HTSupported() )
|
||||
return 1;
|
||||
@ -582,7 +596,7 @@ const CPUInformation* GetCPUInformation()
|
||||
pi.m_szProcessorID = (tchar*)GetProcessorVendorId();
|
||||
pi.m_bHT = HTSupported();
|
||||
|
||||
unsigned long eax, ebx, edx, ecx;
|
||||
uint32 eax, ebx, edx, ecx;
|
||||
if (cpuid(1, eax, ebx, ecx, edx))
|
||||
{
|
||||
pi.m_nModel = eax; // full CPU model info
|
||||
|
@ -49,7 +49,6 @@
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// internal structures
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -152,7 +151,7 @@ struct SpewInfo_t
|
||||
int m_nSpewOutputLevel;
|
||||
};
|
||||
|
||||
CThreadLocalPtr<SpewInfo_t> g_pSpewInfo;
|
||||
CTHREADLOCALPTR(SpewInfo_t) g_pSpewInfo;
|
||||
|
||||
|
||||
// Standard groups
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1425,7 +1425,7 @@ const char *KeyValues::GetString( const char *keyName, const char *defaultValue
|
||||
SetString( keyName, buf );
|
||||
break;
|
||||
case TYPE_PTR:
|
||||
Q_snprintf( buf, sizeof( buf ), "%lld", (int64)(size_t)dat->m_pValue );
|
||||
Q_snprintf( buf, sizeof( buf ), "%lld", (int64)dat->m_pValue );
|
||||
SetString( keyName, buf );
|
||||
break;
|
||||
case TYPE_INT:
|
||||
@ -1478,7 +1478,7 @@ const wchar_t *KeyValues::GetWString( const char *keyName, const wchar_t *defaul
|
||||
SetWString( keyName, wbuf);
|
||||
break;
|
||||
case TYPE_PTR:
|
||||
swprintf( wbuf, Q_ARRAYSIZE(wbuf), L"%lld", (int64)(size_t)dat->m_pValue );
|
||||
swprintf( wbuf, Q_ARRAYSIZE(wbuf), L"%lld", (int64)dat->m_pValue );
|
||||
SetWString( keyName, wbuf );
|
||||
break;
|
||||
case TYPE_INT:
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
@ -18,16 +18,21 @@
|
||||
// Purpose: Comparison function for string sorted associative data structures
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool StrLess( const char * const &pszLeft, const char * const &pszRight )
|
||||
bool StrLessInsensitive( const char * const &pszLeft, const char * const &pszRight )
|
||||
{
|
||||
return ( Q_stricmp( pszLeft, pszRight) < 0 );
|
||||
}
|
||||
|
||||
bool StrLessSensitive( const char * const &pszLeft, const char * const &pszRight )
|
||||
{
|
||||
return ( Q_strcmp( pszLeft, pszRight) < 0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CStringPool::CStringPool()
|
||||
: m_Strings( 32, 256, StrLess )
|
||||
CStringPool::CStringPool( StringPoolCase_t caseSensitivity )
|
||||
: m_Strings( 32, 256, caseSensitivity == StringPoolCaseInsensitive ? StrLessInsensitive : StrLessSensitive )
|
||||
{
|
||||
}
|
||||
|
||||
@ -69,9 +74,7 @@ const char * CStringPool::Allocate( const char *pszValue )
|
||||
return m_Strings[i];
|
||||
|
||||
pszNew = strdup( pszValue );
|
||||
|
||||
if ( bNew )
|
||||
m_Strings.Insert( pszNew );
|
||||
m_Strings.Insert( pszNew );
|
||||
|
||||
return pszNew;
|
||||
}
|
||||
@ -94,217 +97,6 @@ void CStringPool::FreeAll()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
CCountedStringPool::CCountedStringPool()
|
||||
{
|
||||
MEM_ALLOC_CREDIT();
|
||||
m_HashTable.EnsureCount(HASH_TABLE_SIZE);
|
||||
|
||||
for( int i = 0; i < m_HashTable.Count(); i++ )
|
||||
{
|
||||
m_HashTable[i] = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
m_FreeListStart = INVALID_ELEMENT;
|
||||
m_Elements.AddToTail();
|
||||
m_Elements[0].pString = NULL;
|
||||
m_Elements[0].nReferenceCount = 0;
|
||||
m_Elements[0].nNextElement = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
CCountedStringPool::~CCountedStringPool()
|
||||
{
|
||||
FreeAll();
|
||||
}
|
||||
|
||||
void CCountedStringPool::FreeAll()
|
||||
{
|
||||
int i;
|
||||
|
||||
// Reset the hash table:
|
||||
for( i = 0; i < m_HashTable.Count(); i++ )
|
||||
{
|
||||
m_HashTable[i] = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
// Blow away the free list:
|
||||
m_FreeListStart = INVALID_ELEMENT;
|
||||
|
||||
for( i = 0; i < m_Elements.Count(); i++ )
|
||||
{
|
||||
if( m_Elements[i].pString )
|
||||
{
|
||||
delete [] m_Elements[i].pString;
|
||||
m_Elements[i].pString = NULL;
|
||||
m_Elements[i].nReferenceCount = 0;
|
||||
m_Elements[i].nNextElement = INVALID_ELEMENT;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all but the invalid element:
|
||||
m_Elements.RemoveAll();
|
||||
m_Elements.AddToTail();
|
||||
m_Elements[0].pString = NULL;
|
||||
m_Elements[0].nReferenceCount = 0;
|
||||
m_Elements[0].nNextElement = INVALID_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
unsigned short CCountedStringPool::FindStringHandle( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return INVALID_ELEMENT;
|
||||
|
||||
unsigned short nHashBucketIndex = (HashStringCaseless(pIntrinsic ) %HASH_TABLE_SIZE);
|
||||
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// Does the bucket already exist?
|
||||
if( nCurrentBucket != INVALID_ELEMENT )
|
||||
{
|
||||
for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
return nCurrentBucket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
char* CCountedStringPool::FindString( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return NULL;
|
||||
|
||||
// Yes, this will be NULL on failure.
|
||||
return m_Elements[FindStringHandle(pIntrinsic)].pString;
|
||||
}
|
||||
|
||||
unsigned short CCountedStringPool::ReferenceStringHandle( const char* pIntrinsic )
|
||||
{
|
||||
if( pIntrinsic == NULL )
|
||||
return INVALID_ELEMENT;
|
||||
|
||||
unsigned short nHashBucketIndex = (HashStringCaseless( pIntrinsic ) % HASH_TABLE_SIZE);
|
||||
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// Does the bucket already exist?
|
||||
if( nCurrentBucket != INVALID_ELEMENT )
|
||||
{
|
||||
for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
// Anyone who hits 65k references is permanant
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE )
|
||||
{
|
||||
m_Elements[nCurrentBucket].nReferenceCount ++ ;
|
||||
}
|
||||
return nCurrentBucket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_FreeListStart != INVALID_ELEMENT )
|
||||
{
|
||||
nCurrentBucket = m_FreeListStart;
|
||||
m_FreeListStart = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
nCurrentBucket = m_Elements.AddToTail();
|
||||
}
|
||||
|
||||
m_Elements[nCurrentBucket].nReferenceCount = 1;
|
||||
|
||||
// Insert at the beginning of the bucket:
|
||||
m_Elements[nCurrentBucket].nNextElement = m_HashTable[ nHashBucketIndex ];
|
||||
m_HashTable[ nHashBucketIndex ] = nCurrentBucket;
|
||||
|
||||
m_Elements[nCurrentBucket].pString = new char[Q_strlen( pIntrinsic ) + 1];
|
||||
Q_strcpy( m_Elements[nCurrentBucket].pString, pIntrinsic );
|
||||
|
||||
return nCurrentBucket;
|
||||
}
|
||||
|
||||
|
||||
char* CCountedStringPool::ReferenceString( const char* pIntrinsic )
|
||||
{
|
||||
if(!pIntrinsic)
|
||||
return NULL;
|
||||
|
||||
return m_Elements[ReferenceStringHandle( pIntrinsic)].pString;
|
||||
}
|
||||
|
||||
void CCountedStringPool::DereferenceString( const char* pIntrinsic )
|
||||
{
|
||||
// If we get a NULL pointer, just return
|
||||
if (!pIntrinsic)
|
||||
return;
|
||||
|
||||
unsigned short nHashBucketIndex = (HashStringCaseless( pIntrinsic ) % m_HashTable.Count());
|
||||
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
|
||||
|
||||
// If there isn't anything in the bucket, just return.
|
||||
if ( nCurrentBucket == INVALID_ELEMENT )
|
||||
return;
|
||||
|
||||
for( unsigned short previous = INVALID_ELEMENT; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
|
||||
{
|
||||
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
|
||||
{
|
||||
// Anyone who hits 65k references is permanant
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE )
|
||||
{
|
||||
m_Elements[nCurrentBucket].nReferenceCount --;
|
||||
}
|
||||
|
||||
if( m_Elements[nCurrentBucket].nReferenceCount == 0 )
|
||||
{
|
||||
if( previous == INVALID_ELEMENT )
|
||||
{
|
||||
m_HashTable[nHashBucketIndex] = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Elements[previous].nNextElement = m_Elements[nCurrentBucket].nNextElement;
|
||||
}
|
||||
|
||||
delete [] m_Elements[nCurrentBucket].pString;
|
||||
m_Elements[nCurrentBucket].pString = NULL;
|
||||
m_Elements[nCurrentBucket].nReferenceCount = 0;
|
||||
|
||||
m_Elements[nCurrentBucket].nNextElement = m_FreeListStart;
|
||||
m_FreeListStart = nCurrentBucket;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
previous = nCurrentBucket;
|
||||
}
|
||||
}
|
||||
|
||||
char* CCountedStringPool::HandleToString( unsigned short handle )
|
||||
{
|
||||
return m_Elements[handle].pString;
|
||||
}
|
||||
|
||||
void CCountedStringPool::SpewStrings()
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < m_Elements.Count(); i++ )
|
||||
{
|
||||
char* string = m_Elements[i].pString;
|
||||
|
||||
Msg("String %d: ref:%d %s", i, m_Elements[i].nReferenceCount, string == NULL? "EMPTY - ok for slot zero only!" : string);
|
||||
}
|
||||
|
||||
Msg("\n%d total counted strings.", m_Elements.Count());
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
CON_COMMAND( test_stringpool, "Tests the class CStringPool" )
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// $Header: $
|
||||
// $NoKeywords: $
|
||||
@ -92,14 +92,14 @@ CUtlCStringConversion::CUtlCStringConversion( char nEscapeChar, const char *pDel
|
||||
memset( m_pConversion, 0x0, sizeof(m_pConversion) );
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
m_pConversion[ (unsigned char) pArray[i].m_pReplacementString[0] ] = pArray[i].m_nActualChar;
|
||||
m_pConversion[ (unsigned char)(pArray[i].m_pReplacementString[0]) ] = pArray[i].m_nActualChar;
|
||||
}
|
||||
}
|
||||
|
||||
// Finds a conversion for the passed-in string, returns length
|
||||
char CUtlCStringConversion::FindConversion( const char *pString, int *pLength )
|
||||
{
|
||||
char c = m_pConversion[ (unsigned char) pString[0] ];
|
||||
char c = m_pConversion[ (unsigned char)( pString[0] ) ];
|
||||
*pLength = (c != '\0') ? 1 : 0;
|
||||
return c;
|
||||
}
|
||||
@ -114,7 +114,7 @@ CUtlCharConversion::CUtlCharConversion( char nEscapeChar, const char *pDelimiter
|
||||
m_nEscapeChar = nEscapeChar;
|
||||
m_pDelimiter = pDelimiter;
|
||||
m_nCount = nCount;
|
||||
m_nDelimiterLength = Q_strlen( pDelimiter );
|
||||
m_nDelimiterLength = V_strlen( pDelimiter );
|
||||
m_nMaxConversionLength = 0;
|
||||
|
||||
memset( m_pReplacements, 0, sizeof(m_pReplacements) );
|
||||
@ -122,10 +122,10 @@ CUtlCharConversion::CUtlCharConversion( char nEscapeChar, const char *pDelimiter
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
m_pList[i] = pArray[i].m_nActualChar;
|
||||
ConversionInfo_t &info = m_pReplacements[ (unsigned char) m_pList[i] ];
|
||||
ConversionInfo_t &info = m_pReplacements[ (unsigned char)( m_pList[i] ) ];
|
||||
Assert( info.m_pReplacementString == 0 );
|
||||
info.m_pReplacementString = pArray[i].m_pReplacementString;
|
||||
info.m_nLength = Q_strlen( info.m_pReplacementString );
|
||||
info.m_nLength = V_strlen( info.m_pReplacementString );
|
||||
if ( info.m_nLength > m_nMaxConversionLength )
|
||||
{
|
||||
m_nMaxConversionLength = info.m_nLength;
|
||||
@ -158,12 +158,12 @@ int CUtlCharConversion::GetDelimiterLength() const
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CUtlCharConversion::GetConversionString( char c ) const
|
||||
{
|
||||
return m_pReplacements[ (unsigned char) c ].m_pReplacementString;
|
||||
return m_pReplacements[ (unsigned char)c ].m_pReplacementString;
|
||||
}
|
||||
|
||||
int CUtlCharConversion::GetConversionLength( char c ) const
|
||||
{
|
||||
return m_pReplacements[ (unsigned char) c ].m_nLength;
|
||||
return m_pReplacements[ (unsigned char)c ].m_nLength;
|
||||
}
|
||||
|
||||
int CUtlCharConversion::MaxConversionLength() const
|
||||
@ -179,9 +179,9 @@ char CUtlCharConversion::FindConversion( const char *pString, int *pLength )
|
||||
{
|
||||
for ( int i = 0; i < m_nCount; ++i )
|
||||
{
|
||||
if ( !Q_strcmp( pString, m_pReplacements[ (unsigned char) m_pList[i] ].m_pReplacementString ) )
|
||||
if ( !V_strcmp( pString, m_pReplacements[ (unsigned char)( m_pList[i] ) ].m_pReplacementString ) )
|
||||
{
|
||||
*pLength = m_pReplacements[ (unsigned char) m_pList[i] ].m_nLength;
|
||||
*pLength = m_pReplacements[ (unsigned char)( m_pList[i] ) ].m_nLength;
|
||||
return m_pList[i];
|
||||
}
|
||||
}
|
||||
@ -207,7 +207,7 @@ CUtlBuffer::CUtlBuffer( int growSize, int initSize, int nFlags ) :
|
||||
if ( (initSize != 0) && !IsReadOnly() )
|
||||
{
|
||||
m_nMaxPut = -1;
|
||||
AddNullTermination();
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -228,17 +228,115 @@ CUtlBuffer::CUtlBuffer( const void *pBuffer, int nSize, int nFlags ) :
|
||||
m_Flags = nFlags;
|
||||
if ( IsReadOnly() )
|
||||
{
|
||||
m_nMaxPut = nSize;
|
||||
m_nMaxPut = m_Put = nSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nMaxPut = -1;
|
||||
AddNullTermination();
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
SetOverflowFuncs( &CUtlBuffer::GetOverflow, &CUtlBuffer::PutOverflow );
|
||||
}
|
||||
|
||||
|
||||
CUtlBuffer::CUtlBuffer( const CUtlBuffer& copyFrom )
|
||||
: m_Get( copyFrom.m_Get )
|
||||
, m_Put( copyFrom.m_Put )
|
||||
, m_Error( copyFrom.m_Error )
|
||||
, m_Flags( copyFrom.m_Flags )
|
||||
, m_Reserved( copyFrom.m_Reserved )
|
||||
#if defined( _GAMECONSOLE )
|
||||
, pad( copyFrom.pad )
|
||||
#endif
|
||||
, m_nTab( copyFrom.m_nTab )
|
||||
, m_nMaxPut( copyFrom.m_nMaxPut )
|
||||
, m_nOffset( copyFrom.m_nOffset )
|
||||
, m_GetOverflowFunc( copyFrom.m_GetOverflowFunc )
|
||||
, m_PutOverflowFunc( copyFrom.m_PutOverflowFunc )
|
||||
, m_Byteswap( copyFrom.m_Byteswap )
|
||||
{
|
||||
if(copyFrom.m_Memory.Count() > 0)
|
||||
{
|
||||
Assert( false ); // This is a slow path, don't do this.
|
||||
|
||||
// copy memory
|
||||
m_Memory.EnsureCapacity( copyFrom.m_Memory.Count() );
|
||||
memcpy( m_Memory.Base(), copyFrom.m_Memory.Base(), copyFrom.m_Memory.Count() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CUtlBuffer& CUtlBuffer::operator=( const CUtlBuffer& copyFrom )
|
||||
{
|
||||
if ( copyFrom.m_Memory.Count() > 0 )
|
||||
{
|
||||
Assert( false ); // This is a slow path, don't do this.
|
||||
if(this != ©From)
|
||||
{
|
||||
m_Memory.Purge();
|
||||
m_Memory.EnsureCapacity( copyFrom.m_Memory.Count() );
|
||||
memcpy( m_Memory.Base(), copyFrom.m_Memory.Base(), copyFrom.m_Memory.Count() );
|
||||
}
|
||||
}
|
||||
m_Get = copyFrom.m_Get;
|
||||
m_Put = copyFrom.m_Put;
|
||||
m_Error = copyFrom.m_Error;
|
||||
m_Flags = copyFrom.m_Flags;
|
||||
m_Reserved = copyFrom.m_Reserved;
|
||||
#if defined( _GAMECONSOLE )
|
||||
pad = copyFrom.pad;
|
||||
#endif
|
||||
m_nTab = copyFrom.m_nTab;
|
||||
m_nMaxPut = copyFrom.m_nMaxPut;
|
||||
m_nOffset = copyFrom.m_nOffset;
|
||||
m_GetOverflowFunc = copyFrom.m_GetOverflowFunc;
|
||||
m_PutOverflowFunc = copyFrom.m_PutOverflowFunc;
|
||||
m_Byteswap = copyFrom.m_Byteswap;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if VALVE_CPP11
|
||||
CUtlBuffer::CUtlBuffer( CUtlBuffer&& moveFrom ) // = default
|
||||
: m_Memory( Move( moveFrom.m_Memory ) )
|
||||
, m_Get( Move( moveFrom.m_Get ) )
|
||||
, m_Put( Move( moveFrom.m_Put ) )
|
||||
, m_Error( Move( moveFrom.m_Error ) )
|
||||
, m_Flags( Move( moveFrom.m_Flags ) )
|
||||
, m_Reserved( Move( moveFrom.m_Reserved ) )
|
||||
#if defined( _GAMECONSOLE )
|
||||
, pad( Move( moveFrom.pad ) )
|
||||
#endif
|
||||
, m_nTab( Move( moveFrom.m_nTab ) )
|
||||
, m_nMaxPut( Move( moveFrom.m_nMaxPut ) )
|
||||
, m_nOffset( Move( moveFrom.m_nOffset ) )
|
||||
, m_GetOverflowFunc( Move( moveFrom.m_GetOverflowFunc ) )
|
||||
, m_PutOverflowFunc( Move( moveFrom.m_PutOverflowFunc ) )
|
||||
, m_Byteswap( Move( moveFrom.m_Byteswap ) )
|
||||
{}
|
||||
|
||||
CUtlBuffer& CUtlBuffer::operator=( CUtlBuffer&& moveFrom ) // = default
|
||||
{
|
||||
m_Memory = Move( moveFrom.m_Memory );
|
||||
m_Get = Move( moveFrom.m_Get );
|
||||
m_Put = Move( moveFrom.m_Put );
|
||||
m_Error = Move( moveFrom.m_Error );
|
||||
m_Flags = Move( moveFrom.m_Flags );
|
||||
m_Reserved = Move( moveFrom.m_Reserved );
|
||||
#if defined( _GAMECONSOLE )
|
||||
pad = Move( moveFrom.pad );
|
||||
#endif
|
||||
m_nTab = Move( moveFrom.m_nTab );
|
||||
m_nMaxPut = Move( moveFrom.m_nMaxPut );
|
||||
m_nOffset = Move( moveFrom.m_nOffset );
|
||||
m_GetOverflowFunc = Move( moveFrom.m_GetOverflowFunc );
|
||||
m_PutOverflowFunc = Move( moveFrom.m_PutOverflowFunc );
|
||||
m_Byteswap = Move( moveFrom.m_Byteswap );
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Modifies the buffer to be binary or text; Blows away the buffer and the CONTAINS_CRLF value.
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -303,7 +401,7 @@ void CUtlBuffer::SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, i
|
||||
m_nOffset = 0;
|
||||
m_Flags = nFlags;
|
||||
m_nMaxPut = -1;
|
||||
AddNullTermination();
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -321,9 +419,25 @@ void CUtlBuffer::AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nF
|
||||
m_nOffset = 0;
|
||||
m_Flags = nFlags;
|
||||
m_nMaxPut = -1;
|
||||
AddNullTermination();
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Allows the caller to control memory
|
||||
//-----------------------------------------------------------------------------
|
||||
void* CUtlBuffer::DetachMemory()
|
||||
{
|
||||
// Reset all indices; we just changed memory
|
||||
m_Get = 0;
|
||||
m_Put = 0;
|
||||
m_nTab = 0;
|
||||
m_Error = 0;
|
||||
m_nOffset = 0;
|
||||
return m_Memory.DetachMemory( );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes sure we've got at least this much memory
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -351,16 +465,15 @@ void CUtlBuffer::EnsureCapacity( int num )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Base get method from which all others derive
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUtlBuffer::Get( void* pMem, int size )
|
||||
bool CUtlBuffer::Get( void* pMem, int size )
|
||||
{
|
||||
if ( size > 0 && CheckGet( size ) )
|
||||
{
|
||||
int Index = m_Get - m_nOffset;
|
||||
Assert( m_Memory.IsIdxValid( Index ) && m_Memory.IsIdxValid( Index + size - 1 ) );
|
||||
|
||||
memcpy( pMem, &m_Memory[ Index ], size );
|
||||
memcpy( pMem, &m_Memory[m_Get - m_nOffset], size );
|
||||
m_Get += size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -372,10 +485,7 @@ int CUtlBuffer::GetUpTo( void *pMem, int nSize )
|
||||
{
|
||||
if ( CheckArbitraryPeekGet( 0, nSize ) )
|
||||
{
|
||||
int Index = m_Get - m_nOffset;
|
||||
Assert( m_Memory.IsIdxValid( Index ) && m_Memory.IsIdxValid( Index + nSize - 1 ) );
|
||||
|
||||
memcpy( pMem, &m_Memory[ Index ], nSize );
|
||||
memcpy( pMem, &m_Memory[m_Get - m_nOffset], nSize );
|
||||
m_Get += nSize;
|
||||
return nSize;
|
||||
}
|
||||
@ -392,7 +502,7 @@ void CUtlBuffer::EatWhiteSpace()
|
||||
{
|
||||
while ( CheckGet( sizeof(char) ) )
|
||||
{
|
||||
if ( !isspace( *(const unsigned char*)PeekGet() ) )
|
||||
if ( !V_isspace( *(const unsigned char*)PeekGet() ) )
|
||||
break;
|
||||
m_Get += sizeof(char);
|
||||
}
|
||||
@ -437,7 +547,7 @@ int CUtlBuffer::PeekWhiteSpace( int nOffset )
|
||||
|
||||
while ( CheckPeekGet( nOffset, sizeof(char) ) )
|
||||
{
|
||||
if ( !isspace( *(unsigned char*)PeekGet( nOffset ) ) )
|
||||
if ( !V_isspace( *(unsigned char*)PeekGet( nOffset ) ) )
|
||||
break;
|
||||
nOffset += sizeof(char);
|
||||
}
|
||||
@ -491,7 +601,7 @@ int CUtlBuffer::PeekStringLength()
|
||||
for ( int i = 0; i < nPeekAmount; ++i )
|
||||
{
|
||||
// The +1 here is so we eat the terminating 0
|
||||
if ( isspace((unsigned char)pTest[i]) || (pTest[i] == 0) )
|
||||
if ( V_isspace((unsigned char)pTest[i]) || (pTest[i] == 0) )
|
||||
return (i + nOffset - nStartingOffset + 1);
|
||||
}
|
||||
}
|
||||
@ -550,7 +660,7 @@ bool CUtlBuffer::PeekStringMatch( int nOffset, const char *pString, int nLen )
|
||||
{
|
||||
if ( !CheckPeekGet( nOffset, nLen ) )
|
||||
return false;
|
||||
return !Q_strncmp( (const char*)PeekGet(nOffset), pString, nLen );
|
||||
return !V_strncmp( (const char*)PeekGet(nOffset), pString, nLen );
|
||||
}
|
||||
|
||||
|
||||
@ -607,19 +717,16 @@ int CUtlBuffer::PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActu
|
||||
//-----------------------------------------------------------------------------
|
||||
// Reads a null-terminated string
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUtlBuffer::GetStringInternal( char *pString, size_t maxLenInChars )
|
||||
void CUtlBuffer::GetString( char* pString, int nMaxChars )
|
||||
{
|
||||
if ( !IsValid() )
|
||||
if (!IsValid())
|
||||
{
|
||||
*pString = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// This can legitimately be zero if we were told that the buffer is zero length, and
|
||||
// we're asking to duplicate the buffer, so let that pass, too.
|
||||
Assert( maxLenInChars != 0 || PeekStringLength() == 0 );
|
||||
|
||||
if ( maxLenInChars == 0 )
|
||||
Assert( nMaxChars > 0 );
|
||||
if ( nMaxChars <= 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -640,14 +747,14 @@ void CUtlBuffer::GetStringInternal( char *pString, size_t maxLenInChars )
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t nCharsToRead = min( (size_t)nLen, maxLenInChars ) - 1;
|
||||
|
||||
const int nCharsToRead = Min( nLen, nMaxChars ) - 1;
|
||||
|
||||
Get( pString, nCharsToRead );
|
||||
pString[nCharsToRead] = 0;
|
||||
pString[ nCharsToRead ] = 0;
|
||||
|
||||
if ( (size_t)nLen > (nCharsToRead + 1) )
|
||||
if ( nLen > ( nCharsToRead + 1 ) )
|
||||
{
|
||||
SeekGet( SEEK_CURRENT, nLen - (nCharsToRead + 1) );
|
||||
SeekGet( SEEK_CURRENT, nLen - ( nCharsToRead + 1 ) );
|
||||
}
|
||||
|
||||
// Read the terminating NULL in binary formats
|
||||
@ -663,7 +770,7 @@ void CUtlBuffer::GetStringInternal( char *pString, size_t maxLenInChars )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUtlBuffer::GetLine( char* pLine, int nMaxChars )
|
||||
{
|
||||
Assert( IsText() && !ContainsCRLF() );
|
||||
//Assert( IsText() && !ContainsCRLF() );
|
||||
|
||||
if ( !IsValid() )
|
||||
{
|
||||
@ -732,7 +839,7 @@ void CUtlBuffer::GetDelimitedString( CUtlCharConversion *pConv, char *pString, i
|
||||
{
|
||||
if ( !IsText() || !pConv )
|
||||
{
|
||||
GetStringInternal( pString, nMaxChars );
|
||||
GetString( pString, nMaxChars );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -858,11 +965,7 @@ const void* CUtlBuffer::PeekGet( int nMaxSize, int nOffset )
|
||||
{
|
||||
if ( !CheckPeekGet( nOffset, nMaxSize ) )
|
||||
return NULL;
|
||||
|
||||
int Index = m_Get + nOffset - m_nOffset;
|
||||
Assert( m_Memory.IsIdxValid( Index ) && m_Memory.IsIdxValid( Index + nMaxSize - 1 ) );
|
||||
|
||||
return &m_Memory[ Index ];
|
||||
return &m_Memory[ m_Get + nOffset - m_nOffset ];
|
||||
}
|
||||
|
||||
|
||||
@ -914,10 +1017,8 @@ int CUtlBuffer::VaScanf( const char* pFmt, va_list list )
|
||||
return 0;
|
||||
|
||||
int numScanned = 0;
|
||||
int nLength;
|
||||
char c;
|
||||
char* pEnd;
|
||||
while ( (c = *pFmt++) )
|
||||
while ( c = *pFmt++ )
|
||||
{
|
||||
// Stop if we hit the end of the buffer
|
||||
if ( m_Get >= TellMaxPut() )
|
||||
@ -956,93 +1057,105 @@ int CUtlBuffer::VaScanf( const char* pFmt, va_list list )
|
||||
return numScanned;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
{
|
||||
if ( *pFmt == 'd' || *pFmt == 'i' )
|
||||
{
|
||||
if ( !GetTypeText( *va_arg( list, int16 * ) ) )
|
||||
return numScanned; // only support short ints, don't bother with hex
|
||||
}
|
||||
else if ( *pFmt == 'u' )
|
||||
{
|
||||
if ( !GetTypeText( *va_arg( list, uint16 * ) ) )
|
||||
return numScanned;
|
||||
}
|
||||
else
|
||||
return numScanned;
|
||||
++pFmt;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
{
|
||||
if ( *pFmt++ != '6' || *pFmt++ != '4' )
|
||||
return numScanned; // only support "I64d" and "I64u"
|
||||
|
||||
if ( *pFmt == 'd' )
|
||||
{
|
||||
if ( !GetTypeText( *va_arg( list, int64 * ) ) )
|
||||
return numScanned;
|
||||
}
|
||||
else if ( *pFmt == 'u' )
|
||||
{
|
||||
if ( !GetTypeText( *va_arg( list, uint64 * ) ) )
|
||||
return numScanned;
|
||||
}
|
||||
else
|
||||
{
|
||||
return numScanned;
|
||||
}
|
||||
|
||||
++pFmt;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
case 'd':
|
||||
{
|
||||
int* i = va_arg( list, int * );
|
||||
|
||||
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
|
||||
nLength = 128;
|
||||
if ( !CheckArbitraryPeekGet( 0, nLength ) )
|
||||
{
|
||||
*i = 0;
|
||||
int32 *pArg = va_arg( list, int32 * );
|
||||
if ( !GetTypeText( *pArg ) )
|
||||
return numScanned;
|
||||
}
|
||||
|
||||
*i = strtol( (char*)PeekGet(), &pEnd, 10 );
|
||||
int nBytesRead = (int)( pEnd - (char*)PeekGet() );
|
||||
if ( nBytesRead == 0 )
|
||||
return numScanned;
|
||||
m_Get += nBytesRead;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'x':
|
||||
{
|
||||
int* i = va_arg( list, int * );
|
||||
|
||||
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
|
||||
nLength = 128;
|
||||
if ( !CheckArbitraryPeekGet( 0, nLength ) )
|
||||
{
|
||||
*i = 0;
|
||||
uint32 *pArg = va_arg( list, uint32 * );
|
||||
if ( !GetTypeText( *pArg, 16 ) )
|
||||
return numScanned;
|
||||
}
|
||||
|
||||
*i = strtol( (char*)PeekGet(), &pEnd, 16 );
|
||||
int nBytesRead = (int)( pEnd - (char*)PeekGet() );
|
||||
if ( nBytesRead == 0 )
|
||||
return numScanned;
|
||||
m_Get += nBytesRead;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'u':
|
||||
{
|
||||
unsigned int* u = va_arg( list, unsigned int *);
|
||||
|
||||
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
|
||||
nLength = 128;
|
||||
if ( !CheckArbitraryPeekGet( 0, nLength ) )
|
||||
{
|
||||
*u = 0;
|
||||
uint32 *pArg = va_arg( list, uint32 * );
|
||||
if ( !GetTypeText( *pArg ) )
|
||||
return numScanned;
|
||||
}
|
||||
|
||||
*u = strtoul( (char*)PeekGet(), &pEnd, 10 );
|
||||
int nBytesRead = (int)( pEnd - (char*)PeekGet() );
|
||||
if ( nBytesRead == 0 )
|
||||
return numScanned;
|
||||
m_Get += nBytesRead;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'l':
|
||||
{
|
||||
// we currently support %lf and %lld
|
||||
if ( *pFmt == 'f' )
|
||||
{
|
||||
if ( !GetTypeText( *va_arg( list, double * ) ) )
|
||||
return numScanned;
|
||||
}
|
||||
else if ( *pFmt == 'l' && *++pFmt == 'd' )
|
||||
{
|
||||
if ( !GetTypeText( *va_arg( list, int64 * ) ) )
|
||||
return numScanned;
|
||||
}
|
||||
else
|
||||
return numScanned;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
{
|
||||
float* f = va_arg( list, float *);
|
||||
|
||||
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
|
||||
nLength = 128;
|
||||
if ( !CheckArbitraryPeekGet( 0, nLength ) )
|
||||
{
|
||||
*f = 0.0f;
|
||||
float *pArg = va_arg( list, float * );
|
||||
if ( !GetTypeText( *pArg ) )
|
||||
return numScanned;
|
||||
}
|
||||
|
||||
*f = (float)strtod( (char*)PeekGet(), &pEnd );
|
||||
int nBytesRead = (int)( pEnd - (char*)PeekGet() );
|
||||
if ( nBytesRead == 0 )
|
||||
return numScanned;
|
||||
m_Get += nBytesRead;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 's':
|
||||
{
|
||||
char* s = va_arg( list, char * );
|
||||
GetStringInternal( s, 256 );
|
||||
GetString( s, 64 ); // [SECURITY EXPLOIT: Scanf %s should be deprecated as malicious data can overrun stack buffers! Here we'd assume that at least 64 bytes are available on the stack, and even if not this shouldn't give attracker much room for code execution]
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1099,38 +1212,55 @@ bool CUtlBuffer::GetToken( const char *pToken )
|
||||
Assert( pToken );
|
||||
|
||||
// Look for the token
|
||||
int nLen = Q_strlen( pToken );
|
||||
int nLen = V_strlen( pToken );
|
||||
|
||||
int nSizeToCheck = Size() - TellGet() - m_nOffset;
|
||||
// First time through on streaming, check what we already have loaded
|
||||
// if we have enough loaded to do the check
|
||||
int nMaxSize = Size() - ( TellGet() - m_nOffset );
|
||||
if ( nMaxSize <= nLen )
|
||||
{
|
||||
nMaxSize = Size();
|
||||
}
|
||||
int nSizeRemaining = TellMaxPut() - TellGet();
|
||||
|
||||
int nGet = TellGet();
|
||||
do
|
||||
while ( nSizeRemaining >= nLen )
|
||||
{
|
||||
int nMaxSize = TellMaxPut() - TellGet();
|
||||
if ( nMaxSize < nSizeToCheck )
|
||||
{
|
||||
nSizeToCheck = nMaxSize;
|
||||
}
|
||||
if ( nLen > nSizeToCheck )
|
||||
break;
|
||||
|
||||
bool bOverFlow = ( nSizeRemaining > nMaxSize );
|
||||
int nSizeToCheck = bOverFlow ? nMaxSize : nSizeRemaining;
|
||||
if ( !CheckPeekGet( 0, nSizeToCheck ) )
|
||||
break;
|
||||
|
||||
const char *pBufStart = (const char*)PeekGet();
|
||||
const char *pFoundEnd = Q_strnistr( pBufStart, pToken, nSizeToCheck );
|
||||
if ( pFoundEnd )
|
||||
const char *pFoundEnd = V_strnistr( pBufStart, pToken, nSizeToCheck );
|
||||
|
||||
// Time to be careful: if we are in a state of overflow
|
||||
// (namely, there's more of the buffer beyond the current window)
|
||||
// we could be looking for 'foo' for example, and find 'foobar'
|
||||
// if 'foo' happens to be the last 3 characters of the current window
|
||||
size_t nOffset = (size_t)pFoundEnd - (size_t)pBufStart;
|
||||
bool bPotentialMismatch = ( bOverFlow && ( (int)nOffset == Size() - nLen ) );
|
||||
if ( !pFoundEnd || bPotentialMismatch )
|
||||
{
|
||||
size_t nOffset = (size_t)pFoundEnd - (size_t)pBufStart;
|
||||
SeekGet( CUtlBuffer::SEEK_CURRENT, nOffset + nLen );
|
||||
return true;
|
||||
nSizeRemaining -= nSizeToCheck;
|
||||
if ( !pFoundEnd && ( nSizeRemaining < nLen ) )
|
||||
break;
|
||||
|
||||
// Second time through, stream as much in as possible
|
||||
// But keep the last portion of the current buffer
|
||||
// since we couldn't check it against stuff outside the window
|
||||
nSizeRemaining += nLen;
|
||||
nMaxSize = Size();
|
||||
SeekGet( CUtlBuffer::SEEK_CURRENT, nSizeToCheck - nLen );
|
||||
continue;
|
||||
}
|
||||
|
||||
SeekGet( CUtlBuffer::SEEK_CURRENT, nSizeToCheck - nLen - 1 );
|
||||
nSizeToCheck = Size() - (nLen-1);
|
||||
|
||||
} while ( true );
|
||||
// Seek past the end of the found string
|
||||
SeekGet( CUtlBuffer::SEEK_CURRENT, (int)( nOffset + nLen ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
// Didn't find a match, leave the get index where it was to start with
|
||||
SeekGet( CUtlBuffer::SEEK_HEAD, nGet );
|
||||
return false;
|
||||
}
|
||||
@ -1161,7 +1291,7 @@ bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDeli
|
||||
|
||||
// Ending delimiter is not
|
||||
Assert( pEndingDelim && pEndingDelim[0] );
|
||||
nEndingDelimLen = Q_strlen( pEndingDelim );
|
||||
nEndingDelimLen = V_strlen( pEndingDelim );
|
||||
|
||||
int nStartGet = TellGet();
|
||||
char nCurrChar;
|
||||
@ -1170,7 +1300,7 @@ bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDeli
|
||||
while ( *pStartingDelim )
|
||||
{
|
||||
nCurrChar = *pStartingDelim++;
|
||||
if ( !isspace((unsigned char)nCurrChar) )
|
||||
if ( !V_isspace((unsigned char)nCurrChar) )
|
||||
{
|
||||
if ( tolower( GetChar() ) != tolower( nCurrChar ) )
|
||||
goto parseFailed;
|
||||
@ -1187,7 +1317,7 @@ bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDeli
|
||||
goto parseFailed;
|
||||
|
||||
nCurrentGet = TellGet();
|
||||
nCharsToCopy = (nCurrentGet - nEndingDelimLen) - nTokenStart;
|
||||
nCharsToCopy = (int)( (nCurrentGet - nEndingDelimLen) - nTokenStart );
|
||||
if ( nCharsToCopy >= nMaxLen )
|
||||
{
|
||||
nCharsToCopy = nMaxLen - 1;
|
||||
@ -1203,7 +1333,7 @@ bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDeli
|
||||
// Eat trailing whitespace
|
||||
for ( ; nCharsToCopy > 0; --nCharsToCopy )
|
||||
{
|
||||
if ( !isspace( (unsigned char)pString[ nCharsToCopy-1 ] ) )
|
||||
if ( !V_isspace( (unsigned char)pString[ nCharsToCopy-1 ] ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1319,15 +1449,10 @@ void CUtlBuffer::Put( const void *pMem, int size )
|
||||
{
|
||||
if ( size && CheckPut( size ) )
|
||||
{
|
||||
int Index = m_Put - m_nOffset;
|
||||
Assert( m_Memory.IsIdxValid( Index ) && m_Memory.IsIdxValid( Index + size - 1 ) );
|
||||
if( Index >= 0 )
|
||||
{
|
||||
memcpy( &m_Memory[ Index ], pMem, size );
|
||||
m_Put += size;
|
||||
memcpy( &m_Memory[m_Put - m_nOffset], pMem, size );
|
||||
m_Put += size;
|
||||
|
||||
AddNullTermination();
|
||||
}
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1342,7 +1467,7 @@ void CUtlBuffer::PutString( const char* pString )
|
||||
if ( pString )
|
||||
{
|
||||
// Not text? append a null at the end.
|
||||
size_t nLen = Q_strlen( pString ) + 1;
|
||||
int nLen = (int)V_strlen( pString ) + 1;
|
||||
Put( pString, nLen * sizeof(char) );
|
||||
return;
|
||||
}
|
||||
@ -1365,7 +1490,7 @@ void CUtlBuffer::PutString( const char* pString )
|
||||
while ( pEndl )
|
||||
{
|
||||
size_t nSize = (size_t)pEndl - (size_t)pString + sizeof(char);
|
||||
Put( pString, nSize );
|
||||
Put( pString, (int)nSize );
|
||||
pString = pEndl + 1;
|
||||
if ( *pString )
|
||||
{
|
||||
@ -1378,7 +1503,7 @@ void CUtlBuffer::PutString( const char* pString )
|
||||
}
|
||||
}
|
||||
}
|
||||
size_t nLen = Q_strlen( pString );
|
||||
int nLen = (int)V_strlen( pString );
|
||||
if ( nLen )
|
||||
{
|
||||
Put( pString, nLen * sizeof(char) );
|
||||
@ -1430,7 +1555,7 @@ void CUtlBuffer::PutDelimitedString( CUtlCharConversion *pConv, const char *pStr
|
||||
}
|
||||
Put( pConv->GetDelimiter(), pConv->GetDelimiterLength() );
|
||||
|
||||
int nLen = pString ? Q_strlen( pString ) : 0;
|
||||
int nLen = pString ? V_strlen( pString ) : 0;
|
||||
for ( int i = 0; i < nLen; ++i )
|
||||
{
|
||||
PutDelimitedCharInternal( pConv, pString[i] );
|
||||
@ -1446,12 +1571,9 @@ void CUtlBuffer::PutDelimitedString( CUtlCharConversion *pConv, const char *pStr
|
||||
|
||||
void CUtlBuffer::VaPrintf( const char* pFmt, va_list list )
|
||||
{
|
||||
char temp[2048];
|
||||
#ifdef DBGFLAG_ASSERT
|
||||
int nLen =
|
||||
#endif
|
||||
Q_vsnprintf( temp, sizeof( temp ), pFmt, list );
|
||||
Assert( nLen < 2048 );
|
||||
char temp[8192];
|
||||
int nLen = V_vsnprintf( temp, sizeof( temp ), pFmt, list );
|
||||
ErrorIfNot( nLen < sizeof( temp ), ( "CUtlBuffer::VaPrintf: String overflowed buffer [%d]\n", sizeof( temp ) ) );
|
||||
PutString( temp );
|
||||
}
|
||||
|
||||
@ -1563,7 +1685,7 @@ void CUtlBuffer::SeekPut( SeekType_t type, int offset )
|
||||
OnPutOverflow( -nNextPut-1 );
|
||||
m_Put = nNextPut;
|
||||
|
||||
AddNullTermination();
|
||||
AddNullTermination( m_Put );
|
||||
}
|
||||
|
||||
|
||||
@ -1585,8 +1707,10 @@ bool CUtlBuffer::IsBigEndian( void )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// null terminate the buffer
|
||||
// NOTE: Pass in nPut here even though it is just a copy of m_Put. This is almost always called immediately
|
||||
// after modifying m_Put and this lets it stay in a register and avoid LHS on PPC.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CUtlBuffer::AddNullTermination( void )
|
||||
void CUtlBuffer::AddNullTermination( )
|
||||
{
|
||||
if ( m_Put > m_nMaxPut )
|
||||
{
|
||||
@ -1595,12 +1719,7 @@ void CUtlBuffer::AddNullTermination( void )
|
||||
// Add null termination value
|
||||
if ( CheckPut( 1 ) )
|
||||
{
|
||||
int Index = m_Put - m_nOffset;
|
||||
Assert( m_Memory.IsIdxValid( Index ) );
|
||||
if( Index >= 0 )
|
||||
{
|
||||
m_Memory[ Index ] = 0;
|
||||
}
|
||||
m_Memory[m_Put - m_nOffset] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1613,6 +1732,29 @@ void CUtlBuffer::AddNullTermination( void )
|
||||
}
|
||||
|
||||
|
||||
void CUtlBuffer::AddNullTermination( int nPut )
|
||||
{
|
||||
if ( nPut > m_nMaxPut )
|
||||
{
|
||||
if ( !IsReadOnly() && ((m_Error & PUT_OVERFLOW) == 0) )
|
||||
{
|
||||
// Add null termination value
|
||||
if ( CheckPut( 1 ) )
|
||||
{
|
||||
m_Memory[nPut - m_nOffset] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore the overflow state, it was valid before...
|
||||
m_Error &= ~PUT_OVERFLOW;
|
||||
}
|
||||
}
|
||||
m_nMaxPut = nPut;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Converts a buffer from a CRLF buffer to a CR buffer (and back)
|
||||
// Returns false if no conversion was necessary (and outBuf is left untouched)
|
||||
@ -1640,21 +1782,21 @@ bool CUtlBuffer::ConvertCRLF( CUtlBuffer &outBuf )
|
||||
int nPutDelta = 0;
|
||||
|
||||
const char *pBase = (const char*)Base();
|
||||
int nCurrGet = 0;
|
||||
intp nCurrGet = 0;
|
||||
while ( nCurrGet < nInCount )
|
||||
{
|
||||
const char *pCurr = &pBase[nCurrGet];
|
||||
if ( bFromCRLF )
|
||||
{
|
||||
const char *pNext = Q_strnistr( pCurr, "\r\n", nInCount - nCurrGet );
|
||||
const char *pNext = V_strnistr( pCurr, "\r\n", nInCount - nCurrGet );
|
||||
if ( !pNext )
|
||||
{
|
||||
outBuf.Put( pCurr, nInCount - nCurrGet );
|
||||
break;
|
||||
}
|
||||
|
||||
int nBytes = (size_t)pNext - (size_t)pCurr;
|
||||
outBuf.Put( pCurr, nBytes );
|
||||
intp nBytes = (intp)pNext - (intp)pCurr;
|
||||
outBuf.Put( pCurr, (int)nBytes );
|
||||
outBuf.PutChar( '\n' );
|
||||
nCurrGet += nBytes + 2;
|
||||
if ( nGet >= nCurrGet - 1 )
|
||||
@ -1668,15 +1810,15 @@ bool CUtlBuffer::ConvertCRLF( CUtlBuffer &outBuf )
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *pNext = Q_strnchr( pCurr, '\n', nInCount - nCurrGet );
|
||||
const char *pNext = V_strnchr( pCurr, '\n', nInCount - nCurrGet );
|
||||
if ( !pNext )
|
||||
{
|
||||
outBuf.Put( pCurr, nInCount - nCurrGet );
|
||||
break;
|
||||
}
|
||||
|
||||
int nBytes = (size_t)pNext - (size_t)pCurr;
|
||||
outBuf.Put( pCurr, nBytes );
|
||||
intp nBytes = (intp)pNext - (intp)pCurr;
|
||||
outBuf.Put( pCurr, (int)nBytes );
|
||||
outBuf.PutChar( '\r' );
|
||||
outBuf.PutChar( '\n' );
|
||||
nCurrGet += nBytes + 1;
|
||||
@ -1793,4 +1935,3 @@ char * CUtlInplaceBuffer::InplaceGetLinePtr( void )
|
||||
|
||||
return pszLine;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright <EFBFBD> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Defines a symbol table
|
||||
//
|
||||
@ -9,29 +9,11 @@
|
||||
#pragma warning (disable:4514)
|
||||
|
||||
#include "utlsymbol.h"
|
||||
#include "KeyValues.h"
|
||||
#include "tier0/threadtools.h"
|
||||
#include "tier0/memdbgon.h"
|
||||
#include "stringpool.h"
|
||||
#include "utlhashtable.h"
|
||||
#include "utlstring.h"
|
||||
|
||||
// Ensure that everybody has the right compiler version installed. The version
|
||||
// number can be obtained by looking at the compiler output when you type 'cl'
|
||||
// and removing the last two digits and the periods: 16.00.40219.01 becomes 160040219
|
||||
#ifdef _MSC_FULL_VER
|
||||
#if _MSC_FULL_VER > 160000000
|
||||
// VS 2010
|
||||
#if _MSC_FULL_VER < 160040219
|
||||
#error You must install VS 2010 SP1
|
||||
#endif
|
||||
#else
|
||||
// VS 2005
|
||||
#if _MSC_FULL_VER < 140050727
|
||||
#error You must install VS 2005 SP1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#include "generichash.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include <stddef.h>
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
@ -68,6 +50,17 @@ void CUtlSymbol::Initialize()
|
||||
}
|
||||
}
|
||||
|
||||
void CUtlSymbol::LockTableForRead()
|
||||
{
|
||||
Initialize();
|
||||
s_pSymbolTable->LockForRead();
|
||||
}
|
||||
|
||||
void CUtlSymbol::UnlockTableForRead()
|
||||
{
|
||||
s_pSymbolTable->UnlockForRead();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Singleton to delete table on exit from module
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -104,6 +97,11 @@ const char* CUtlSymbol::String( ) const
|
||||
return CurrTable()->String(m_Id);
|
||||
}
|
||||
|
||||
const char* CUtlSymbol::StringNoLock( ) const
|
||||
{
|
||||
return CurrTable()->StringNoLock(m_Id);
|
||||
}
|
||||
|
||||
void CUtlSymbol::DisableStaticSymbolTable()
|
||||
{
|
||||
s_bAllowStaticSymbolTable = false;
|
||||
@ -125,16 +123,25 @@ bool CUtlSymbol::operator==( const char* pStr ) const
|
||||
//-----------------------------------------------------------------------------
|
||||
// symbol table stuff
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &index ) const
|
||||
inline const char* CUtlSymbolTable::DecoratedStringFromIndex( const CStringPoolIndex &index ) const
|
||||
{
|
||||
Assert( index.m_iPool < m_StringPools.Count() );
|
||||
Assert( index.m_iOffset < m_StringPools[index.m_iPool]->m_TotalLen );
|
||||
|
||||
return &m_StringPools[index.m_iPool]->m_Data[index.m_iOffset];
|
||||
// step over the hash decorating the beginning of the string
|
||||
return (&m_StringPools[index.m_iPool]->m_Data[index.m_iOffset]);
|
||||
}
|
||||
|
||||
inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &index ) const
|
||||
{
|
||||
// step over the hash decorating the beginning of the string
|
||||
return DecoratedStringFromIndex(index)+sizeof(hashDecoration_t);
|
||||
}
|
||||
|
||||
// The first two bytes of each string in the pool are actually the hash for that string.
|
||||
// Thus we compare hashes rather than entire strings for a significant perf benefit.
|
||||
// However since there is a high rate of hash collision we must still compare strings
|
||||
// if the hashes match.
|
||||
bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStringPoolIndex &i2 ) const
|
||||
{
|
||||
// Need to do pointer math because CUtlSymbolTable is used in CUtlVectors, and hence
|
||||
@ -142,21 +149,79 @@ bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStri
|
||||
// right now at least, because m_LessFunc is the first member of CUtlRBTree, and m_Lookup
|
||||
// is the first member of CUtlSymbolTabke, this == pTable
|
||||
CUtlSymbolTable *pTable = (CUtlSymbolTable *)( (byte *)this - offsetof(CUtlSymbolTable::CTree, m_LessFunc) ) - offsetof(CUtlSymbolTable, m_Lookup );
|
||||
|
||||
#if 1 // using the hashes
|
||||
const char *str1, *str2;
|
||||
hashDecoration_t hash1, hash2;
|
||||
|
||||
if (i1 == INVALID_STRING_INDEX)
|
||||
{
|
||||
str1 = pTable->m_pUserSearchString;
|
||||
hash1 = pTable->m_nUserSearchStringHash;
|
||||
}
|
||||
else
|
||||
{
|
||||
str1 = pTable->DecoratedStringFromIndex( i1 );
|
||||
hashDecoration_t storedHash = *reinterpret_cast<const hashDecoration_t *>(str1);
|
||||
str1 += sizeof(hashDecoration_t);
|
||||
AssertMsg2( storedHash == ( !pTable->m_bInsensitive ? HashString(str1) : HashStringCaseless(str1) ),
|
||||
"The stored hash (%d) for symbol %s is not correct.", storedHash, str1 );
|
||||
hash1 = storedHash;
|
||||
}
|
||||
|
||||
if (i2 == INVALID_STRING_INDEX)
|
||||
{
|
||||
str2 = pTable->m_pUserSearchString;
|
||||
hash2 = pTable->m_nUserSearchStringHash;
|
||||
}
|
||||
else
|
||||
{
|
||||
str2 = pTable->DecoratedStringFromIndex( i2 );
|
||||
hashDecoration_t storedHash = *reinterpret_cast<const hashDecoration_t *>(str2);
|
||||
str2 += sizeof(hashDecoration_t);
|
||||
AssertMsg2( storedHash == ( !pTable->m_bInsensitive ? HashString(str2) : HashStringCaseless(str2) ),
|
||||
"The stored hash (%d) for symbol '%s' is not correct.", storedHash, str2 );
|
||||
hash2 = storedHash;
|
||||
}
|
||||
|
||||
// compare the hashes
|
||||
if ( hash1 == hash2 )
|
||||
{
|
||||
if ( !str1 && str2 )
|
||||
return 1;
|
||||
if ( !str2 && str1 )
|
||||
return -1;
|
||||
if ( !str1 && !str2 )
|
||||
return 0;
|
||||
|
||||
// if the hashes match compare the strings
|
||||
if ( !pTable->m_bInsensitive )
|
||||
return strcmp( str1, str2 ) < 0;
|
||||
else
|
||||
return V_stricmp( str1, str2 ) < 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return hash1 < hash2;
|
||||
}
|
||||
|
||||
#else // not using the hashes, just comparing strings
|
||||
const char* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
|
||||
pTable->StringFromIndex( i1 );
|
||||
pTable->StringFromIndex( i1 );
|
||||
const char* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
|
||||
pTable->StringFromIndex( i2 );
|
||||
pTable->StringFromIndex( i2 );
|
||||
|
||||
if ( !str1 && str2 )
|
||||
return false;
|
||||
return 1;
|
||||
if ( !str2 && str1 )
|
||||
return true;
|
||||
return -1;
|
||||
if ( !str1 && !str2 )
|
||||
return false;
|
||||
return 0;
|
||||
if ( !pTable->m_bInsensitive )
|
||||
return V_strcmp( str1, str2 ) < 0;
|
||||
return strcmp( str1, str2 ) < 0;
|
||||
else
|
||||
return V_stricmp( str1, str2 ) < 0;
|
||||
return strcmpi( str1, str2 ) < 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -177,11 +242,13 @@ CUtlSymbolTable::~CUtlSymbolTable()
|
||||
|
||||
CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
|
||||
{
|
||||
VPROF( "CUtlSymbol::Find" );
|
||||
if (!pString)
|
||||
return CUtlSymbol();
|
||||
|
||||
// Store a special context used to help with insertion
|
||||
m_pUserSearchString = pString;
|
||||
m_nUserSearchStringHash = m_bInsensitive ? HashStringCaseless(pString) : HashString(pString) ;
|
||||
|
||||
// Passing this special invalid symbol makes the comparison function
|
||||
// use the string passed in the context
|
||||
@ -189,6 +256,7 @@ CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
|
||||
|
||||
#ifdef _DEBUG
|
||||
m_pUserSearchString = NULL;
|
||||
m_nUserSearchStringHash = 0;
|
||||
#endif
|
||||
|
||||
return CUtlSymbol( idx );
|
||||
@ -217,6 +285,7 @@ int CUtlSymbolTable::FindPoolWithSpace( int len ) const
|
||||
|
||||
CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
|
||||
{
|
||||
VPROF("CUtlSymbol::AddString");
|
||||
if (!pString)
|
||||
return CUtlSymbol( UTL_INVAL_SYMBOL );
|
||||
|
||||
@ -225,35 +294,47 @@ CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
|
||||
if (id.IsValid())
|
||||
return id;
|
||||
|
||||
int len = V_strlen(pString) + 1;
|
||||
int lenString = strlen(pString) + 1; // length of just the string
|
||||
int lenDecorated = lenString + sizeof(hashDecoration_t); // and with its hash decoration
|
||||
// make sure that all strings are aligned on 2-byte boundaries so the hashes will read correctly
|
||||
COMPILE_TIME_ASSERT(sizeof(hashDecoration_t) == 2);
|
||||
lenDecorated = (lenDecorated + 1) & (~0x01); // round up to nearest multiple of 2
|
||||
|
||||
// Find a pool with space for this string, or allocate a new one.
|
||||
int iPool = FindPoolWithSpace( len );
|
||||
int iPool = FindPoolWithSpace( lenDecorated );
|
||||
if ( iPool == -1 )
|
||||
{
|
||||
// Add a new pool.
|
||||
int newPoolSize = max( len, MIN_STRING_POOL_SIZE );
|
||||
StringPool_t *pPool = (StringPool_t*)malloc( sizeof( StringPool_t ) + newPoolSize - 1 );
|
||||
pPool->m_TotalLen = newPoolSize;
|
||||
int newPoolSize = MAX( lenDecorated + sizeof( StringPool_t ), MIN_STRING_POOL_SIZE );
|
||||
StringPool_t *pPool = (StringPool_t*)malloc( newPoolSize );
|
||||
pPool->m_TotalLen = newPoolSize - sizeof( StringPool_t );
|
||||
pPool->m_SpaceUsed = 0;
|
||||
iPool = m_StringPools.AddToTail( pPool );
|
||||
}
|
||||
|
||||
// Compute a hash
|
||||
hashDecoration_t hash = m_bInsensitive ? HashStringCaseless(pString) : HashString(pString) ;
|
||||
|
||||
// Copy the string in.
|
||||
StringPool_t *pPool = m_StringPools[iPool];
|
||||
Assert( pPool->m_SpaceUsed < 0xFFFF ); // This should never happen, because if we had a string > 64k, it
|
||||
// would have been given its entire own pool.
|
||||
|
||||
unsigned short iStringOffset = pPool->m_SpaceUsed;
|
||||
const char *startingAddr = &pPool->m_Data[pPool->m_SpaceUsed];
|
||||
|
||||
memcpy( &pPool->m_Data[pPool->m_SpaceUsed], pString, len );
|
||||
pPool->m_SpaceUsed += len;
|
||||
// store the hash at the head of the string
|
||||
*((hashDecoration_t *)(startingAddr)) = hash;
|
||||
// and then the string's data
|
||||
memcpy( (void *)(startingAddr + sizeof(hashDecoration_t)), pString, lenString );
|
||||
pPool->m_SpaceUsed += lenDecorated;
|
||||
|
||||
// didn't find, insert the string into the vector.
|
||||
// insert the string into the vector.
|
||||
CStringPoolIndex index;
|
||||
index.m_iPool = iPool;
|
||||
index.m_iOffset = iStringOffset;
|
||||
|
||||
MEM_ALLOC_CREDIT();
|
||||
UtlSymId_t idx = m_Lookup.Insert( index );
|
||||
return CUtlSymbol( idx );
|
||||
}
|
||||
@ -288,22 +369,6 @@ void CUtlSymbolTable::RemoveAll()
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CUtlFilenameSymbolTable::HashTable : public CUtlStableHashtable<CUtlConstString>
|
||||
{
|
||||
};
|
||||
|
||||
CUtlFilenameSymbolTable::CUtlFilenameSymbolTable()
|
||||
{
|
||||
m_Strings = new HashTable;
|
||||
}
|
||||
|
||||
CUtlFilenameSymbolTable::~CUtlFilenameSymbolTable()
|
||||
{
|
||||
delete m_Strings;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pFileName -
|
||||
@ -328,7 +393,7 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileNa
|
||||
Q_strncpy( fn, pFileName, sizeof( fn ) );
|
||||
Q_RemoveDotSlashes( fn );
|
||||
#ifdef _WIN32
|
||||
Q_strlower( fn );
|
||||
strlwr( fn );
|
||||
#endif
|
||||
|
||||
// Split the filename into constituent parts
|
||||
@ -340,20 +405,18 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileNa
|
||||
// not found, lock and look again
|
||||
FileNameHandleInternal_t handle;
|
||||
m_lock.LockForWrite();
|
||||
handle.path = m_Strings->Insert( basepath ) + 1;
|
||||
handle.file = m_Strings->Insert( filename ) + 1;
|
||||
//handle.path = m_StringPool.FindStringHandle( basepath );
|
||||
//handle.file = m_StringPool.FindStringHandle( filename );
|
||||
//if ( handle.path != m_Strings.InvalidHandle() && handle.file )
|
||||
//{
|
||||
handle.SetPath( m_PathStringPool.FindStringHandle( basepath ) );
|
||||
handle.SetFile( m_FileStringPool.FindStringHandle( filename ) );
|
||||
if ( handle.GetPath() && handle.GetFile() )
|
||||
{
|
||||
// found
|
||||
// m_lock.UnlockWrite();
|
||||
// return *( FileNameHandle_t * )( &handle );
|
||||
//}
|
||||
m_lock.UnlockWrite();
|
||||
return *( FileNameHandle_t * )( &handle );
|
||||
}
|
||||
|
||||
// safely add it
|
||||
//handle.path = m_StringPool.ReferenceStringHandle( basepath );
|
||||
//handle.file = m_StringPool.ReferenceStringHandle( filename );
|
||||
handle.SetPath( m_PathStringPool.ReferenceStringHandle( basepath ) );
|
||||
handle.SetFile( m_FileStringPool.ReferenceStringHandle( filename ) );
|
||||
m_lock.UnlockWrite();
|
||||
|
||||
return *( FileNameHandle_t * )( &handle );
|
||||
@ -371,7 +434,7 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
|
||||
Q_strncpy( fn, pFileName, sizeof( fn ) );
|
||||
Q_RemoveDotSlashes( fn );
|
||||
#ifdef _WIN32
|
||||
Q_strlower( fn );
|
||||
strlwr( fn );
|
||||
#endif
|
||||
|
||||
// Split the filename into constituent parts
|
||||
@ -382,16 +445,13 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
|
||||
|
||||
FileNameHandleInternal_t handle;
|
||||
|
||||
Assert( (uint16)(m_Strings->InvalidHandle() + 1) == 0 );
|
||||
|
||||
m_lock.LockForRead();
|
||||
handle.path = m_Strings->Find(basepath) + 1;
|
||||
handle.file = m_Strings->Find(filename) + 1;
|
||||
//handle.path = m_StringPool.FindStringHandle(basepath);
|
||||
//handle.file = m_StringPool.FindStringHandle(filename);
|
||||
handle.SetPath( m_PathStringPool.FindStringHandle( basepath ) );
|
||||
handle.SetFile( m_FileStringPool.FindStringHandle( filename ) );
|
||||
m_lock.UnlockRead();
|
||||
|
||||
if ( handle.path == 0 || handle.file == 0 )
|
||||
|
||||
if ( ( handle.GetPath() == 0 ) || ( handle.GetFile() == 0 ) )
|
||||
return NULL;
|
||||
|
||||
return *( FileNameHandle_t * )( &handle );
|
||||
@ -406,17 +466,15 @@ bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf,
|
||||
{
|
||||
buf[ 0 ] = 0;
|
||||
|
||||
FileNameHandleInternal_t *internal = ( FileNameHandleInternal_t * )&handle;
|
||||
if ( !internal || !internal->file || !internal->path )
|
||||
FileNameHandleInternal_t *internalFileHandle = ( FileNameHandleInternal_t * )&handle;
|
||||
if ( !internalFileHandle )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_lock.LockForRead();
|
||||
//const char *path = m_StringPool.HandleToString(internal->path);
|
||||
//const char *fn = m_StringPool.HandleToString(internal->file);
|
||||
const char *path = (*m_Strings)[ internal->path - 1 ].Get();
|
||||
const char *fn = (*m_Strings)[ internal->file - 1].Get();
|
||||
const char *path = m_PathStringPool.HandleToString( internalFileHandle->GetPath() );
|
||||
const char *fn = m_FileStringPool.HandleToString( internalFileHandle->GetFile() );
|
||||
m_lock.UnlockRead();
|
||||
|
||||
if ( !path || !fn )
|
||||
@ -432,5 +490,34 @@ bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf,
|
||||
|
||||
void CUtlFilenameSymbolTable::RemoveAll()
|
||||
{
|
||||
m_Strings->Purge();
|
||||
m_PathStringPool.FreeAll();
|
||||
m_FileStringPool.FreeAll();
|
||||
}
|
||||
|
||||
void CUtlFilenameSymbolTable::SpewStrings()
|
||||
{
|
||||
m_lock.LockForRead();
|
||||
m_PathStringPool.SpewStrings();
|
||||
m_FileStringPool.SpewStrings();
|
||||
m_lock.UnlockRead();
|
||||
}
|
||||
|
||||
bool CUtlFilenameSymbolTable::SaveToBuffer( CUtlBuffer &buffer )
|
||||
{
|
||||
m_lock.LockForRead();
|
||||
bool bResult = m_PathStringPool.SaveToBuffer( buffer );
|
||||
bResult = bResult && m_FileStringPool.SaveToBuffer( buffer );
|
||||
m_lock.UnlockRead();
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool CUtlFilenameSymbolTable::RestoreFromBuffer( CUtlBuffer &buffer )
|
||||
{
|
||||
m_lock.LockForWrite();
|
||||
bool bResult = m_PathStringPool.RestoreFromBuffer( buffer );
|
||||
bResult = bResult && m_FileStringPool.RestoreFromBuffer( buffer );
|
||||
m_lock.UnlockWrite();
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "filesystem.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "const.h"
|
||||
#include "vprof.h"
|
||||
|
||||
#if defined( _X360 )
|
||||
#include "xbox/xbox_win32stubs.h"
|
||||
@ -869,18 +870,6 @@ void BuildGroup::PanelAdded(Panel *panel)
|
||||
_panelDar.AddToTail(temp);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Add panel the list of panels that are in the build group
|
||||
//-----------------------------------------------------------------------------
|
||||
void BuildGroup::PanelRemoved(Panel *panel)
|
||||
{
|
||||
Assert(panel);
|
||||
|
||||
PHandle temp;
|
||||
temp = panel;
|
||||
_panelDar.FindAndRemove(temp);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: loads the control settings from file
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1553,4 +1542,4 @@ void BuildGroup::ClearResFileCache()
|
||||
nIndex = m_dictCachedResFiles.Next( nIndex );
|
||||
}
|
||||
m_dictCachedResFiles.Purge();
|
||||
}
|
||||
}
|
||||
|
@ -3800,17 +3800,11 @@ void Panel::SetTall(int tall)
|
||||
|
||||
void Panel::SetBuildGroup(BuildGroup* buildGroup)
|
||||
{
|
||||
if ( _buildGroup == buildGroup )
|
||||
return;
|
||||
if ( _buildGroup.Get() )
|
||||
{
|
||||
_buildGroup->PanelRemoved( this );
|
||||
}
|
||||
_buildGroup = buildGroup;
|
||||
if ( _buildGroup.Get() )
|
||||
{
|
||||
//TODO: remove from old group
|
||||
|
||||
Assert(buildGroup != NULL);
|
||||
_buildGroup = buildGroup;
|
||||
_buildGroup->PanelAdded(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool Panel::IsBuildGroupEnabled()
|
||||
@ -5142,7 +5136,7 @@ void Panel::OnMessage(const KeyValues *params, VPANEL ifromPanel)
|
||||
{
|
||||
typedef void (Panel::*MessageFunc_HandleConstCharPtr_t)(VPANEL, VPANEL);
|
||||
VPANEL vp1 = ivgui()->HandleToPanel( param1->GetInt() );
|
||||
VPANEL vp2 = ivgui()->HandleToPanel( param1->GetInt() );
|
||||
VPANEL vp2 = ivgui()->HandleToPanel( param2->GetInt() );
|
||||
(this->*((MessageFunc_HandleConstCharPtr_t)pMap->func))( vp1, vp2 );
|
||||
}
|
||||
else
|
||||
|
@ -27,7 +27,7 @@
|
||||
class CPhysCollideVirtualMesh;
|
||||
|
||||
CTSPool< CUtlVector<CPhysCollideVirtualMesh *> > g_MeshFrameLocksPool;
|
||||
CThreadLocalPtr< CUtlVector<CPhysCollideVirtualMesh *> > g_pMeshFrameLocks;
|
||||
CTHREADLOCALPTR(CUtlVector<CPhysCollideVirtualMesh *>) g_pMeshFrameLocks;
|
||||
|
||||
// This is the surfacemanager class for IVP that implements the required functions by layering CPhysCollideVirtualMesh
|
||||
class IVP_SurfaceManager_VirtualMesh : public IVP_SurfaceManager
|
||||
|
@ -57,7 +57,7 @@ bool CPhysicsEnvironment::Save( const physsaveparams_t ¶ms )
|
||||
|
||||
if ( type >= 0 && type < PIID_NUM_TYPES )
|
||||
{
|
||||
params.pSave->WriteInt( (int *)¶ms.pObject );
|
||||
params.pSave->WriteData( (char *)¶ms.pObject, sizeof(void*) );
|
||||
return (*saveFuncs[type])( params, params.pObject );
|
||||
}
|
||||
return false;
|
||||
@ -105,7 +105,7 @@ bool CPhysicsEnvironment::Restore( const physrestoreparams_t ¶ms )
|
||||
if ( type >= 0 && type < PIID_NUM_TYPES )
|
||||
{
|
||||
void *pOldObject;
|
||||
params.pRestore->ReadInt( (int *)&pOldObject );
|
||||
params.pRestore->ReadData( (char *)&pOldObject, sizeof(void*), 0 );
|
||||
if ( (*restoreFuncs[type])( params, params.ppObject ) )
|
||||
{
|
||||
AddPtrAssociation( pOldObject, *params.ppObject );
|
||||
@ -131,11 +131,11 @@ void CPhysicsEnvironment::PostRestore()
|
||||
|
||||
void CVPhysPtrSaveRestoreOps::Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
|
||||
{
|
||||
int *pField = (int *)fieldInfo.pField;
|
||||
void *pField = (void *)fieldInfo.pField;
|
||||
int nObjects = fieldInfo.pTypeDesc->fieldSize;
|
||||
for ( int i = 0; i < nObjects; i++ )
|
||||
{
|
||||
pSave->WriteInt( pField );
|
||||
pSave->WriteData( (char*)pField, sizeof(void*) );
|
||||
++pField;
|
||||
}
|
||||
}
|
||||
@ -153,9 +153,10 @@ void CVPhysPtrSaveRestoreOps::Restore( const SaveRestoreFieldInfo_t &fieldInfo,
|
||||
{
|
||||
void **ppField = (void **)fieldInfo.pField;
|
||||
int nObjects = fieldInfo.pTypeDesc->fieldSize;
|
||||
|
||||
for ( int i = 0; i < nObjects; i++ )
|
||||
{
|
||||
pRestore->ReadInt( (int *)ppField );
|
||||
pRestore->ReadData( (char *)ppField, sizeof(void*), 0 );
|
||||
|
||||
int iNewVal = s_VPhysPtrMap.Find( *ppField );
|
||||
if ( iNewVal != s_VPhysPtrMap.InvalidIndex() )
|
||||
@ -188,10 +189,11 @@ void CVPhysPtrUtlVectorSaveRestoreOps::Save( const SaveRestoreFieldInfo_t &field
|
||||
|
||||
VPhysPtrVector *pUtlVector = (VPhysPtrVector*)fieldInfo.pField;
|
||||
int nObjects = pUtlVector->Count();
|
||||
|
||||
pSave->WriteInt( &nObjects );
|
||||
for ( int i = 0; i < nObjects; i++ )
|
||||
{
|
||||
pSave->WriteInt( &pUtlVector->Element(i) );
|
||||
pSave->WriteData( (char*)&pUtlVector->Element(i), sizeof(void*) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,7 +209,8 @@ void CVPhysPtrUtlVectorSaveRestoreOps::Restore( const SaveRestoreFieldInfo_t &fi
|
||||
for ( int i = 0; i < nObjects; i++ )
|
||||
{
|
||||
void **ppElem = (void**)(&pUtlVector->Element(i));
|
||||
pRestore->ReadInt( (int*)ppElem );
|
||||
|
||||
pRestore->ReadData( (char *)ppElem, sizeof(void*), 0 );
|
||||
|
||||
int iNewVal = s_VPhysPtrMap.Find( *ppElem );
|
||||
if ( iNewVal != s_VPhysPtrMap.InvalidIndex() )
|
||||
|
@ -585,7 +585,7 @@ private:
|
||||
CUtlVector<HCoroutine> m_VecCoroutineStack;
|
||||
};
|
||||
|
||||
CThreadLocalPtr< CCoroutineMgr > g_ThreadLocalCoroutineMgr;
|
||||
CTHREADLOCALPTR(CCoroutineMgr) g_ThreadLocalCoroutineMgr;
|
||||
|
||||
CUtlVector< CCoroutineMgr * > g_VecPCoroutineMgr;
|
||||
CThreadMutex g_ThreadMutexCoroutineMgr;
|
||||
@ -610,7 +610,7 @@ void Coroutine_ReleaseThreadMemory()
|
||||
{
|
||||
AUTO_LOCK( g_ThreadMutexCoroutineMgr );
|
||||
|
||||
if ( g_ThreadLocalCoroutineMgr != NULL )
|
||||
if ( g_ThreadLocalCoroutineMgr != static_cast<const void*>( nullptr ) )
|
||||
{
|
||||
int iCoroutineMgr = g_VecPCoroutineMgr.Find( g_ThreadLocalCoroutineMgr );
|
||||
delete g_VecPCoroutineMgr[iCoroutineMgr];
|
||||
|
@ -227,7 +227,7 @@ public:
|
||||
// and execute or execute pFunctor right after completing current job and
|
||||
// before looking for another job.
|
||||
//-----------------------------------------------------
|
||||
void ExecuteHighPriorityFunctor( CFunctor *pFunctor );
|
||||
// void ExecuteHighPriorityFunctor( CFunctor *pFunctor );
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Add an function object to the queue (master thread)
|
||||
@ -247,8 +247,6 @@ public:
|
||||
|
||||
virtual void Reserved1() {}
|
||||
|
||||
void WaitForIdle( bool bAll = true );
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
@ -418,7 +416,7 @@ private:
|
||||
CFunctor *pFunctor = NULL;
|
||||
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s PeekCall():%d", __FUNCTION__, GetCallParam() );
|
||||
|
||||
switch ( GetCallParam( &pFunctor ) )
|
||||
switch ( GetCallParam() )
|
||||
{
|
||||
case TPM_EXIT:
|
||||
Reply( true );
|
||||
@ -427,10 +425,10 @@ private:
|
||||
|
||||
case TPM_SUSPEND:
|
||||
Reply( true );
|
||||
SuspendCooperative();
|
||||
Suspend();
|
||||
break;
|
||||
|
||||
case TPM_RUNFUNCTOR:
|
||||
/* case TPM_RUNFUNCTOR:
|
||||
if( pFunctor )
|
||||
{
|
||||
( *pFunctor )();
|
||||
@ -441,7 +439,7 @@ private:
|
||||
Assert( pFunctor );
|
||||
Reply( false );
|
||||
}
|
||||
break;
|
||||
break;*/
|
||||
|
||||
default:
|
||||
AssertMsg( 0, "Unknown call to thread" );
|
||||
@ -535,7 +533,7 @@ int CThreadPool::NumIdleThreads()
|
||||
return m_nIdleThreads;
|
||||
}
|
||||
|
||||
void CThreadPool::ExecuteHighPriorityFunctor( CFunctor *pFunctor )
|
||||
/*void CThreadPool::ExecuteHighPriorityFunctor( CFunctor *pFunctor )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < m_Threads.Count(); i++ )
|
||||
@ -547,7 +545,7 @@ void CThreadPool::ExecuteHighPriorityFunctor( CFunctor *pFunctor )
|
||||
{
|
||||
m_Threads[i]->WaitForReply();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Pause/resume processing jobs
|
||||
@ -575,7 +573,10 @@ int CThreadPool::SuspendExecution()
|
||||
// here with the thread not actually suspended
|
||||
for ( i = 0; i < m_Threads.Count(); i++ )
|
||||
{
|
||||
m_Threads[i]->BWaitForThreadSuspendCooperative();
|
||||
while ( !m_Threads[i]->IsSuspended() )
|
||||
{
|
||||
ThreadSleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,7 +594,7 @@ int CThreadPool::ResumeExecution()
|
||||
{
|
||||
for ( int i = 0; i < m_Threads.Count(); i++ )
|
||||
{
|
||||
m_Threads[i]->ResumeCooperative();
|
||||
m_Threads[i]->Resume();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -601,13 +602,6 @@ int CThreadPool::ResumeExecution()
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
void CThreadPool::WaitForIdle( bool bAll )
|
||||
{
|
||||
ThreadWaitForEvents( m_IdleEvents.Count(), m_IdleEvents.Base(), bAll, 60000 );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
int CThreadPool::YieldWait( CThreadEvent **pEvents, int nEvents, bool bWaitAll, unsigned timeout )
|
||||
{
|
||||
tmZone( TELEMETRY_LEVEL0, TMZF_IDLE, "%s(%d) SPINNING %t", __FUNCTION__, timeout, tmSendCallStack( TELEMETRY_LEVEL0, 0 ) );
|
||||
@ -618,7 +612,7 @@ int CThreadPool::YieldWait( CThreadEvent **pEvents, int nEvents, bool bWaitAll,
|
||||
CJob *pJob;
|
||||
// Always wait for zero milliseconds initially, to let us process jobs on this thread.
|
||||
timeout = 0;
|
||||
while ( ( result = ThreadWaitForEvents( nEvents, pEvents, bWaitAll, timeout ) ) == WAIT_TIMEOUT )
|
||||
while ( ( result = CThreadEvent::WaitForMultiple( nEvents, pEvents, bWaitAll, timeout ) ) == TW_TIMEOUT )
|
||||
{
|
||||
if ( !m_bExecOnThreadPoolThreadsOnly && m_SharedQueue.Pop( &pJob ) )
|
||||
{
|
||||
|
13
wscript
13
wscript
@ -158,11 +158,14 @@ def define_platform(conf):
|
||||
if conf.options.SDL:
|
||||
conf.define('USE_SDL', 1)
|
||||
|
||||
if conf.options.ALLOW64:
|
||||
conf.define('PLATFORM_64BITS', 1)
|
||||
|
||||
if conf.env.DEST_OS == 'linux':
|
||||
conf.define('_GLIBCXX_USE_CXX11_ABI',0)
|
||||
conf.env.append_unique('DEFINES', [
|
||||
'LINUX=1', '_LINUX=1',
|
||||
'POSIX=1', '_POSIX=1',
|
||||
'POSIX=1', '_POSIX=1', 'PLATFORM_POSIX=1',
|
||||
'GNUC',
|
||||
'NO_HOOK_MALLOC',
|
||||
'_DLL_EXT=.so'
|
||||
@ -265,6 +268,12 @@ def configure(conf):
|
||||
'-Wuninitialized',
|
||||
'-Winit-self',
|
||||
'-Wstrict-aliasing',
|
||||
'-Wno-reorder',
|
||||
'-Wno-unknown-pragmas',
|
||||
'-Wno-unused-function',
|
||||
'-Wno-unused-but-set-variable',
|
||||
'-Wno-unused-value',
|
||||
'-Wno-unused-variable',
|
||||
'-faligned-new',
|
||||
]
|
||||
|
||||
@ -274,7 +283,7 @@ def configure(conf):
|
||||
|
||||
cflags, linkflags = conf.get_optimization_flags()
|
||||
|
||||
flags = ['-fPIC', '-pipe'] #, '-fsanitize=undefined', '-fno-sanitize=vptr'] #, '-fno-sanitize=vptr,shift,shift-exponent,shift-base,signed-integer-overflow']
|
||||
flags = ['-pipe', '-fPIC'] #, '-fsanitize=undefined'] #, '-fsanitize=undefined'] #, '-fno-sanitize=vptr'] #, '-fno-sanitize=vptr,shift,shift-exponent,shift-base,signed-integer-overflow']
|
||||
if conf.env.COMPILER_CC != 'msvc':
|
||||
flags += ['-pthread']
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user