[or-cvs] r6953: Looks like we might need a priority queue. (in tor/trunk: . src/common src/or)

nickm at seul.org nickm at seul.org
Mon Jul 31 17:59:38 UTC 2006


Author: nickm
Date: 2006-07-31 13:59:37 -0400 (Mon, 31 Jul 2006)
New Revision: 6953

Modified:
   tor/trunk/
   tor/trunk/src/common/container.c
   tor/trunk/src/common/container.h
   tor/trunk/src/or/test.c
Log:
 r6958 at Kushana:  nickm | 2006-07-29 18:54:15 -0400
 Looks like we might need a priority queue.



Property changes on: tor/trunk
___________________________________________________________________
Name: svk:merge
   - c95137ef-5f19-0410-b913-86e773d04f59:/tor/branches/eventdns:6952
c95137ef-5f19-0410-b913-86e773d04f59:/tor/branches/oo-connections:6950
   + c95137ef-5f19-0410-b913-86e773d04f59:/tor/branches/eventdns:6958
c95137ef-5f19-0410-b913-86e773d04f59:/tor/branches/oo-connections:6950

Modified: tor/trunk/src/common/container.c
===================================================================
--- tor/trunk/src/common/container.c	2006-07-31 17:59:11 UTC (rev 6952)
+++ tor/trunk/src/common/container.c	2006-07-31 17:59:37 UTC (rev 6953)
@@ -461,6 +461,87 @@
   smartlist_sort(sl, _compare_string_ptrs);
 }
 
+#define LEFT_CHILD(i)  ( ((i)+1)*2 - 1)
+#define RIGHT_CHILD(i) ( ((i)+1)*2 )
+#define PARENT(i)      ( ((i)+1)/2 - 1)
+
+static INLINE void
+smartlist_heapify(smartlist_t *sl,
+                  int (*compare)(const void *a, const void *b),
+                  int idx)
+{
+  while (1) {
+    int left_idx = LEFT_CHILD(idx);
+    int best_idx;
+
+    if (left_idx >= sl->num_used)
+      return;
+    if (compare(sl->list[idx],sl->list[left_idx]) < 0)
+      best_idx = idx;
+    else
+      best_idx = left_idx;
+    if (left_idx+1 < sl->num_used &&
+        compare(sl->list[left_idx+1],sl->list[best_idx]) < 0)
+      best_idx = left_idx + 1;
+
+    if (best_idx == idx) {
+      return;
+    } else {
+      void *tmp = sl->list[idx];
+      sl->list[idx] = sl->list[best_idx];
+      sl->list[best_idx] = tmp;
+
+      idx = best_idx;
+    }
+  }
+}
+
+void
+smartlist_pqueue_add(smartlist_t *sl,
+                     int (*compare)(const void *a, const void *b),
+                     void *item)
+{
+  int idx;
+  smartlist_add(sl,item);
+
+  for (idx = sl->num_used - 1; idx; ) {
+    int parent = PARENT(idx);
+    if (compare(sl->list[idx], sl->list[parent]) < 0) {
+      void *tmp = sl->list[parent];
+      sl->list[parent] = sl->list[idx];
+      sl->list[idx] = tmp;
+      idx = parent;
+    } else {
+      return;
+    }
+  }
+}
+
+void *
+smartlist_pqueue_pop(smartlist_t *sl,
+                     int (*compare)(const void *a, const void *b))
+{
+  void *top;
+  tor_assert(sl->num_used);
+
+  top = sl->list[0];
+  if (--sl->num_used) {
+    sl->list[0] = sl->list[sl->num_used];
+    smartlist_heapify(sl, compare, 0);
+  }
+  return top;
+}
+
+void
+smartlist_pqueue_assert_ok(smartlist_t *sl,
+                           int (*compare)(const void *a, const void *b))
+{
+  int i;
+  for (i = sl->num_used - 1; i > 0; --i) {
+    tor_assert(compare(sl->list[PARENT(i)], sl->list[i]) <= 0);
+  }
+}
+
 /** Helper: compare two DIGEST_LEN digests. */
 static int
 _compare_digests(const void **_a, const void **_b)

