/*++ Copyright (c) 1998-1999 Microsoft Corporation Module Name: hash.h Abstract: Declaration of the CHashTable class Author: mquinton 04-28-98 Notes: Revision History: --*/ #ifndef __HASH_H__ #define __HASH_H__ typedef struct _TABLEENTRY { ULONG_PTR HashKey; ULONG_PTR Element; CTAPI * pTapiObj; } TABLEENTRY; typedef struct _TABLEHEADER { DWORD dwUsedElements; TABLEENTRY * pEntries; } TABLEHEADER; class CHashTable { private: CRITICAL_SECTION m_cs; DWORD m_dwTables; DWORD m_dwEntriesPerTable; TABLEHEADER * m_pTables; public: CHashTable() { InitializeCriticalSection( &m_cs ); } ~CHashTable() { DeleteCriticalSection( &m_cs ); } DECLARE_TRACELOG_CLASS(CHashTable) void Lock() { //LOG((TL_INFO,"Hash Table locking......")); EnterCriticalSection( &m_cs ); //LOG((TL_INFO,"Hash Table locked")); } void Unlock() { //LOG((TL_INFO,"Hash Table Unlocking......")); LeaveCriticalSection( &m_cs ); //LOG((TL_INFO,"Hash Table Unlocked")); } HRESULT Initialize( DWORD dwEntries ) { DWORD dwCount; BYTE * pStart; m_dwTables = 31; m_dwEntriesPerTable = dwEntries; m_pTables = (TABLEHEADER *)ClientAlloc( sizeof(TABLEHEADER) * m_dwTables ); if ( NULL == m_pTables ) { return E_OUTOFMEMORY; } pStart = (BYTE *)ClientAlloc( sizeof(TABLEENTRY) * m_dwTables * m_dwEntriesPerTable ); if ( NULL == pStart ) { ClientFree( m_pTables ); return E_OUTOFMEMORY; } for ( dwCount = 0; dwCount < m_dwTables; dwCount++ ) { m_pTables[dwCount].pEntries = (TABLEENTRY *)&( pStart[dwCount * m_dwEntriesPerTable * sizeof (TABLEENTRY)] ); m_pTables[dwCount].dwUsedElements = 0; } return S_OK; } HRESULT Insert( ULONG_PTR HashKey, ULONG_PTR Element , CTAPI *pTapiObj = 0) { DWORD dwHashIndex; DWORD dwCount = 0; TABLEHEADER * pTableHeader; if ( HashKey == 0 ) return S_OK; dwHashIndex = Hash( HashKey ); pTableHeader = &(m_pTables[dwHashIndex]); if (pTableHeader->dwUsedElements == m_dwEntriesPerTable) { HRESULT hr; hr = Resize(); if ( !SUCCEEDED(hr) ) { return hr; } } while ( 0 != pTableHeader->pEntries[dwCount].HashKey ) { dwCount ++; } if (dwCount >= m_dwEntriesPerTable) { LOG((TL_ERROR,"Hash Table insert: dwCount >= m_dwEntriesPerTable")); } pTableHeader->pEntries[dwCount].HashKey = HashKey; pTableHeader->pEntries[dwCount].Element = Element; pTableHeader->pEntries[dwCount].pTapiObj = pTapiObj; pTableHeader->dwUsedElements++; LOG((TL_INFO,"Hash Table insert: key %p - obj %p - tapi %p", HashKey, Element, pTapiObj)); #ifdef DBG CheckForDups( pTableHeader ); #endif return S_OK; } #ifdef DBG HRESULT CheckForDups( TABLEHEADER * pTableHeader ) { DWORD dwCount; DWORD dwInner; for ( dwCount = 0; dwCount < m_dwEntriesPerTable; dwCount++ ) { if (pTableHeader->pEntries[dwCount].HashKey == 0) continue; for ( dwInner = dwCount+1; dwInner < m_dwEntriesPerTable; dwInner++ ) { if ( pTableHeader->pEntries[dwCount].HashKey == pTableHeader->pEntries[dwInner].HashKey ) { LOG((TL_ERROR, "HashTable - dup entry")); LOG((TL_ERROR, " dwCount = %lx, dwInner = %lx", dwCount,dwInner)); LOG((TL_ERROR, " dwHash = %p", pTableHeader->pEntries[dwCount].HashKey)); LOG(( TL_ERROR, "HashTable - dup entry")); LOG(( TL_ERROR, " dwCount = %lx, dwInner = %lx", dwCount,dwInner)); LOG(( TL_ERROR, " HashKey = %p", pTableHeader->pEntries[dwCount].HashKey)); DebugBreak(); } } } return 0; } #endif // DBG HRESULT Remove( ULONG_PTR HashKey ) { DWORD dwHashIndex; DWORD dwCount; TABLEHEADER * pTableHeader; LOG((TL_INFO,"Hash Table Remove: key %p ", HashKey)); if ( HashKey == 0 ) return S_OK; dwHashIndex = Hash( HashKey ); pTableHeader = &(m_pTables[dwHashIndex]); for ( dwCount = 0; dwCount < m_dwEntriesPerTable; dwCount++ ) { if ( HashKey == pTableHeader->pEntries[dwCount].HashKey ) { LOG((TL_INFO,"Hash Table Remove: key %p - obj %p",HashKey,pTableHeader->pEntries[dwCount].Element)); LOG(( TL_TRACE, "Hash Table Remove: key %p - obj %p",HashKey,pTableHeader->pEntries[dwCount].Element)); break; } } if ( dwCount == m_dwEntriesPerTable ) { return E_FAIL; } pTableHeader->pEntries[dwCount].HashKey = 0; pTableHeader->pEntries[dwCount].pTapiObj = 0; pTableHeader->dwUsedElements--; return S_OK; } HRESULT Find( ULONG_PTR HashKey, ULONG_PTR * pElement ) { DWORD dwHashIndex; TABLEHEADER * pTableHeader; DWORD dwCount; if ( HashKey == 0 ) { LOG((TL_INFO,"Find - Hash Table returning E_FAIL on Find(NULL)")); return E_FAIL; // return S_OK; } dwHashIndex = Hash( HashKey ); pTableHeader = &(m_pTables[dwHashIndex]); for (dwCount = 0; dwCount < m_dwEntriesPerTable; dwCount++ ) { if ( HashKey == pTableHeader->pEntries[dwCount].HashKey ) { break; } } if ( dwCount == m_dwEntriesPerTable ) { return E_FAIL; } *pElement = pTableHeader->pEntries[dwCount].Element; LOG((TL_INFO,"Find - Hash Table found: key %p - obj %p",HashKey,*pElement)); return S_OK; } DWORD Hash( ULONG_PTR HashKey ) { return (DWORD)((HashKey >> 4) % m_dwTables); } HRESULT Resize() { BYTE * pNewTable; BYTE * pOldTable; DWORD dwCount; DWORD dwNumEntries; dwNumEntries = 2 * m_dwEntriesPerTable; pNewTable = (BYTE *)ClientAlloc( sizeof(TABLEENTRY) * m_dwTables * dwNumEntries ); if ( NULL == pNewTable ) { return E_OUTOFMEMORY; } pOldTable = (BYTE *)(m_pTables[0].pEntries); for ( dwCount = 0; dwCount < m_dwTables; dwCount ++ ) { CopyMemory( pNewTable, m_pTables[dwCount].pEntries, sizeof(TABLEENTRY) * m_dwEntriesPerTable ); m_pTables[dwCount].pEntries = (TABLEENTRY*)pNewTable; pNewTable += sizeof(TABLEENTRY) * dwNumEntries; } ClientFree( pOldTable ); m_dwEntriesPerTable = dwNumEntries; return S_OK; } void Shutdown() { ClientFree( m_pTables[0].pEntries ); ClientFree( m_pTables ); } HRESULT Flush( CTAPI * pTapiObj ) { DWORD dwOuterCount; DWORD dwInnerCount; TABLEHEADER * pTableHeader; Lock(); for ( dwOuterCount = 0; dwOuterCount < m_dwTables; dwOuterCount++ ) { pTableHeader = &(m_pTables[dwOuterCount]); for ( dwInnerCount = 0; dwInnerCount < m_dwEntriesPerTable; dwInnerCount++ ) { if ( pTapiObj == pTableHeader->pEntries[dwInnerCount].pTapiObj ) { LOG((TL_INFO,"Hash Table Flush: key %p - obj %p - tapi %p",pTableHeader->pEntries[dwInnerCount].HashKey,pTableHeader->pEntries[dwInnerCount].Element, pTapiObj)); LOG(( TL_ERROR, "Hash Table Flush: key %p - obj %p - tapi %p",pTableHeader->pEntries[dwInnerCount].HashKey,pTableHeader->pEntries[dwInnerCount].Element, pTapiObj)); pTableHeader->pEntries[dwInnerCount].HashKey = 0; pTableHeader->pEntries[dwInnerCount].pTapiObj = 0; pTableHeader->dwUsedElements--; } } // end for dwInnerCount } // end for dwOuterCount Unlock(); return S_OK; } }; #endif