Make binaryheap enlargeable.
authorMasahiko Sawada <msawada@postgresql.org>
Wed, 3 Apr 2024 01:27:43 +0000 (10:27 +0900)
committerMasahiko Sawada <msawada@postgresql.org>
Wed, 3 Apr 2024 01:27:43 +0000 (10:27 +0900)
The node array space of the binaryheap is doubled when there is no
available space.

Reviewed-by: Vignesh C, Peter Smith, Hayato Kuroda, Ajin Cherian,
Tomas Vondra, Shubham Khanna
Discussion: https://postgr.es/m/CAD21AoDffo37RC-eUuyHJKVEr017V2YYDLyn1xF_00ofptWbkg%40mail.gmail.com

src/common/binaryheap.c
src/include/lib/binaryheap.h

index 7377ebdf1568153e6a404c7fd336092c7f0b294b..2ffd656e87b76923260739c18faa9784e3355f15 100644 (file)
@@ -30,25 +30,24 @@ static void sift_up(binaryheap *heap, int node_off);
 /*
  * binaryheap_allocate
  *
- * Returns a pointer to a newly-allocated heap that has the capacity to
- * store the given number of nodes, with the heap property defined by
- * the given comparator function, which will be invoked with the additional
- * argument specified by 'arg'.
+ * Returns a pointer to a newly-allocated heap with the given initial number
+ * of nodes, and with the heap property defined by the given comparator
+ * function, which will be invoked with the additional argument specified by
+ * 'arg'.
  */
 binaryheap *
-binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
+binaryheap_allocate(int num_nodes, binaryheap_comparator compare, void *arg)
 {
-       int                     sz;
        binaryheap *heap;
 
-       sz = offsetof(binaryheap, bh_nodes) + sizeof(bh_node_type) * capacity;
-       heap = (binaryheap *) palloc(sz);
-       heap->bh_space = capacity;
+       heap = (binaryheap *) palloc(sizeof(binaryheap));
+       heap->bh_space = num_nodes;
        heap->bh_compare = compare;
        heap->bh_arg = arg;
 
        heap->bh_size = 0;
        heap->bh_has_heap_property = true;
+       heap->bh_nodes = (bh_node_type *) palloc(sizeof(bh_node_type) * num_nodes);
 
        return heap;
 }
@@ -74,6 +73,7 @@ binaryheap_reset(binaryheap *heap)
 void
 binaryheap_free(binaryheap *heap)
 {
+       pfree(heap->bh_nodes);
        pfree(heap);
 }
 
@@ -104,6 +104,17 @@ parent_offset(int i)
        return (i - 1) / 2;
 }
 
+/*
+ * Double the space allocated for nodes.
+ */
+static void
+enlarge_node_array(binaryheap *heap)
+{
+       heap->bh_space *= 2;
+       heap->bh_nodes = repalloc(heap->bh_nodes,
+                                                         sizeof(bh_node_type) * heap->bh_space);
+}
+
 /*
  * binaryheap_add_unordered
  *
@@ -115,14 +126,10 @@ parent_offset(int i)
 void
 binaryheap_add_unordered(binaryheap *heap, bh_node_type d)
 {
+       /* make sure enough space for a new node */
        if (heap->bh_size >= heap->bh_space)
-       {
-#ifdef FRONTEND
-               pg_fatal("out of binary heap slots");
-#else
-               elog(ERROR, "out of binary heap slots");
-#endif
-       }
+               enlarge_node_array(heap);
+
        heap->bh_has_heap_property = false;
        heap->bh_nodes[heap->bh_size] = d;
        heap->bh_size++;
@@ -153,14 +160,10 @@ binaryheap_build(binaryheap *heap)
 void
 binaryheap_add(binaryheap *heap, bh_node_type d)
 {
+       /* make sure enough space for a new node */
        if (heap->bh_size >= heap->bh_space)
-       {
-#ifdef FRONTEND
-               pg_fatal("out of binary heap slots");
-#else
-               elog(ERROR, "out of binary heap slots");
-#endif
-       }
+               enlarge_node_array(heap);
+
        heap->bh_nodes[heap->bh_size] = d;
        heap->bh_size++;
        sift_up(heap, heap->bh_size - 1);
index 19025c08ef1f3814b89d03ed7e79448d743319d5..9f6efb06e3ab0e05d845d78b8f2cac02ca3b7a80 100644 (file)
@@ -46,10 +46,10 @@ typedef struct binaryheap
        bool            bh_has_heap_property;   /* debugging cross-check */
        binaryheap_comparator bh_compare;
        void       *bh_arg;
-       bh_node_type bh_nodes[FLEXIBLE_ARRAY_MEMBER];
+       bh_node_type *bh_nodes;
 } binaryheap;
 
-extern binaryheap *binaryheap_allocate(int capacity,
+extern binaryheap *binaryheap_allocate(int num_nodes,
                                                                           binaryheap_comparator compare,
                                                                           void *arg);
 extern void binaryheap_reset(binaryheap *heap);