Modified: tor/trunk/src/common/container.h
===================================================================
--- tor/trunk/src/common/container.h	2006-07-31 17:59:11 UTC (rev 6952)
+++ tor/trunk/src/common/container.h	2006-07-31 17:59:37 UTC (rev 6953)
@@ -38,6 +38,7 @@
 int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
 void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
 void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
+
 /* smartlist_choose() is defined in crypto.[ch] */
 #ifdef DEBUG_SMARTLIST
 /** Return the number of items in sl.
@@ -76,6 +77,14 @@
 void *smartlist_bsearch(smartlist_t *sl, const void *key,
                         int (*compare)(const void *key, const void **member));
 
+void smartlist_pqueue_add(smartlist_t *sl,
+                          int (*compare)(const void *a, const void *b),
+                          void *item);
+void *smartlist_pqueue_pop(smartlist_t *sl,
+                           int (*compare)(const void *a, const void *b));
+void smartlist_pqueue_assert_ok(smartlist_t *sl,
+                                int (*compare)(const void *a, const void *b));
+
 #define SPLIT_SKIP_SPACE   0x01
 #define SPLIT_IGNORE_BLANK 0x02
 int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep,

Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c	2006-07-31 17:59:11 UTC (rev 6952)
+++ tor/trunk/src/or/test.c	2006-07-31 17:59:37 UTC (rev 6953)
@@ -921,7 +921,67 @@
   smartlist_free(sl);
 }
 
+static int
+_compare_strings_for_pqueue(const void *s1, const void *s2)
+{
+  return strcmp((const char*)s1, (const char*)s2);
+}
+
 static void
+test_pqueue(void)
+{
+  smartlist_t *sl;
+  int (*cmp)(const void *, const void*);
+#define OK() smartlist_pqueue_assert_ok(sl, cmp)
+
+  cmp = _compare_strings_for_pqueue;
+
+  sl = smartlist_create();
+  smartlist_pqueue_add(sl, cmp, "cows");
+  smartlist_pqueue_add(sl, cmp, "zebras");
+  smartlist_pqueue_add(sl, cmp, "fish");
+  smartlist_pqueue_add(sl, cmp, "frogs");
+  smartlist_pqueue_add(sl, cmp, "apples");
+  smartlist_pqueue_add(sl, cmp, "squid");//
+  smartlist_pqueue_add(sl, cmp, "daschunds");
+  smartlist_pqueue_add(sl, cmp, "eggplants");
+  smartlist_pqueue_add(sl, cmp, "weissbier");//
+  smartlist_pqueue_add(sl, cmp, "lobsters");
+  smartlist_pqueue_add(sl, cmp, "roquefort");//
+
+  OK();
+
+  test_eq(smartlist_len(sl), 11);
+  test_streq(smartlist_get(sl, 0), "apples");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "apples");
+  test_eq(smartlist_len(sl), 10);
+  OK();
+  test_streq(smartlist_pqueue_pop(sl, cmp), "cows");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "daschunds");
+  smartlist_pqueue_add(sl, cmp, "chinchillas");
+  OK();
+  smartlist_pqueue_add(sl, cmp, "fireflies");
+  OK();
+  test_streq(smartlist_pqueue_pop(sl, cmp), "chinchillas");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "eggplants");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "fireflies");
+  OK();
+  test_streq(smartlist_pqueue_pop(sl, cmp), "fish");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "frogs");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "lobsters");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "roquefort");
+  OK();
+  test_eq(smartlist_len(sl), 3);
+  test_streq(smartlist_pqueue_pop(sl, cmp), "squid");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "weissbier");
+  test_streq(smartlist_pqueue_pop(sl, cmp), "zebras");
+  test_eq(smartlist_len(sl), 0);
+  OK();
+#undef OK
+  smartlist_free(sl);
+}
+
+static void
 test_gzip(void)
 {
   char *buf1, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
@@ -1675,6 +1735,7 @@
   test_util();
   test_strmap();
   test_control_formats();
+  test_pqueue();
   puts("\n========================= Onion Skins =====================");
   test_onion();
   test_onion_handshake();



More information about the tor-commits mailing list