232 lines
3.7 KiB
C++
232 lines
3.7 KiB
C++
//+-------------------------------------------------------------------------
|
||
//
|
||
// Microsoft Windows
|
||
//
|
||
// Copyright (C) Microsoft Corporation, 1994 - 1999
|
||
//
|
||
// File: hashtabl.hxx
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
/*++
|
||
|
||
Module Name:
|
||
|
||
hashtabl.hxx
|
||
|
||
Abstract:
|
||
|
||
interface for a hash table indexed by UUID
|
||
|
||
Author:
|
||
|
||
Jeff Roberts (jroberts) 9-Nov-1994
|
||
|
||
Revision History:
|
||
|
||
9-Nov-1994 jroberts
|
||
|
||
Created this module.
|
||
|
||
--*/
|
||
|
||
#ifndef _HASHTABL_HXX_
|
||
#define _HASHTABL_HXX_
|
||
|
||
#define NO_HASH ((unsigned)(-1))
|
||
#define INVALID_NODE ((UUID_HASH_TABLE_NODE *) (-1))
|
||
|
||
|
||
class UUID_HASH_TABLE_NODE
|
||
{
|
||
public:
|
||
|
||
UUID_HASH_TABLE_NODE * pNext;
|
||
UUID_HASH_TABLE_NODE * pPrev;
|
||
|
||
RPC_UUID Uuid;
|
||
|
||
UUID_HASH_TABLE_NODE(
|
||
)
|
||
{
|
||
#ifdef DEBUGRPC
|
||
|
||
pNext = INVALID_NODE;
|
||
pPrev = INVALID_NODE;
|
||
|
||
#endif
|
||
}
|
||
|
||
UUID_HASH_TABLE_NODE(
|
||
RPC_UUID * pNewUuid
|
||
)
|
||
{
|
||
Initialize(pNewUuid);
|
||
#ifdef DEBUGRPC
|
||
|
||
pNext = INVALID_NODE;
|
||
pPrev = INVALID_NODE;
|
||
|
||
#endif
|
||
}
|
||
|
||
inline void
|
||
Initialize(
|
||
RPC_UUID * pNewUuid
|
||
)
|
||
{
|
||
Uuid = *pNewUuid;
|
||
}
|
||
|
||
int
|
||
CompareUuid(
|
||
void * Buffer
|
||
)
|
||
{
|
||
RPC_UUID * UuidBuffer = (RPC_UUID *) Buffer;
|
||
return Uuid.MatchUuid(UuidBuffer);
|
||
}
|
||
|
||
inline void
|
||
VerifyFree(
|
||
)
|
||
{
|
||
ASSERT(pNext == INVALID_NODE);
|
||
ASSERT(pPrev == INVALID_NODE);
|
||
}
|
||
|
||
void
|
||
QueryUuid(
|
||
void * Buffer
|
||
)
|
||
{
|
||
RPC_UUID * UuidBuffer = (RPC_UUID *) Buffer;
|
||
*UuidBuffer = Uuid;
|
||
}
|
||
|
||
};
|
||
|
||
|
||
class UUID_HASH_TABLE
|
||
{
|
||
public:
|
||
|
||
UUID_HASH_TABLE(
|
||
RPC_STATUS * pStatus,
|
||
unsigned long SpinCount = 0
|
||
);
|
||
|
||
~UUID_HASH_TABLE();
|
||
|
||
unsigned
|
||
Add(
|
||
UUID_HASH_TABLE_NODE * pNode,
|
||
unsigned Hash = NO_HASH
|
||
);
|
||
|
||
void
|
||
Remove(
|
||
UUID_HASH_TABLE_NODE * pNode,
|
||
unsigned Hash = NO_HASH
|
||
);
|
||
|
||
inline UUID_HASH_TABLE_NODE *
|
||
Lookup(
|
||
RPC_UUID * Uuid,
|
||
unsigned Hash = NO_HASH
|
||
);
|
||
|
||
inline unsigned
|
||
MakeHash(
|
||
RPC_UUID * Uuid
|
||
)
|
||
{
|
||
return (Uuid->HashUuid() & BUCKET_COUNT_MASK);
|
||
}
|
||
|
||
protected:
|
||
|
||
inline void
|
||
RequestHashMutex(
|
||
unsigned Hash
|
||
)
|
||
{
|
||
BucketMutexes[Hash % MUTEX_COUNT]->Request();
|
||
}
|
||
|
||
inline void
|
||
ReleaseHashMutex(
|
||
unsigned Hash
|
||
)
|
||
{
|
||
BucketMutexes[Hash % MUTEX_COUNT]->Clear();
|
||
}
|
||
|
||
enum
|
||
{
|
||
// number of hash buckets
|
||
//
|
||
BUCKET_COUNT = 128,
|
||
|
||
// XOR this with any number to get a hash bucket index
|
||
//
|
||
BUCKET_COUNT_MASK = 0x007f,
|
||
|
||
MUTEX_COUNT = 4
|
||
|
||
};
|
||
|
||
#ifdef DEBUGRPC
|
||
unsigned Counts[BUCKET_COUNT];
|
||
#endif
|
||
|
||
// hash buckets - each bucket has a linked list of nodes
|
||
// in no particular order
|
||
//
|
||
UUID_HASH_TABLE_NODE * Buckets[BUCKET_COUNT];
|
||
|
||
// a mutex protexts each bucket
|
||
//
|
||
MUTEX * BucketMutexes[MUTEX_COUNT];
|
||
};
|
||
|
||
|
||
UUID_HASH_TABLE_NODE *
|
||
UUID_HASH_TABLE::Lookup(
|
||
RPC_UUID * Uuid,
|
||
unsigned Hash
|
||
)
|
||
{
|
||
if (Hash == NO_HASH)
|
||
{
|
||
Hash = MakeHash(Uuid);
|
||
}
|
||
|
||
ASSERT( Hash < BUCKET_COUNT );
|
||
|
||
UUID_HASH_TABLE_NODE * pScan = Buckets[Hash];
|
||
while (pScan)
|
||
{
|
||
if (0 == Uuid->MatchUuid(&pScan->Uuid))
|
||
{
|
||
return pScan;
|
||
}
|
||
|
||
if (pScan->pNext && pScan->pNext->pPrev != pScan)
|
||
{
|
||
#ifdef NTENV
|
||
DbgBreakPoint();
|
||
#else
|
||
RpcpBreakPoint();
|
||
#endif
|
||
}
|
||
|
||
pScan = pScan->pNext;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
#endif // _HASHTABL_HXX_
|
||
|