mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-11 11:19:09 +00:00
1
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Base class for objects that are kept in synch between client and server
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef SHAREDOBJECT_H
|
||||
#define SHAREDOBJECT_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// ENABLE_SO_OVERWRITE_PARANOIA can be set to either 0 or 1. If enabled, it will add
|
||||
// extra fields to every CSharedObject instance to try and detect overwrites at the
|
||||
// cost of additional runtime memory.
|
||||
#define ENABLE_SO_OVERWRITE_PARANOIA 0
|
||||
|
||||
// ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA can be set to either 0 or 1. If enabled, it
|
||||
// will add extra fields to every CSharedObject instance to try and detect issues with
|
||||
// constructions/destruction (ie., double-deletes, etc.), including reference counting.
|
||||
#define ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA (defined( STAGING_ONLY ))
|
||||
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
namespace GCSDK
|
||||
{
|
||||
|
||||
class CSQLAccess;
|
||||
class CSharedObject;
|
||||
typedef CSharedObject *(*SOCreationFunc_t)( );
|
||||
class CSharedObjectCache;
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Purpose: Abstract base class for objects that are shared between the GC and
|
||||
// a gameserver/client. These can also be stored in the database.
|
||||
//----------------------------------------------------------------------------
|
||||
class CSharedObject
|
||||
{
|
||||
friend class CGCSharedObjectCache;
|
||||
friend class CSharedObjectCache;
|
||||
public:
|
||||
|
||||
#ifdef GC
|
||||
virtual ~CSharedObject()
|
||||
{
|
||||
#if ENABLE_SO_OVERWRITE_PARANOIA
|
||||
m_pThis = NULL;
|
||||
#endif // ENABLE_SO_OVERWRITE_PARANOIA
|
||||
|
||||
#if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
AssertMsg2( m_nRefCount == 0, "Deleting shared object type %d with refcount %d", m_nSOTypeID, m_nRefCount );
|
||||
|
||||
m_nSOTypeID = -1;
|
||||
m_nRefCount = -1;
|
||||
#endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
}
|
||||
|
||||
#if ENABLE_SO_OVERWRITE_PARANOIA
|
||||
CSharedObject *m_pThis;
|
||||
#endif // ENABLE_SO_OVERWRITE_PARANOIA
|
||||
|
||||
#if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
int m_nRefCount;
|
||||
mutable int m_nSOTypeID;
|
||||
#endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
|
||||
void Check() const
|
||||
{
|
||||
#if ENABLE_SO_OVERWRITE_PARANOIA
|
||||
Assert( m_pThis == this );
|
||||
#endif // ENABLE_SO_OVERWRITE_PARANOIA
|
||||
|
||||
#if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
Assert( m_nRefCount >= 0 );
|
||||
|
||||
if ( m_nSOTypeID == kSharedObject_UnassignedType )
|
||||
{
|
||||
m_nSOTypeID = GetTypeID();
|
||||
}
|
||||
|
||||
Assert( m_nSOTypeID >= 0 );
|
||||
#endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
}
|
||||
#else
|
||||
virtual ~CSharedObject() {}
|
||||
#endif
|
||||
|
||||
virtual int GetTypeID() const = 0;
|
||||
virtual bool BParseFromMessage( const CUtlBuffer & buffer ) = 0;
|
||||
virtual bool BParseFromMessage( const std::string &buffer ) = 0;
|
||||
virtual bool BUpdateFromNetwork( const CSharedObject & objUpdate ) = 0;
|
||||
virtual bool BIsKeyLess( const CSharedObject & soRHS ) const = 0;
|
||||
virtual void Copy( const CSharedObject & soRHS ) = 0;
|
||||
virtual void Dump() const = 0;
|
||||
virtual bool BShouldDeleteByCache() const { return true; }
|
||||
virtual CUtlString GetDebugString() const { return PchClassName( GetTypeID() ); };
|
||||
|
||||
bool BIsKeyEqual( const CSharedObject & soRHS ) const;
|
||||
|
||||
static void RegisterFactory( int nTypeID, SOCreationFunc_t fnFactory, uint32 unFlags, const char *pchClassName );
|
||||
static CSharedObject *Create( int nTypeID );
|
||||
static uint32 GetTypeFlags( int nTypeID );
|
||||
static const char *PchClassName( int nTypeID );
|
||||
static const char *PchClassBuildCacheNodeName( int nTypeID );
|
||||
static const char *PchClassCreateNodeName( int nTypeID );
|
||||
static const char *PchClassUpdateNodeName( int nTypeID );
|
||||
|
||||
#ifdef GC
|
||||
virtual bool BIsNetworked() const { return true; }
|
||||
virtual bool BIsDatabaseBacked() const { return true; }
|
||||
virtual bool BYieldingAddToDatabase();
|
||||
virtual bool BYieldingWriteToDatabase( const CUtlVector< int > &fields );
|
||||
virtual bool BYieldingRemoveFromDatabase();
|
||||
|
||||
virtual bool BYieldingAddInsertToTransaction( CSQLAccess & sqlAccess ) { return false; }
|
||||
virtual bool BYieldingAddWriteToTransaction( CSQLAccess & sqlAccess, const CUtlVector< int > &fields ) { return false; }
|
||||
virtual bool BYieldingAddRemoveToTransaction( CSQLAccess & sqlAccess ) { return false; }
|
||||
|
||||
virtual bool BAddToMessage( CUtlBuffer & bufOutput ) const = 0;
|
||||
virtual bool BAddToMessage( std::string *pBuffer ) const = 0;
|
||||
virtual bool BAddDestroyToMessage( CUtlBuffer & bufDestroy ) const = 0;
|
||||
virtual bool BAddDestroyToMessage( std::string *pBuffer ) const = 0;
|
||||
|
||||
virtual bool BParseFromMemcached( CUtlBuffer & buffer ) { return false; }
|
||||
virtual bool BAddToMemcached( CUtlBuffer & bufOutput ) const { return false; }
|
||||
|
||||
bool BSendCreateToSteamID( const CSteamID & steamID, const CSteamID & ownerID, uint64 ulVersion ) const;
|
||||
bool BSendDestroyToSteamID( const CSteamID & steamID, const CSteamID & ownerID, uint64 ulVersion ) const;
|
||||
|
||||
#ifdef DBGFLAG_VALIDATE
|
||||
virtual void Validate( CValidator &validator, const char *pchName );
|
||||
static void ValidateStatics( CValidator & validator );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/*
|
||||
// Dirty bit modification. Do not call these directly on SharedObjects. Call them
|
||||
// on the cache that owns the object so they can be added/removed from the right lists.
|
||||
virtual void DirtyField( int nField ) = 0;
|
||||
virtual void MakeDatabaseClean() = 0;
|
||||
virtual void MakeNetworkClean() = 0;
|
||||
*/
|
||||
#endif // GC
|
||||
|
||||
#ifdef GC
|
||||
CSharedObject()
|
||||
{
|
||||
#if ENABLE_SO_OVERWRITE_PARANOIA
|
||||
m_pThis = this;
|
||||
#endif // ENABLE_SO_OVERWRITE_PARANOIA
|
||||
|
||||
#if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
m_nRefCount = 0;
|
||||
m_nSOTypeID = kSharedObject_UnassignedType;
|
||||
#endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
enum { kSharedObject_UnassignedType = -999 };
|
||||
#endif // ENABLE_SO_CONSTRUCT_DESTRUCT_PARANOIA
|
||||
|
||||
struct SharedObjectInfo_t
|
||||
{
|
||||
SOCreationFunc_t m_pFactoryFunction;
|
||||
uint32 m_unFlags;
|
||||
const char *m_pchClassName;
|
||||
CUtlString m_sBuildCacheSubNodeName;
|
||||
CUtlString m_sUpdateNodeName;
|
||||
CUtlString m_sCreateNodeName;
|
||||
};
|
||||
static CUtlMap<int, SharedObjectInfo_t> sm_mapFactories;
|
||||
|
||||
public:
|
||||
static const CUtlMap<int, SharedObjectInfo_t> & GetFactories() { return sm_mapFactories; }
|
||||
};
|
||||
|
||||
typedef CUtlVectorFixedGrowable<CSharedObject *, 1> CSharedObjectVec;
|
||||
|
||||
#ifdef GC
|
||||
|
||||
//this class manages the stats for the shared objects, such as how many exist, how many have been sent, how many have been created, how many destroyed
|
||||
class CSharedObjectStats
|
||||
{
|
||||
public:
|
||||
|
||||
CSharedObjectStats();
|
||||
|
||||
//called to register a shared object class given a type ID and name. This will return false if
|
||||
//a type of this ID is already registered
|
||||
void RegisterSharedObjectType( int nTypeID, const char* pszTypeName );
|
||||
|
||||
//called to track when a shared object is created/destroyed to update the running total
|
||||
void TrackSharedObjectLifetime( int nTypeID, int32 nCount );
|
||||
|
||||
//called when a shared object is created to track its creation
|
||||
void TrackSharedObjectSendCreate( int nTypeID, uint32 nCount );
|
||||
//called when a shared object is destroyed to track counts
|
||||
void TrackSharedObjectSendDestroy( int nTypeID, uint32 nCount );
|
||||
|
||||
//tracks a new subscription
|
||||
void TrackSubscription( int nTypeID, uint32 nFlags, uint32 nNumSubscriptions );
|
||||
|
||||
//called when a shared object is sent
|
||||
void TrackSharedObjectSend( int nTypeID, uint32 nNumClients, uint32 nMsgSize );
|
||||
|
||||
//reset the stats for all the caches
|
||||
void ResetStats();
|
||||
|
||||
//called to start/stop collecting stats
|
||||
void StartCollectingStats();
|
||||
void StopCollectingStats();
|
||||
bool IsCollectingStats() const { return m_bCollectingStats; }
|
||||
|
||||
//called to report the currently collected stats
|
||||
void ReportCollectedStats() const;
|
||||
|
||||
private:
|
||||
|
||||
struct SOStats_t
|
||||
{
|
||||
SOStats_t();
|
||||
void ResetStats();
|
||||
|
||||
//the text name of this cache
|
||||
CUtlString m_sName;
|
||||
//the number of outstanding SO cache objects of this type. This is not cleared
|
||||
uint32 m_nNumActive;
|
||||
//the type ID of this stat
|
||||
int m_nTypeID;
|
||||
|
||||
//the total number that have been created/destroyed. Active is difference between these
|
||||
uint32 m_nNumCreated;
|
||||
uint32 m_nNumDestroyed;
|
||||
//how many bytes we have sent (raw, and multiplexed to multiple subscribers)
|
||||
uint64 m_nRawBytesSent;
|
||||
uint64 m_nMultiplexedBytesSent;
|
||||
//the number of sends since our last clear
|
||||
uint32 m_nNumSends;
|
||||
//how many subscriptions we have gotten by various subscription types
|
||||
uint32 m_nNumSubOwner;
|
||||
uint32 m_nNumSubOtherUsers;
|
||||
uint32 m_nNumSubGameServer;
|
||||
};
|
||||
|
||||
//sort function that controls the order that the SO stats are presented in the report
|
||||
static bool SortSOStatsSent( const SOStats_t* pLhs, const SOStats_t* pRhs );
|
||||
static bool SortSOStatsSubscribe( const SOStats_t* pLhs, const SOStats_t* pRhs );
|
||||
|
||||
//to compact the memory space for wide ranging type IDs, the list of stats has two components, an array that can be looked up
|
||||
//via the type ID which maps to a stat index (or invalid index if no mapping is registered)
|
||||
static const uint16 knInvalidIndex = ( uint16 )-1;
|
||||
CUtlVector< uint16 > m_vTypeToIndex;
|
||||
CUtlVector< SOStats_t > m_Stats;
|
||||
|
||||
//are we currently collecting stats or not?
|
||||
bool m_bCollectingStats;
|
||||
//the time that we've been collecting
|
||||
CJobTime m_CollectTime;
|
||||
uint64 m_nMicroSElapsed;
|
||||
};
|
||||
|
||||
//global stat tracker
|
||||
extern CSharedObjectStats g_SharedObjectStats;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Purpose: Templatized function to use as a factory method for
|
||||
// CSharedObject subclasses
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename SharedObjectSubclass_t>
|
||||
CSharedObject *CreateSharedObjectSubclass()
|
||||
{
|
||||
return new SharedObjectSubclass_t();
|
||||
}
|
||||
|
||||
// Version that always asserts and returns NULL, for SOs that should not be auto-created this way
|
||||
template<int nSharedObjectType>
|
||||
CSharedObject *CreateSharedObjectSubclassProhibited()
|
||||
{
|
||||
AssertMsg( false, "Attempting to auto-create object of type %d which does not allow SO-based creation", nSharedObjectType );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef GC
|
||||
#define REG_SHARED_OBJECT_SUBCLASS( derivedClass, flags ) GCSDK::CSharedObject::RegisterFactory( derivedClass::k_nTypeID, GCSDK::CreateSharedObjectSubclass<derivedClass>, (flags), #derivedClass )
|
||||
// GC only -- sharedobjects that cannot be auto-created by the SO code, and might not have a specific derived class that
|
||||
// publicly implements the interface
|
||||
#define REG_SHARED_OBJECT_SUBCLASS_BY_ID_NOCREATE( strName, nTypeID, flags ) \
|
||||
GCSDK::CSharedObject::RegisterFactory( nTypeID, CreateSharedObjectSubclassProhibited<nTypeID>, (flags), strName )
|
||||
#else
|
||||
#define REG_SHARED_OBJECT_SUBCLASS( derivedClass ) GCSDK::CSharedObject::RegisterFactory( derivedClass::k_nTypeID, GCSDK::CreateSharedObjectSubclass<derivedClass>, 0, #derivedClass )
|
||||
#endif
|
||||
|
||||
} // namespace GCSDK
|
||||
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
#endif //SHAREDOBJECT_H
|
||||
Reference in New Issue
Block a user