aboutsummaryrefslogtreecommitdiff
path: root/mp/src/public/tier1/utlhandletable.h
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /mp/src/public/tier1/utlhandletable.h
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/public/tier1/utlhandletable.h')
-rw-r--r--mp/src/public/tier1/utlhandletable.h586
1 files changed, 586 insertions, 0 deletions
diff --git a/mp/src/public/tier1/utlhandletable.h b/mp/src/public/tier1/utlhandletable.h
new file mode 100644
index 00000000..5d9c46fc
--- /dev/null
+++ b/mp/src/public/tier1/utlhandletable.h
@@ -0,0 +1,586 @@
+//========= Copyright 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;
+ T *GetHandle( UtlHandle_t h, bool checkValidity ) const;
+
+ // Is a handle valid?
+ bool IsHandleValid( UtlHandle_t h ) const;
+
+ // Iterate over handles; they may not be valid
+ unsigned int GetValidHandleCount() const;
+ unsigned int GetHandleCount() const;
+ UtlHandle_t GetHandleFromIndex( int i ) const;
+ int GetIndexFromHandle( UtlHandle_t h ) 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 )
+ {
+ Assert( i < ( 1 << HandleBits ) );
+ Assert( s < ( 1 << ( 31 - HandleBits ) ) );
+ }
+ 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;
+
+ unsigned int m_nValidHandles;
+ CUtlVector< EntryType_t > m_list;
+ CUtlQueue< int > m_unused;
+};
+
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+template< class T, int HandleBits >
+CUtlHandleTable<T, HandleBits>::CUtlHandleTable() : m_nValidHandles( 0 )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// 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;
+
+ ++m_nValidHandles;
+
+ 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
+ if ( !entry.nInvalid )
+ {
+ entry.nInvalid = 1;
+ --m_nValidHandles;
+ }
+ entry.m_pData = NULL;
+
+
+ // If a handle has been used this many times, then we need to take it out of service, otherwise if the
+ // serial # wraps around we'll possibly revalidate old handles and they'll start to point at the wrong objects. Unlikely, but possible.
+ bool bStopUsing = ( entry.m_nSerial >= ( (1 << ( 31 - HandleBits ) ) - 1 ) );
+ if ( !bStopUsing )
+ {
+ m_unused.Insert( nIndex );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// 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
+ if ( entry->nInvalid )
+ {
+ ++m_nValidHandles;
+ 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;
+}
+
+template< class T, int HandleBits >
+T *CUtlHandleTable<T, HandleBits>::GetHandle( UtlHandle_t handle, bool checkValidity ) const
+{
+ const EntryType_t *entry = GetEntry( handle, checkValidity );
+ 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 );
+ AssertOnce( 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>::GetValidHandleCount() const
+{
+ return m_nValidHandles;
+}
+
+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;
+}
+
+template< class T, int HandleBits >
+int CUtlHandleTable<T, HandleBits>::GetIndexFromHandle( UtlHandle_t h ) const
+{
+ if ( h == UTLHANDLE_INVALID )
+ return -1;
+
+ return GetListIndex( h );
+}
+
+
+
+//-----------------------------------------------------------------------------
+// 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 NULL;
+
+ 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;
+
+ if ( !entry.nInvalid )
+ {
+ --m_nValidHandles;
+ 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;
+
+ if ( entry.nInvalid )
+ {
+ ++m_nValidHandles;
+ 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
+