|
1 | 1 | /*
|
2 | 2 | * simplehash.h
|
3 | 3 | *
|
4 |
| - * Hash table implementation which will be specialized to user-defined |
5 |
| - * types, by including this file to generate the required code. It's |
6 |
| - * probably not worthwhile to do so for hash tables that aren't performance |
7 |
| - * or space sensitive. |
| 4 | + * When included this file generates a "templated" (by way of macros) |
| 5 | + * open-addressing hash table implementation specialized to user-defined |
| 6 | + * types. |
| 7 | + * |
| 8 | + * It's probably not worthwhile to generate such a specialized implementation |
| 9 | + * for hash tables that aren't performance or space sensitive. |
| 10 | + * |
| 11 | + * Compared to dynahash, simplehash has the following benefits: |
| 12 | + * |
| 13 | + * - Due to the "templated" code generation has known structure sizes and no |
| 14 | + * indirect function calls (which show up substantially in dynahash |
| 15 | + * profiles). These features considerably increase speed for small |
| 16 | + * entries. |
| 17 | + * - Open addressing has better CPU cache behavior than dynahash's chained |
| 18 | + * hashtables. |
| 19 | + * - The generated interface is type-safe and easier to use than dynahash, |
| 20 | + * though at the cost of more complex setup. |
| 21 | + * - Allocates memory in a MemoryContext or another allocator with a |
| 22 | + * malloc/free style interface (which isn't easily usable in a shared |
| 23 | + * memory context) |
| 24 | + * - Does not require the overhead of a separate memory context. |
8 | 25 | *
|
9 | 26 | * Usage notes:
|
10 | 27 | *
|
|
34 | 51 | * - SH_STORE_HASH - if defined the hash is stored in the elements
|
35 | 52 | * - SH_GET_HASH(tb, a) - return the field to store the hash in
|
36 | 53 | *
|
| 54 | + * The element type is required to contain a "uint32 status" member. |
| 55 | + * |
| 56 | + * While SH_STORE_HASH (and subsequently SH_GET_HASH) are optional, because |
| 57 | + * the hash table implementation needs to compare hashes to move elements |
| 58 | + * (particularly when growing the hash), it's preferable, if possible, to |
| 59 | + * store the element's hash in the element's data type. If the hash is so |
| 60 | + * stored, the hash table will also compare hashes before calling SH_EQUAL |
| 61 | + * when comparing two keys. |
| 62 | + * |
| 63 | + * For convenience the hash table create functions accept a void pointer |
| 64 | + * that will be stored in the hash table type's member private_data. This |
| 65 | + * allows callbacks to reference caller provided data. |
| 66 | + * |
37 | 67 | * For examples of usage look at tidbitmap.c (file local definition) and
|
38 | 68 | * execnodes.h/execGrouping.c (exposed declaration, file local
|
39 | 69 | * implementation).
|
@@ -149,24 +179,59 @@ typedef struct SH_ITERATOR
|
149 | 179 |
|
150 | 180 | /* externally visible function prototypes */
|
151 | 181 | #ifdef SH_RAW_ALLOCATOR
|
| 182 | +/* <prefix>_hash <prefix>_create(uint32 nelements, void *private_data) */ |
152 | 183 | SH_SCOPE SH_TYPE *SH_CREATE(uint32 nelements, void *private_data);
|
153 | 184 | #else
|
| 185 | +/* |
| 186 | + * <prefix>_hash <prefix>_create(MemoryContext ctx, uint32 nelements, |
| 187 | + * void *private_data) |
| 188 | + */ |
154 | 189 | SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements,
|
155 | 190 | void *private_data);
|
156 | 191 | #endif
|
| 192 | + |
| 193 | +/* void <prefix>_destroy(<prefix>_hash *tb) */ |
157 | 194 | SH_SCOPE void SH_DESTROY(SH_TYPE * tb);
|
| 195 | + |
| 196 | +/* void <prefix>_reset(<prefix>_hash *tb) */ |
158 | 197 | SH_SCOPE void SH_RESET(SH_TYPE * tb);
|
| 198 | + |
| 199 | +/* void <prefix>_grow(<prefix>_hash *tb) */ |
159 | 200 | SH_SCOPE void SH_GROW(SH_TYPE * tb, uint32 newsize);
|
| 201 | + |
| 202 | +/* <element> *<prefix>_insert(<prefix>_hash *tb, <key> key, bool *found) */ |
160 | 203 | SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found);
|
| 204 | + |
| 205 | +/* |
| 206 | + * <element> *<prefix>_insert_hash(<prefix>_hash *tb, <key> key, uint32 hash, |
| 207 | + * bool *found) |
| 208 | + */ |
161 | 209 | SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT_HASH(SH_TYPE * tb, SH_KEY_TYPE key,
|
162 | 210 | uint32 hash, bool *found);
|
| 211 | + |
| 212 | +/* <element> *<prefix>_lookup(<prefix>_hash *tb, <key> key) */ |
163 | 213 | SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP(SH_TYPE * tb, SH_KEY_TYPE key);
|
| 214 | + |
| 215 | +/* <element> *<prefix>_lookup_hash(<prefix>_hash *tb, <key> key, uint32 hash) */ |
164 | 216 | SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP_HASH(SH_TYPE * tb, SH_KEY_TYPE key,
|
165 | 217 | uint32 hash);
|
| 218 | + |
| 219 | +/* bool <prefix>_delete(<prefix>_hash *tb, <key> key) */ |
166 | 220 | SH_SCOPE bool SH_DELETE(SH_TYPE * tb, SH_KEY_TYPE key);
|
| 221 | + |
| 222 | +/* void <prefix>_start_iterate(<prefix>_hash *tb, <prefix>_iterator *iter) */ |
167 | 223 | SH_SCOPE void SH_START_ITERATE(SH_TYPE * tb, SH_ITERATOR * iter);
|
| 224 | + |
| 225 | +/* |
| 226 | + * void <prefix>_start_iterate_at(<prefix>_hash *tb, <prefix>_iterator *iter, |
| 227 | + * uint32 at) |
| 228 | + */ |
168 | 229 | SH_SCOPE void SH_START_ITERATE_AT(SH_TYPE * tb, SH_ITERATOR * iter, uint32 at);
|
| 230 | + |
| 231 | +/* <element> *<prefix>_iterate(<prefix>_hash *tb, <prefix>_iterator *iter) */ |
169 | 232 | SH_SCOPE SH_ELEMENT_TYPE *SH_ITERATE(SH_TYPE * tb, SH_ITERATOR * iter);
|
| 233 | + |
| 234 | +/* void <prefix>_stat(<prefix>_hash *tb */ |
170 | 235 | SH_SCOPE void SH_STAT(SH_TYPE * tb);
|
171 | 236 |
|
172 | 237 | #endif /* SH_DECLARE */
|
|
0 commit comments