amd64: fix multithread, fix vgui, fix physmodels

This commit is contained in:
nillerusr 2022-06-05 01:44:42 +03:00
parent 01413fdd71
commit 9ee21ecf90
63 changed files with 5679 additions and 2468 deletions

View File

@ -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" );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

View File

@ -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 ) )

View File

@ -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;
}

View File

@ -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, ... );

View File

@ -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;
}
};

View File

@ -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"

View File

@ -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 );

View File

@ -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

View File

@ -797,7 +797,7 @@ void Sys_ShutdownAuthentication( void )
//-----------------------------------------------------------------------------
// Debug library spew output
//-----------------------------------------------------------------------------
CThreadLocalInt<> g_bInSpew;
CTHREADLOCALINT g_bInSpew;
#include "tier1/fmtstr.h"

View File

@ -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;
}
}

View File

@ -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"

View File

@ -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?

View File

@ -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 );

View File

@ -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
//-----------------------------------------------------------------------------

View File

@ -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 );
// -----------------------

View File

@ -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

View File

@ -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 );

View File

@ -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
}
};

View File

@ -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;
}
};

View File

@ -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 )
{

View File

@ -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 );

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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:

View File

@ -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()

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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.

View File

@ -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

View File

@ -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++ )

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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;

View File

@ -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

View File

@ -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() );

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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" )
{

View File

@ -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 != &copyFrom)
{
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;
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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

View File

@ -57,7 +57,7 @@ bool CPhysicsEnvironment::Save( const physsaveparams_t &params )
if ( type >= 0 && type < PIID_NUM_TYPES )
{
params.pSave->WriteInt( (int *)&params.pObject );
params.pSave->WriteData( (char *)&params.pObject, sizeof(void*) );
return (*saveFuncs[type])( params, params.pObject );
}
return false;
@ -105,7 +105,7 @@ bool CPhysicsEnvironment::Restore( const physrestoreparams_t &params )
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() )

View File

@ -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];

View File

@ -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
View File

@ -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']