87
87
#define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket)
88
88
#define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash)
89
89
90
+ /* Allocation function for hash table elements */
91
+ typedef void * (* simplehash_allocate ) (Size size , void * args );
92
+ typedef void (* simplehash_free ) (void * pointer , void * args );
93
+
90
94
/* generate forward declarations necessary to use the hash table */
91
95
#ifdef SH_DECLARE
92
96
@@ -112,6 +116,11 @@ typedef struct SH_TYPE
112
116
/* hash buckets */
113
117
SH_ELEMENT_TYPE * data ;
114
118
119
+ /* Allocation and free functions, and the associated context. */
120
+ simplehash_allocate element_alloc ;
121
+ simplehash_free element_free ;
122
+ void * element_args ;
123
+
115
124
/* memory context to use for allocations */
116
125
MemoryContext ctx ;
117
126
@@ -133,7 +142,8 @@ typedef struct SH_ITERATOR
133
142
} SH_ITERATOR ;
134
143
135
144
/* externally visible function prototypes */
136
- SH_SCOPE SH_TYPE * SH_CREATE (MemoryContext ctx , uint32 nelements );
145
+ SH_SCOPE SH_TYPE * SH_CREATE (MemoryContext ctx , uint32 nelements ,
146
+ simplehash_allocate allocfunc , simplehash_free freefunc , void * args );
137
147
SH_SCOPE void SH_DESTROY (SH_TYPE * tb );
138
148
SH_SCOPE void SH_GROW (SH_TYPE * tb , uint32 newsize );
139
149
SH_SCOPE SH_ELEMENT_TYPE * SH_INSERT (SH_TYPE * tb , SH_KEY_TYPE key , bool * found );
@@ -276,12 +286,35 @@ SH_ENTRY_HASH(SH_TYPE *tb, SH_ELEMENT_TYPE * entry)
276
286
#endif
277
287
}
278
288
289
+ /* default memory allocator function */
290
+ static void *
291
+ SH_DEFAULT_ALLOC (Size size , void * args )
292
+ {
293
+ MemoryContext context = (MemoryContext ) args ;
294
+
295
+ return MemoryContextAllocExtended (context , size ,
296
+ MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO );
297
+ }
298
+
299
+ /* default memory free function */
300
+ static void
301
+ SH_DEFAULT_FREE (void * pointer , void * args )
302
+ {
303
+ pfree (pointer );
304
+ }
305
+
279
306
/*
280
- * Create a hash table with enough space for `nelements` distinct members,
281
- * allocating required memory in the passed-in context.
307
+ * Create a hash table with enough space for `nelements` distinct members.
308
+ * Memory for the hash table is allocated from the passed-in context. If
309
+ * desired, the array of elements can be allocated using a passed-in allocator;
310
+ * this could be useful in order to place the array of elements in a shared
311
+ * memory, or in a context that will outlive the rest of the hash table.
312
+ * Memory other than for the array of elements will still be allocated from
313
+ * the passed-in context.
282
314
*/
283
315
SH_SCOPE SH_TYPE *
284
- SH_CREATE (MemoryContext ctx , uint32 nelements )
316
+ SH_CREATE (MemoryContext ctx , uint32 nelements , simplehash_allocate allocfunc ,
317
+ simplehash_free freefunc , void * args )
285
318
{
286
319
SH_TYPE * tb ;
287
320
uint64 size ;
@@ -294,9 +327,22 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
294
327
295
328
SH_COMPUTE_PARAMETERS (tb , size );
296
329
297
- tb -> data = MemoryContextAllocExtended (tb -> ctx ,
298
- sizeof (SH_ELEMENT_TYPE ) * tb -> size ,
299
- MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO );
330
+ if (allocfunc == NULL )
331
+ {
332
+ tb -> element_alloc = SH_DEFAULT_ALLOC ;
333
+ tb -> element_free = SH_DEFAULT_FREE ;
334
+ tb -> element_args = ctx ;
335
+ }
336
+ else
337
+ {
338
+ tb -> element_alloc = allocfunc ;
339
+ tb -> element_free = freefunc ;
340
+
341
+ tb -> element_args = args ;
342
+ }
343
+
344
+ tb -> data = tb -> element_alloc (sizeof (SH_ELEMENT_TYPE ) * tb -> size ,
345
+ tb -> element_args );
300
346
301
347
return tb ;
302
348
}
@@ -305,7 +351,7 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
305
351
SH_SCOPE void
306
352
SH_DESTROY (SH_TYPE * tb )
307
353
{
308
- pfree (tb -> data );
354
+ tb -> element_free (tb -> data , tb -> element_args );
309
355
pfree (tb );
310
356
}
311
357
@@ -333,9 +379,8 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
333
379
/* compute parameters for new table */
334
380
SH_COMPUTE_PARAMETERS (tb , newsize );
335
381
336
- tb -> data = MemoryContextAllocExtended (
337
- tb -> ctx , sizeof (SH_ELEMENT_TYPE ) * tb -> size ,
338
- MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO );
382
+ tb -> data = tb -> element_alloc (sizeof (SH_ELEMENT_TYPE ) * tb -> size ,
383
+ tb -> element_args );
339
384
340
385
newdata = tb -> data ;
341
386
@@ -421,7 +466,7 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
421
466
}
422
467
}
423
468
424
- pfree (olddata );
469
+ tb -> element_free (olddata , tb -> element_args );
425
470
}
426
471
427
472
/*
0 commit comments