]> granicus.if.org Git - postgresql/commitdiff
Allow the element allocator for a simplehash to be specified.
authorRobert Haas <rhaas@postgresql.org>
Tue, 7 Feb 2017 20:58:30 +0000 (15:58 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 7 Feb 2017 21:01:44 +0000 (16:01 -0500)
This is infrastructure for a pending patch to allow parallel bitmap
heap scans.

Dilip Kumar, reviewed (in earlier versions) by Andres Freund and
(more recently) by me.  Some further renaming by me, also.

src/backend/executor/execGrouping.c
src/backend/nodes/tidbitmap.c
src/include/lib/simplehash.h

index 47c9656e1be1fd781a25846bbdf6f16717b972f5..2d9ce938bafc6ee6803929875b7ae6dbbcd1dceb 100644 (file)
@@ -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;
index 7b31948fd28a8993e01333c67a2b1145089089d8..36102b5deab70959aa808b3fd5bff25f53c534f0 100644 (file)
@@ -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)
index 72e18499c07aad8db520b81151e606841fbc9d2c..fd7063c216f0b0ba0c25ac5cf700bf3306d6a8ca 100644 (file)
 #define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket)
 #define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash)
 
+/* Allocation function for hash table elements */
+typedef void *(*simplehash_allocate) (Size size, void *args);
+typedef void (*simplehash_free) (void *pointer, void *args);
+
 /* generate forward declarations necessary to use the hash table */
 #ifdef SH_DECLARE
 
@@ -112,6 +116,11 @@ typedef struct SH_TYPE
        /* hash buckets */
        SH_ELEMENT_TYPE *data;
 
+       /* Allocation and free functions, and the associated context. */
+       simplehash_allocate element_alloc;
+       simplehash_free element_free;
+       void       *element_args;
+
        /* memory context to use for allocations */
        MemoryContext ctx;
 
@@ -133,7 +142,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,
+               simplehash_allocate allocfunc, simplehash_free freefunc, 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,12 +286,35 @@ 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.
+ * Create a hash table with enough space for `nelements` distinct members.
+ * Memory for the hash table is allocated from the passed-in context.  If
+ * desired, the array of elements can be allocated using a passed-in allocator;
+ * this could be useful in order to place the array of elements in a shared
+ * memory, or in a context that will outlive the rest of the hash table.
+ * Memory other than for the array of elements will still be allocated from
+ * the passed-in context.
  */
 SH_SCOPE SH_TYPE *
-SH_CREATE(MemoryContext ctx, uint32 nelements)
+SH_CREATE(MemoryContext ctx, uint32 nelements, simplehash_allocate allocfunc,
+                 simplehash_free freefunc, void *args)
 {
        SH_TYPE    *tb;
        uint64          size;
@@ -294,9 +327,22 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
 
        SH_COMPUTE_PARAMETERS(tb, size);
 
-       tb->data = MemoryContextAllocExtended(tb->ctx,
-                                                                                 sizeof(SH_ELEMENT_TYPE) * tb->size,
-                                                                                 MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+       if (allocfunc == NULL)
+       {
+               tb->element_alloc = SH_DEFAULT_ALLOC;
+               tb->element_free = SH_DEFAULT_FREE;
+               tb->element_args = ctx;
+       }
+       else
+       {
+               tb->element_alloc = allocfunc;
+               tb->element_free = freefunc;
+
+               tb->element_args = args;
+       }
+
+       tb->data = tb->element_alloc(sizeof(SH_ELEMENT_TYPE) * tb->size,
+                                                                tb->element_args);
 
        return tb;
 }
@@ -305,7 +351,7 @@ SH_CREATE(MemoryContext ctx, uint32 nelements)
 SH_SCOPE void
 SH_DESTROY(SH_TYPE *tb)
 {
-       pfree(tb->data);
+       tb->element_free(tb->data, tb->element_args);
        pfree(tb);
 }
 
@@ -333,9 +379,8 @@ 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->element_alloc(sizeof(SH_ELEMENT_TYPE) * tb->size,
+                                                                tb->element_args);
 
        newdata = tb->data;
 
@@ -421,7 +466,7 @@ SH_GROW(SH_TYPE *tb, uint32 newsize)
                }
        }
 
-       pfree(olddata);
+       tb->element_free(olddata, tb->element_args);
 }
 
 /*