]> granicus.if.org Git - apache/commitdiff
Add a couple of optimizations to the priority queue code:
authorCliff Woolley <jwoolley@apache.org>
Wed, 17 Jul 2002 00:01:03 +0000 (00:01 +0000)
committerCliff Woolley <jwoolley@apache.org>
Wed, 17 Jul 2002 00:01:03 +0000 (00:01 +0000)
 * bubble_up and percolate_down do not need to do "swaps" -- they can just
   shift the existing items and reinsert the moving item once at the end
 * minchild() did not need that for loop -- a node can only ever have at
   most two children, and they are guaranteed to be adjacent

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@96089 13f79535-47bb-0310-9956-ffa450edef68

modules/experimental/cache_pqueue.c

index 145be5b56b5b158483c162f6a952a78f0dbdbb7f..424023e9661816322595709192867dd031e35dbb 100644 (file)
@@ -13,8 +13,8 @@
 
 #include "cache_pqueue.h"
 #define left(i) (2*(i))
-#define right(i) ((2*i)+1)
-#define parent(i) (i/2)
+#define right(i) ((2*(i))+1)
+#define parent(i) ((i)/2)
 /*
  *  Priority queue structure
  */
@@ -67,60 +67,62 @@ apr_ssize_t cache_pq_size(cache_pqueue_t *q)
     return q->size;
 }
 
-static void cache_pq_bubble_up(cache_pqueue_t*q, apr_ssize_t i)
+static void cache_pq_bubble_up(cache_pqueue_t *q, apr_ssize_t i)
 {
     apr_ssize_t parent_node;
-    parent_node = parent(i);
-
-    while (i > 1 && q->pri(q->d[parent_node]) < q->pri(q->d[i])) {
-        void *tmp;
-        tmp = q->d[i];
+    void *moving_node = q->d[i];
+    long moving_pri = q->pri(moving_node);
 
+    for (parent_node = parent(i);
+         ((i > 1) && (q->pri(q->d[parent_node]) < moving_pri));
+         i = parent_node, parent_node = parent(i))
+    {
         q->d[i] = q->d[parent_node];
-        q->d[parent_node] = tmp;
         q->set(q->d[i], i);
-        q->set(q->d[parent_node], parent_node);
-        i = parent_node;
-        parent_node = parent(i);
     }
+
+    q->d[i] = moving_node;
+    q->set(moving_node, i);
 }
 
 static apr_ssize_t minchild(cache_pqueue_t *q, apr_ssize_t i)
 {
-    apr_ssize_t y, minc;
-    minc = left(i);
-    if (minc >= q->size)
-        return -1;
-
-    for (y = minc + 1; y <= right(i) && y < q->size; y++) {
-        if (q->pri(q->d[y]) > q->pri(q->d[minc]))
-            minc = y;
+    apr_ssize_t child_node = left(i);
+
+    if (child_node >= q->size)
+        return 0;
+
+    if ((child_node+1 < q->size) &&
+        (q->pri(q->d[child_node+1]) > q->pri(q->d[child_node])))
+    {
+        child_node++; /* use right child instead of left */
     }
-    return minc;
+
+    return child_node;
 }
 
-static void cache_pq_percolate_down(cache_pqueue_t*q, apr_ssize_t i)
+static void cache_pq_percolate_down(cache_pqueue_t *q, apr_ssize_t i)
 {
-    apr_ssize_t cx = minchild(q, i);
-    while ((cx != -1) && (q->pri(q->d[cx]) > q->pri(q->d[i])))
-    {
-        void *tmp;
+    apr_ssize_t child_node;
+    void *moving_node = q->d[i];
+    long moving_pri = q->pri(moving_node);
 
-        tmp = q->d[i];
-        q->d[i] = q->d[cx];
-        q->d[cx] = tmp;
+    while ((child_node = minchild(q, i)) &&
+           (moving_pri < q->pri(q->d[child_node])))
+    {
+        q->d[i] = q->d[child_node];
         q->set(q->d[i], i);
-        q->set(q->d[cx], cx);
-        i = cx;
-        cx = minchild(q, i);
+        i = child_node;
     }
+
+    q->d[i] = moving_node;
+    q->set(moving_node, i);
 }
 
-apr_status_t cache_pq_insert(cache_pqueue_t *q, voidd)
+apr_status_t cache_pq_insert(cache_pqueue_t *q, void *d)
 {
     void *tmp;
     apr_ssize_t i;
-    apr_ssize_t parent_node;
     apr_ssize_t newsize;
 
     if (!q) return APR_EGENERAL;
@@ -137,26 +139,15 @@ apr_status_t cache_pq_insert(cache_pqueue_t *q, void* d)
 
     /* insert item */
     i = q->size++;
-    parent_node = parent(i);
-    /*
-     * this is an optimization of the bubble-up as it doesn't
-     * have to swap the member around
-     */
-    while ((i > 1) && q->pri(q->d[parent_node]) < q->pri(d)) {
-        q->d[i] = q->d[parent_node];
-        q->set(q->d[i], i);
-        i = parent_node;
-        parent_node = parent(i);
-    }
     q->d[i] = d;
-    q->set(q->d[i], i);
+    cache_pq_bubble_up(q, i);
     return APR_SUCCESS;
 }
 
 /*
  * move a existing entry to a new priority
  */
-void cache_pq_change_priority(cache_pqueue_t*q,
+void cache_pq_change_priority(cache_pqueue_t *q,
                               long old_priority,
                               long new_priority,
                               void *d)
@@ -170,7 +161,7 @@ void cache_pq_change_priority(cache_pqueue_t*q,
         cache_pq_percolate_down(q, posn);
 }
 
-apr_status_t cache_pq_remove(cache_pqueue_t *q, voidd)
+apr_status_t cache_pq_remove(cache_pqueue_t *q, void *d)
 {
     apr_ssize_t posn;
     void *popped = NULL;
@@ -241,6 +232,7 @@ static void cache_pq_set_null( void*d, apr_ssize_t val)
 {
     /* do nothing */
 }
+
 /*
  * this is a debug function.. so it's EASY not fast
  */
@@ -260,6 +252,7 @@ void cache_pq_dump(cache_pqueue_t *q,
         print(out, q->d[i]);
     }
 }
+
 /*
  * this is a debug function.. so it's EASY not fast
  */