8787#define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket)
8888#define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash)
8989
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+
9094/* generate forward declarations necessary to use the hash table */
9195#ifdef SH_DECLARE
9296
@@ -112,6 +116,11 @@ typedef struct SH_TYPE
112116 /* hash buckets */
113117 SH_ELEMENT_TYPE * data ;
114118
119+ /* Allocation and free functions, and the associated context. */
120+ simplehash_allocate element_alloc ;
121+ simplehash_free element_free ;
122+ void * element_args ;
123+
115124 /* memory context to use for allocations */
116125 MemoryContext ctx ;
117126
@@ -133,7 +142,8 @@ typedef struct SH_ITERATOR
133142} SH_ITERATOR ;
134143
135144/* 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 );
137147SH_SCOPE void SH_DESTROY (SH_TYPE * tb );
138148SH_SCOPE void SH_GROW (SH_TYPE * tb , uint32 newsize );
139149SH_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)
276286#endif
277287}
278288
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+
279306/*
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.
282314 */
283315SH_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 )
285318{
286319 SH_TYPE * tb ;
287320 uint64 size ;
@@ -294,9 +327,22 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
294327
295328 SH_COMPUTE_PARAMETERS (tb , size );
296329
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 );
300346
301347 return tb ;
302348}
@@ -305,7 +351,7 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
305351SH_SCOPE void
306352SH_DESTROY (SH_TYPE * tb )
307353{
308- pfree (tb -> data );
354+ tb -> element_free (tb -> data , tb -> element_args );
309355 pfree (tb );
310356}
311357
@@ -333,9 +379,8 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
333379 /* compute parameters for new table */
334380 SH_COMPUTE_PARAMETERS (tb , newsize );
335381
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 );
339384
340385 newdata = tb -> data ;
341386
@@ -421,7 +466,7 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
421466 }
422467 }
423468
424- pfree (olddata );
469+ tb -> element_free (olddata , tb -> element_args );
425470}
426471
427472/*
0 commit comments