//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= // // Purpose: // //============================================================================= #ifndef UTLHANDLETABLE_H #define UTLHANDLETABLE_H #ifdef _WIN32 #pragma once #endif #include "tier1/utlvector.h" #include "tier1/utlqueue.h" //----------------------------------------------------------------------------- // Handles are 32 bits. Invalid handles are all 1s //----------------------------------------------------------------------------- typedef unsigned int UtlHandle_t; #define UTLHANDLE_INVALID ((UtlHandle_t)~0) //----------------------------------------------------------------------------- // Purpose: This is a table used to allocate handles // HandleBits specifies the max # of simultaneously allocated handles. // An extra bit is used for the validity state // The rest of the 32 bits are used for a serial number //----------------------------------------------------------------------------- template< class T, int HandleBits > class CUtlHandleTable { public: CUtlHandleTable(); // Allocate, deallocate handles UtlHandle_t AddHandle(); void RemoveHandle( UtlHandle_t h ); // Set/get handle values void SetHandle( UtlHandle_t h, T *pData ); T *GetHandle( UtlHandle_t h ) const; // Is a handle valid? bool IsHandleValid( UtlHandle_t h ) const; // Iterate over handles; they may not be valid unsigned int GetHandleCount() const; UtlHandle_t GetHandleFromIndex( int i ) const; void MarkHandleInvalid( UtlHandle_t h ); void MarkHandleValid( UtlHandle_t h ); private: struct HandleType_t { HandleType_t( unsigned int i, unsigned int s ) : nIndex( i ), nSerial( s ) {} unsigned int nIndex : HandleBits; unsigned int nSerial : 31 - HandleBits; }; struct EntryType_t { EntryType_t() : m_nSerial( 0 ), nInvalid( 0 ), m_pData( 0 ) {} unsigned int m_nSerial : 31; unsigned int nInvalid : 1; T *m_pData; }; static unsigned int GetSerialNumber( UtlHandle_t handle ); static unsigned int GetListIndex( UtlHandle_t handle ); static UtlHandle_t CreateHandle( unsigned int nSerial, unsigned int nIndex ); const EntryType_t *GetEntry( UtlHandle_t handle, bool checkValidity ) const; CUtlVector< EntryType_t > m_list; CUtlQueue< int > m_unused; }; //----------------------------------------------------------------------------- // Constructor, destructor //----------------------------------------------------------------------------- template< class T, int HandleBits > CUtlHandleTable<T, HandleBits>::CUtlHandleTable() { } //----------------------------------------------------------------------------- // Allocate, deallocate handles //----------------------------------------------------------------------------- template< class T, int HandleBits > UtlHandle_t CUtlHandleTable<T, HandleBits>::AddHandle() { unsigned int nIndex = ( m_unused.Count() > 0 ) ? m_unused.RemoveAtHead() : m_list.AddToTail(); EntryType_t &entry = m_list[ nIndex ]; entry.nInvalid = 0; entry.m_pData = NULL; return CreateHandle( entry.m_nSerial, nIndex ); } template< class T, int HandleBits > void CUtlHandleTable<T, HandleBits>::RemoveHandle( UtlHandle_t handle ) { unsigned int nIndex = GetListIndex( handle ); Assert( nIndex < ( unsigned int )m_list.Count() ); if ( nIndex >= ( unsigned int )m_list.Count() ) return; EntryType_t &entry = m_list[ nIndex ]; ++entry.m_nSerial; // mark old serial# invalid m_unused.Insert( nIndex ); // AddToTail } //----------------------------------------------------------------------------- // Set/get handle values //----------------------------------------------------------------------------- template< class T, int HandleBits > void CUtlHandleTable<T, HandleBits>::SetHandle( UtlHandle_t handle, T *pData ) { EntryType_t *entry = const_cast< EntryType_t* >( GetEntry( handle, false ) ); Assert( entry ); if ( entry == NULL ) return; // Validate the handle entry->nInvalid = 0; entry->m_pData = pData; } template< class T, int HandleBits > T *CUtlHandleTable<T, HandleBits>::GetHandle( UtlHandle_t handle ) const { const EntryType_t *entry = GetEntry( handle, true ); return entry ? entry->m_pData : NULL; } //----------------------------------------------------------------------------- // Is a handle valid? //----------------------------------------------------------------------------- template< class T, int HandleBits > bool CUtlHandleTable<T, HandleBits>::IsHandleValid( UtlHandle_t handle ) const { if ( handle == UTLHANDLE_INVALID ) return false; unsigned int nIndex = GetListIndex( handle ); Assert( nIndex < ( unsigned int )m_list.Count() ); if ( nIndex >= ( unsigned int )m_list.Count() ) return false; const EntryType_t &entry = m_list[ nIndex ]; if ( entry.m_nSerial != GetSerialNumber( handle ) ) return false; if ( 1 == entry.nInvalid ) return false; return true; } //----------------------------------------------------------------------------- // Current max handle //----------------------------------------------------------------------------- template< class T, int HandleBits > unsigned int CUtlHandleTable<T, HandleBits>::GetHandleCount() const { return m_list.Count(); } template< class T, int HandleBits > UtlHandle_t CUtlHandleTable<T, HandleBits>::GetHandleFromIndex( int i ) const { if ( m_list[i].m_pData ) return CreateHandle( m_list[i].m_nSerial, i ); return UTLHANDLE_INVALID; } //----------------------------------------------------------------------------- // Cracking handles into indices + serial numbers //----------------------------------------------------------------------------- template< class T, int HandleBits > unsigned int CUtlHandleTable<T, HandleBits>::GetSerialNumber( UtlHandle_t handle ) { return ( ( HandleType_t* )&handle )->nSerial; } template< class T, int HandleBits > unsigned int CUtlHandleTable<T, HandleBits>::GetListIndex( UtlHandle_t handle ) { return ( ( HandleType_t* )&handle )->nIndex; } template< class T, int HandleBits > UtlHandle_t CUtlHandleTable<T, HandleBits>::CreateHandle( unsigned int nSerial, unsigned int nIndex ) { HandleType_t h( nIndex, nSerial ); return *( UtlHandle_t* )&h; } //----------------------------------------------------------------------------- // Looks up a entry by handle //----------------------------------------------------------------------------- template< class T, int HandleBits > const typename CUtlHandleTable<T, HandleBits>::EntryType_t *CUtlHandleTable<T, HandleBits>::GetEntry( UtlHandle_t handle, bool checkValidity ) const { if ( handle == UTLHANDLE_INVALID ) return NULL; unsigned int nIndex = GetListIndex( handle ); Assert( nIndex < ( unsigned int )m_list.Count() ); if ( nIndex >= ( unsigned int )m_list.Count() ) return NULL; const EntryType_t &entry = m_list[ nIndex ]; if ( entry.m_nSerial != GetSerialNumber( handle ) ) return NULL; if ( checkValidity && ( 1 == entry.nInvalid ) ) return false; return &entry; } template< class T, int HandleBits > void CUtlHandleTable<T, HandleBits>::MarkHandleInvalid( UtlHandle_t handle ) { if ( handle == UTLHANDLE_INVALID ) return; unsigned int nIndex = GetListIndex( handle ); Assert( nIndex < ( unsigned int )m_list.Count() ); if ( nIndex >= ( unsigned int )m_list.Count() ) return; EntryType_t &entry = m_list[ nIndex ]; if ( entry.m_nSerial != GetSerialNumber( handle ) ) return; entry.nInvalid = 1; } template< class T, int HandleBits > void CUtlHandleTable<T, HandleBits>::MarkHandleValid( UtlHandle_t handle ) { if ( handle == UTLHANDLE_INVALID ) return; unsigned int nIndex = GetListIndex( handle ); Assert( nIndex < ( unsigned int )m_list.Count() ); if ( nIndex >= ( unsigned int )m_list.Count() ) return; EntryType_t &entry = m_list[ nIndex ]; if ( entry.m_nSerial != GetSerialNumber( handle ) ) return; entry.nInvalid = 0; } //----------------------------------------------------------------------------- // Handle wrapper. Assumes 2 things // 1) That class T has a non-static method called GetHandle which returns a UtlHandle_t // 2) That class T has a static method called GetPtrFromHandle which returns a T* given a UtlHandle_t // 3) That class T has a static method called IsHandleValid which accepts a UtlHandle_t //----------------------------------------------------------------------------- template< class T > class CUtlHandle { public: // Constructors CUtlHandle(); explicit CUtlHandle( T *pObject ); CUtlHandle( UtlHandle_t h ); CUtlHandle( const CUtlHandle<T> &h ); // Assignment void Set( T *pObject ); void Set( UtlHandle_t h ); const CUtlHandle<T> &operator=( UtlHandle_t h ); const CUtlHandle<T> &operator=( T *pObject ); // Retrieval T *Get(); const T* Get() const; // Is the handle valid? bool IsValid() const; // Casting operator T*(); operator UtlHandle_t(); operator bool(); T* operator->(); const T* operator->() const; // Equality bool operator==( CUtlHandle<T> h ) const; bool operator==( T *pObject ) const; bool operator==( UtlHandle_t h ) const; bool operator!=( CUtlHandle<T> h ) const; bool operator!=( T *pObject ) const; bool operator!=( UtlHandle_t h ) const; private: UtlHandle_t m_handle; }; //----------------------------------------------------------------------------- // Constructors //----------------------------------------------------------------------------- template< class T > CUtlHandle<T>::CUtlHandle() : m_handle( UTLHANDLE_INVALID ) { } template< class T > CUtlHandle<T>::CUtlHandle( T *pObject ) { Set( pObject ); } template< class T > CUtlHandle<T>::CUtlHandle( UtlHandle_t h ) { m_handle = h; } template< class T > CUtlHandle<T>::CUtlHandle( const CUtlHandle<T> &h ) { m_handle = h.m_handle; } //----------------------------------------------------------------------------- // Assignment //----------------------------------------------------------------------------- template< class T > void CUtlHandle<T>::Set( T *pObject ) { // Assumes T has a member function GetHandle m_handle = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID; } template< class T > void CUtlHandle<T>::Set( UtlHandle_t h ) { m_handle = h; } template< class T > const CUtlHandle<T> &CUtlHandle<T>::operator=( UtlHandle_t h ) { Set( h ); return *this; } template< class T > const CUtlHandle<T> &CUtlHandle<T>::operator=( T *pObject ) { Set( pObject ); return *this; } //----------------------------------------------------------------------------- // Is the handle valid? //----------------------------------------------------------------------------- template< class T > bool CUtlHandle<T>::IsValid() const { // Assumes T has a static member function IsHandleValid return T::IsHandleValid( m_handle ); } //----------------------------------------------------------------------------- // Retrieval //----------------------------------------------------------------------------- template< class T > T *CUtlHandle<T>::Get() { // Assumes T has a static member function GetPtrFromHandle return T::GetPtrFromHandle( m_handle ); } template< class T > const T* CUtlHandle<T>::Get() const { // Assumes T has a static member function GetPtrFromHandle return T::GetPtrFromHandle( m_handle ); } //----------------------------------------------------------------------------- // Casting //----------------------------------------------------------------------------- template< class T > CUtlHandle<T>::operator T*() { return Get(); } template< class T > CUtlHandle<T>::operator UtlHandle_t() { return m_handle; } template< class T > T* CUtlHandle<T>::operator->() { return Get(); } template< class T > const T* CUtlHandle<T>::operator->() const { return Get(); } template< class T > CUtlHandle<T>::operator bool() { return m_handle != UTLHANDLE_INVALID; } //----------------------------------------------------------------------------- // Equality //----------------------------------------------------------------------------- template< class T > bool CUtlHandle<T>::operator==( CUtlHandle<T> h ) const { return m_handle == h.m_handle; } template< class T > bool CUtlHandle<T>::operator==( T *pObject ) const { UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID; return m_handle == h; } template< class T > bool CUtlHandle<T>::operator==( UtlHandle_t h ) const { return m_handle == h; } template< class T > bool CUtlHandle<T>::operator!=( CUtlHandle<T> h ) const { return m_handle != h.m_handle; } template< class T > bool CUtlHandle<T>::operator!=( T *pObject ) const { UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID; return m_handle != h; } template< class T > bool CUtlHandle<T>::operator!=( UtlHandle_t h ) const { return m_handle != h; } //----------------------------------------------------------------------------- // Add this macro to a class definition to hook in handles for it! //----------------------------------------------------------------------------- #define DECLARE_HANDLES( _className, _handleBitCount ) \ public: \ UtlHandle_t GetHandle() \ { \ return m_Handle; \ } \ static _className* GetPtrFromHandle( UtlHandle_t h ) \ { \ return m_HandleTable.GetHandle( h ); \ } \ static bool IsHandleValid( UtlHandle_t h ) \ { \ return m_HandleTable.IsHandleValid( h ); \ } \ private: \ UtlHandle_t m_Handle; \ static CUtlHandleTable< _className, _handleBitCount > m_HandleTable //----------------------------------------------------------------------------- // Add this macro to a .cpp file to hook in handles for it! //----------------------------------------------------------------------------- #define IMPLEMENT_HANDLES( _className, _handleBitCount ) \ CUtlHandleTable< _className, _handleBitCount > _className::m_HandleTable; //----------------------------------------------------------------------------- // Add these macro to the class constructor + destructor //----------------------------------------------------------------------------- #define CONSTRUCT_HANDLE( ) \ m_Handle = m_HandleTable.AddHandle(); \ m_HandleTable.SetHandle( m_Handle, this ) #define DESTRUCT_HANDLE() \ m_HandleTable.RemoveHandle( m_Handle ); \ m_Handle = UTLHANDLE_INVALID #endif // UTLHANDLETABLE_H
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 5821 | Knut Wikstrom |
Added Valve Source code. This is NOT to be commited to other than new code from Valve. |