mirror of
https://github.com/0TheSpy/Seaside.git
synced 2025-01-07 10:03:29 +08:00
500 lines
11 KiB
C++
500 lines
11 KiB
C++
#ifndef UTLHANDLETABLE_H
|
|
#define UTLHANDLETABLE_H
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
|
|
#include "utlvector.h"
|
|
#include "utlqueue.h"
|
|
|
|
|
|
typedef unsigned int UtlHandle_t;
|
|
#define UTLHANDLE_INVALID ((UtlHandle_t)~0)
|
|
|
|
|
|
template< class T, int HandleBits >
|
|
class CUtlHandleTable
|
|
{
|
|
public:
|
|
CUtlHandleTable();
|
|
|
|
UtlHandle_t AddHandle();
|
|
void RemoveHandle(UtlHandle_t h);
|
|
|
|
void SetHandle(UtlHandle_t h, T* pData);
|
|
T* GetHandle(UtlHandle_t h) const;
|
|
T* GetHandle(UtlHandle_t h, bool checkValidity) const;
|
|
|
|
bool IsHandleValid(UtlHandle_t h) const;
|
|
|
|
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;
|
|
};
|
|
|
|
|
|
template< class T, int HandleBits >
|
|
CUtlHandleTable<T, HandleBits>::CUtlHandleTable() : m_nValidHandles(0)
|
|
{
|
|
}
|
|
|
|
|
|
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;
|
|
if (!entry.nInvalid)
|
|
{
|
|
entry.nInvalid = 1;
|
|
--m_nValidHandles;
|
|
}
|
|
entry.m_pData = NULL;
|
|
|
|
|
|
bool bStopUsing = (entry.m_nSerial >= ((1 << (31 - HandleBits)) - 1));
|
|
if (!bStopUsing)
|
|
{
|
|
m_unused.Insert(nIndex);
|
|
}
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
template< class T >
|
|
class CUtlHandle
|
|
{
|
|
public:
|
|
CUtlHandle();
|
|
explicit CUtlHandle(T* pObject);
|
|
CUtlHandle(UtlHandle_t h);
|
|
CUtlHandle(const CUtlHandle<T>& h);
|
|
|
|
void Set(T* pObject);
|
|
void Set(UtlHandle_t h);
|
|
const CUtlHandle<T>& operator=(UtlHandle_t h);
|
|
const CUtlHandle<T>& operator=(T* pObject);
|
|
|
|
T* Get();
|
|
const T* Get() const;
|
|
|
|
bool IsValid() const;
|
|
|
|
operator T* ();
|
|
operator UtlHandle_t();
|
|
operator bool();
|
|
T* operator->();
|
|
const T* operator->() const;
|
|
|
|
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;
|
|
};
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
template< class T >
|
|
void CUtlHandle<T>::Set(T* pObject)
|
|
{
|
|
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;
|
|
}
|
|
|
|
|
|
template< class T >
|
|
bool CUtlHandle<T>::IsValid() const
|
|
{
|
|
return T::IsHandleValid(m_handle);
|
|
}
|
|
|
|
|
|
template< class T >
|
|
T* CUtlHandle<T>::Get()
|
|
{
|
|
return T::GetPtrFromHandle(m_handle);
|
|
}
|
|
|
|
template< class T >
|
|
const T* CUtlHandle<T>::Get() const
|
|
{
|
|
return T::GetPtrFromHandle(m_handle);
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
#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
|
|
|
|
|
|
#define IMPLEMENT_HANDLES( _className, _handleBitCount ) \
|
|
CUtlHandleTable< _className, _handleBitCount > _className::m_HandleTable;
|
|
|
|
|
|
#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
|