* Added optional allocator template parameter.

* Added optional parameter "void** oldTable" to Resize(). If given the old
  allocation for the table is returned instead of freeing it.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35278 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-01-25 12:18:20 +00:00
parent dc6a27e9b5
commit b20de45ebd

View File

@ -31,18 +31,44 @@
typedef int KeyType;
typedef Foo ValueType;
HashTableDefinition(const HashTableDefinition&) {}
size_t HashKey(int key) const
{
return key >> 1;
}
size_t HashKey(int key) const { return key >> 1; }
size_t Hash(Foo* value) const { return HashKey(value->bar); }
bool Compare(int key, Foo* value) const { return value->bar == key; }
Foo*& GetLink(Foo* value) const { return value->fNext; }
size_t Hash(Foo* value) const
{
return HashKey(value->bar);
}
bool Compare(int key, Foo* value) const
{
return value->bar == key;
}
Foo*& GetLink(Foo* value) const
{
return value->fNext;
}
};
*/
struct MallocAllocator {
void* Allocate(size_t size) const
{
return malloc(size);
}
void Free(void* memory) const
{
free(memory);
}
};
template<typename Definition, bool AutoExpand = true,
bool CheckDuplicates = false>
bool CheckDuplicates = false, typename Allocator = MallocAllocator>
class BOpenHashTable {
public:
typedef BOpenHashTable<Definition, AutoExpand, CheckDuplicates> HashTable;
@ -51,9 +77,7 @@ public:
static const size_t kMinimumSize = 8;
// we use malloc() / free() for allocation. If in the future this
// is revealed to be insufficient we can switch to a template based
// allocator. All allocations are of power of 2 lengths.
// All allocations are of power of 2 lengths.
// regrowth factor: 200 / 256 = 78.125%
// 50 / 256 = 19.53125%
@ -75,9 +99,19 @@ public:
{
}
BOpenHashTable(const Definition& definition, const Allocator& allocator)
:
fDefinition(definition),
fAllocator(allocator),
fTableSize(0),
fItemCount(0),
fTable(NULL)
{
}
~BOpenHashTable()
{
free(fTable);
fAllocator.Free(fTable);
}
status_t Init(size_t initialSize = kMinimumSize)
@ -259,15 +293,18 @@ public:
unless \a force is \c true, in which case the supplied allocation is
used in any event.
Otherwise \c true is returned.
If \a oldTable is non-null and resizing is successful, the old table
will not be freed, but will be returned via this parameter instead.
*/
bool Resize(void* allocation, size_t size, bool force = false)
bool Resize(void* allocation, size_t size, bool force = false,
void** oldTable = NULL)
{
if (!force && size != ResizeNeeded()) {
free(allocation);
fAllocator.Free(allocation);
return false;
}
_Resize((ValueType**)allocation, size / sizeof(ValueType*));
_Resize((ValueType**)allocation, size / sizeof(ValueType*), oldTable);
return true;
}
@ -356,7 +393,7 @@ protected:
bool _Resize(size_t newSize)
{
ValueType** newTable
= (ValueType**)malloc(sizeof(ValueType*) * newSize);
= (ValueType**)fAllocator.Allocate(sizeof(ValueType*) * newSize);
if (newTable == NULL)
return false;
@ -364,7 +401,7 @@ protected:
return true;
}
void _Resize(ValueType** newTable, size_t newSize)
void _Resize(ValueType** newTable, size_t newSize, void** oldTable = NULL)
{
for (size_t i = 0; i < newSize; i++)
newTable[i] = NULL;
@ -379,7 +416,10 @@ protected:
}
}
free(fTable);
if (oldTable != NULL)
*oldTable = fTable;
else
fAllocator.Free(fTable);
}
fTableSize = newSize;
@ -406,6 +446,7 @@ protected:
}
Definition fDefinition;
Allocator fAllocator;
size_t fTableSize;
size_t fItemCount;
ValueType** fTable;