blob: 2671c2c7ea3c57061d663510d4024b0006553395 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
* Copyright (c) 2012 The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* General purpose hash table, used for finding classes, methods, etc.
*
* When the number of elements reaches a certain percentage of the table's
* capacity, the table will be resized.
*/
#ifndef _TESTFRAMEWORK_HASH
#define _TESTFRAMEWORK_HASH
#include <pthread.h>
#define HASH_TOMBSTONE ((void*) 0xcbcacccd) // invalid ptr value
/* compute the hash of an item with a specific type */
typedef unsigned int (*HashCompute)(const void* item);
/*
* Compare a hash entry with a "loose" item after their hash values match.
* Returns { <0, 0, >0 } depending on ordering of items (same semantics
* as strcmp()).
*/
typedef int (*HashCompareFunc)(const void* tableItem, const void* looseItem);
/*
* This function will be used to free entries in the table. This can be
* NULL if no free is required, free(), or a custom function.
*/
typedef void (*HashFreeFunc)(void* ptr);
/*
* Expandable hash table.
*
* This structure should be considered opaque.
*/
class TfHashTable {
public:
/*
* Create and initialize a HashTable structure, using "initialSize" as
* a basis for the initial capacity of the table. (The actual initial
* table size may be adjusted upward.) If you know exactly how many
* elements the table will hold, pass the result from TfHashSize() in.)
*
* Returns "false" if unable to allocate the table.
*/
TfHashTable(size_t initialSize, HashFreeFunc freeFunc,
HashCompareFunc cmpFunc, HashCompute computeFunc);
/*
* Free a hash table. Performs a "clear" first.
*/
~TfHashTable();
/*
* Compute the capacity needed for a table to hold "size" elements. Use
* this when you know ahead of time how many elements the table will hold.
* Pass this value into TfHashTableCreate() to ensure that you can add
* all elements without needing to reallocate the table.
*/
size_t TfHashSize(size_t size);
/*
* Clear out a hash table, freeing the contents of any used entries.
*/
void TfHashTableClear();
/*
* Look up an entry in the table, possibly adding it if it's not there.
*
* If "item" is not found, and "doAdd" is false, NULL is returned.
* Otherwise, a pointer to the found or added item is returned. (You can
* tell the difference by seeing if return value == item.)
*
* An "add" operation may cause the entire table to be reallocated. Don't
* forget to lock the table before calling this.
*/
void* TfHashTableLookup(void* item, int len = -1, bool doAdd = false);
/*
* Remove an item from the hash table, given its "data" pointer. Does not
* invoke the "free" function; just detaches it from the table.
*/
bool TfHashTableRemove(void* item);
static unsigned int ComputeUtf8Hash(const char* str);
private:
/*
* Exclusive access. Important when adding items to a table, or when
* doing any operations on a table that could be added to by another thread.
*/
void TfHashTableLock() {
pthread_mutex_lock(&lock);
}
void TfHashTableUnlock() {
pthread_mutex_unlock(&lock);
}
bool resizeHash(int newSize);
unsigned int roundUpPower2(unsigned int val);
int countTombStones();
private:
/*
* One entry in the hash table. "data" values are expected to be (or have
* the same characteristics as) valid pointers. In particular, a NULL
* value for "data" indicates an empty slot, and HASH_TOMBSTONE indicates
* a no-longer-used slot that must be stepped over during probing.
*
* Attempting to add a NULL or tombstone value is an error.
*
* When an entry is released, we will call (HashFreeFunc)(entry->data).
*/
struct HashEntry {
unsigned int hashValue;
void* data;
};
private:
int tableSize; /* must be power of 2 */
int numEntries; /* current #of "live" entries */
int numDeadEntries; /* current #of tombstone entries */
HashEntry* pEntries; /* array on heap */
HashFreeFunc freeFunc;
HashCompareFunc cmpFunc;
HashCompute computeFunc;
pthread_mutex_t lock;
};
#endif /*_TESTFRAMEWORK_HASH*/