diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c index 47c9656..2d9ce93 100644 --- a/src/backend/executor/execGrouping.c +++ b/src/backend/executor/execGrouping.c @@ -330,7 +330,8 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx, else hashtable->hash_iv = 0; - hashtable->hashtab = tuplehash_create(tablecxt, nbuckets); + hashtable->hashtab = + tuplehash_create(tablecxt, nbuckets, NULL, NULL, NULL); hashtable->hashtab->private_data = hashtable; return hashtable; diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index 7b31948..36102b5 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -244,7 +244,7 @@ tbm_create_pagetable(TIDBitmap *tbm) Assert(tbm->status != TBM_HASH); Assert(tbm->pagetable == NULL); - tbm->pagetable = pagetable_create(tbm->mcxt, 128); + tbm->pagetable = pagetable_create(tbm->mcxt, 128, NULL, NULL, NULL); /* If entry1 is valid, push it into the hashtable */ if (tbm->status == TBM_ONE_PAGE) diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h index 12aedbc..8c3e726 100644 --- a/src/include/lib/simplehash.h +++ b/src/include/lib/simplehash.h @@ -90,6 +90,12 @@ /* generate forward declarations necessary to use the hash table */ #ifdef SH_DECLARE +/* Allocation function for hash table elements */ +typedef void *(*element_allocate) (Size size, void *args); + +/* Free function */ +typedef void (*element_free) (void *pointer, void *args); + /* type definitions */ typedef struct SH_TYPE { @@ -112,8 +118,17 @@ typedef struct SH_TYPE /* hash buckets */ SH_ELEMENT_TYPE *data; + /* Allocation function for hash table elements */ + element_allocate alloc; + + /* Free function */ + element_free free; + + /* Arguments to be passed to allocation and free functions */ + void *args; + /* memory context to use for allocations */ - MemoryContext ctx; + MemoryContext element_allocator_ctx; /* user defined data, useful for callbacks */ void *private_data; @@ -133,7 +148,8 @@ typedef struct SH_ITERATOR } SH_ITERATOR; /* externally visible function prototypes */ -SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements); +SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements, + element_allocate alloc, element_free free, void *args); SH_SCOPE void SH_DESTROY(SH_TYPE *tb); SH_SCOPE void SH_GROW(SH_TYPE *tb, uint32 newsize); SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE *tb, SH_KEY_TYPE key, bool *found); @@ -276,27 +292,62 @@ SH_ENTRY_HASH(SH_TYPE *tb, SH_ELEMENT_TYPE * entry) #endif } +/* default memory allocator function */ +static void * +SH_DEFAULT_ALLOC(Size size, void *args) +{ + MemoryContext context = (MemoryContext) args; + + return MemoryContextAllocExtended(context, size, + MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO); +} + +/* default memory free function */ +static void +SH_DEFAULT_FREE(void *pointer, void *args) +{ + pfree(pointer); +} + /* * Create a hash table with enough space for `nelements` distinct members, * allocating required memory in the passed-in context. + * + * WARNING : alloc is an allocator handle which provides memory allocator + * function for storing hash elements. User needs to be aware that providing + * allocator does not store complete hash table in the allocator memory i.e + * hash table will still be allocated in local memory. However all the + * elements will be stored in the memory provided by the allocator. */ SH_SCOPE SH_TYPE * -SH_CREATE(MemoryContext ctx, uint32 nelements) +SH_CREATE(MemoryContext ctx, uint32 nelements, element_allocate alloc, + element_free free, void *args) { - SH_TYPE *tb; - uint64 size; + SH_TYPE *tb; + uint64 size; tb = MemoryContextAllocZero(ctx, sizeof(SH_TYPE)); - tb->ctx = ctx; + tb->element_allocator_ctx = ctx; /* increase nelements by fillfactor, want to store nelements elements */ size = Min((double) SH_MAX_SIZE, ((double) nelements) / SH_FILLFACTOR); SH_COMPUTE_PARAMETERS(tb, size); - tb->data = MemoryContextAllocExtended(tb->ctx, - sizeof(SH_ELEMENT_TYPE) * tb->size, - MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO); + if (!alloc) + { + tb->alloc = (element_allocate) SH_DEFAULT_ALLOC; + tb->free = (element_free) SH_DEFAULT_FREE; + tb->args = (void *) ctx; + } + else + { + tb->alloc = alloc; + tb->free = free; + tb->args = args; + } + + tb->data = tb->alloc(sizeof(SH_ELEMENT_TYPE) * tb->size, tb->args); return tb; } @@ -305,7 +356,7 @@ SH_CREATE(MemoryContext ctx, uint32 nelements) SH_SCOPE void SH_DESTROY(SH_TYPE *tb) { - pfree(tb->data); + tb->free(tb->data, tb->args); pfree(tb); } @@ -333,9 +384,7 @@ SH_GROW(SH_TYPE *tb, uint32 newsize) /* compute parameters for new table */ SH_COMPUTE_PARAMETERS(tb, newsize); - tb->data = MemoryContextAllocExtended( - tb->ctx, sizeof(SH_ELEMENT_TYPE) * tb->size, - MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO); + tb->data = tb->alloc(sizeof(SH_ELEMENT_TYPE) * tb->size, tb->args); newdata = tb->data; @@ -421,7 +470,7 @@ SH_GROW(SH_TYPE *tb, uint32 newsize) } } - pfree(olddata); + tb->free(olddata, tb->args); } /*