You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by yl...@apache.org on 2014/07/18 01:58:03 UTC
svn commit: r1611515 - in /apr/apr/trunk: include/apr_skiplist.h
tables/apr_skiplist.c test/testskiplist.c
Author: ylavic
Date: Thu Jul 17 23:58:02 2014
New Revision: 1611515
URL: http://svn.apache.org/r1611515
Log:
Provide apr_skiplist_size/height/preheight() to get the corresponding values
in O(1), and apr_skiplist_set_preheight() to configure preheight mode.
Modified:
apr/apr/trunk/include/apr_skiplist.h
apr/apr/trunk/tables/apr_skiplist.c
apr/apr/trunk/test/testskiplist.c
Modified: apr/apr/trunk/include/apr_skiplist.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr_skiplist.h?rev=1611515&r1=1611514&r2=1611515&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_skiplist.h (original)
+++ apr/apr/trunk/include/apr_skiplist.h Thu Jul 17 23:58:02 2014
@@ -264,6 +264,40 @@ APR_DECLARE(void *) apr_skiplist_pop(apr
APR_DECLARE(void *) apr_skiplist_peek(apr_skiplist *sl);
/**
+ * Return the size of the list (number of elements), in O(1).
+ * @param sl The skip list
+ */
+APR_DECLARE(size_t) apr_skiplist_size(const apr_skiplist *sl);
+
+/**
+ * Return the height of the list (number of skip paths), in O(1).
+ * @param sl The skip list
+ */
+APR_DECLARE(int) apr_skiplist_height(const apr_skiplist *sl);
+
+/**
+ * Return the predefined maximum height of the skip list.
+ * @param sl The skip list
+ */
+APR_DECLARE(int) apr_skiplist_preheight(const apr_skiplist *sl);
+
+/**
+ * Set a predefined maximum height for the skip list.
+ * @param sl The skip list
+ * @param to The preheight to set, or a nul/negative value to disable.
+ * @remark When a preheight is used, the height of each inserted element is
+ * computed randomly up to this preheight instead of the current skip list's
+ * height plus one used by the default implementation. Using a preheight can
+ * probably ensure more fairness with long living elements (since with an
+ * adaptative height, former elements may have been created with a low height,
+ * hence a longest path to reach them while the skip list grows). On the other
+ * hand, the default behaviour (preheight <= 0) with a growing and decreasing
+ * maximum height is more adaptative/suitable for short living values.
+ * @note Should be called before any insertion/add.
+ */
+APR_DECLARE(void) apr_skiplist_set_preheight(apr_skiplist *sl, int to);
+
+/**
* Merge two skip lists. XXX SEMANTICS
* @param sl1 One of two skip lists to be merged
* @param sl2 The other of two skip lists to be merged
Modified: apr/apr/trunk/tables/apr_skiplist.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/tables/apr_skiplist.c?rev=1611515&r1=1611514&r2=1611515&view=diff
==============================================================================
--- apr/apr/trunk/tables/apr_skiplist.c (original)
+++ apr/apr/trunk/tables/apr_skiplist.c Thu Jul 17 23:58:02 2014
@@ -25,12 +25,14 @@
#include "apr_skiplist.h"
+#include <limits.h> /* for INT_MAX */
+
struct apr_skiplist {
apr_skiplist_compare compare;
apr_skiplist_compare comparek;
int height;
int preheight;
- int size;
+ size_t size;
apr_skiplistnode *top;
apr_skiplistnode *bottom;
/* These two are needed for appending */
@@ -675,6 +677,26 @@ APR_DECLARE(void *) apr_skiplist_peek(ap
return NULL;
}
+APR_DECLARE(size_t) apr_skiplist_size(const apr_skiplist *sl)
+{
+ return sl->size;
+}
+
+APR_DECLARE(int) apr_skiplist_height(const apr_skiplist *sl)
+{
+ return sl->height;
+}
+
+APR_DECLARE(int) apr_skiplist_preheight(const apr_skiplist *sl)
+{
+ return sl->preheight;
+}
+
+APR_DECLARE(void) apr_skiplist_set_preheight(apr_skiplist *sl, int to)
+{
+ sl->preheight = (to > 0) ? to : 0;
+}
+
static void skiplisti_destroy(void *vsl)
{
apr_skiplist_destroy((apr_skiplist *) vsl, NULL);
Modified: apr/apr/trunk/test/testskiplist.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/test/testskiplist.c?rev=1611515&r1=1611514&r2=1611515&view=diff
==============================================================================
--- apr/apr/trunk/test/testskiplist.c (original)
+++ apr/apr/trunk/test/testskiplist.c Thu Jul 17 23:58:02 2014
@@ -33,14 +33,14 @@
static apr_pool_t *ptmp = NULL;
static apr_skiplist *skiplist = NULL;
-/* apr_skiplist_size() is missing in 1.5.x, wrap it */
-static int apr_skiplist_size(apr_skiplist *sl)
+static int skiplist_get_size(abts_case *tc, apr_skiplist *sl)
{
- int size = 0;
+ size_t size = 0;
apr_skiplistnode *n;
for (n = apr_skiplist_getlist(sl); n; apr_skiplist_next(sl, &n)) {
++size;
}
+ ABTS_TRUE(tc, size == apr_skiplist_size(sl));
return size;
}
@@ -75,53 +75,66 @@ static void skiplist_dontfind(abts_case
static void skiplist_insert(abts_case *tc, void *data)
{
const char *val;
- int i;
+ int i, height = 0;
for (i = 0; i < 10; ++i) {
apr_skiplist_insert(skiplist, "baton");
- ABTS_INT_EQUAL(tc, 1, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 1 == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "baton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "baton", val);
+
+ if (height == 0) {
+ height = apr_skiplist_height(skiplist);
+ }
+ else {
+ ABTS_INT_EQUAL(tc, height, apr_skiplist_height(skiplist));
+ }
}
apr_skiplist_insert(skiplist, "foo");
- ABTS_INT_EQUAL(tc, 2, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 2 == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "foo", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "foo", val);
+
+ apr_skiplist_insert(skiplist, "atfirst");
+ ABTS_TRUE(tc, 3 == skiplist_get_size(tc, skiplist));
+ val = apr_skiplist_find(skiplist, "atfirst", NULL);
+ ABTS_PTR_NOTNULL(tc, val);
+ ABTS_STR_EQUAL(tc, "atfirst", val);
}
static void skiplist_add(abts_case *tc, void *data)
{
const char *val;
- size_t i, n = apr_skiplist_size(skiplist);
+ size_t i, n = skiplist_get_size(tc, skiplist);
for (i = 0; i < 100; ++i) {
n++;
apr_skiplist_add(skiplist, "daton");
- ABTS_INT_EQUAL(tc, n, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "daton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "daton", val);
n++;
apr_skiplist_add(skiplist, "baton");
- ABTS_INT_EQUAL(tc, n, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "baton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "baton", val);
n++;
apr_skiplist_add(skiplist, "caton");
- ABTS_INT_EQUAL(tc, n, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "caton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "caton", val);
n++;
apr_skiplist_add(skiplist, "aaton");
- ABTS_INT_EQUAL(tc, n, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, n == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "aaton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "aaton", val);
@@ -131,14 +144,14 @@ static void skiplist_add(abts_case *tc,
static void skiplist_destroy(abts_case *tc, void *data)
{
apr_skiplist_destroy(skiplist, NULL);
- ABTS_INT_EQUAL(tc, 0, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
}
static void skiplist_size(abts_case *tc, void *data)
{
const char *val;
- ABTS_INT_EQUAL(tc, 0, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
apr_skiplist_insert(skiplist, "abc");
apr_skiplist_insert(skiplist, "ghi");
@@ -153,7 +166,7 @@ static void skiplist_size(abts_case *tc,
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "def", val);
- ABTS_INT_EQUAL(tc, 3, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 3 == skiplist_get_size(tc, skiplist));
apr_skiplist_destroy(skiplist, NULL);
}
@@ -161,28 +174,28 @@ static void skiplist_remove(abts_case *t
{
const char *val;
- ABTS_INT_EQUAL(tc, 0, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
apr_skiplist_add(skiplist, "baton");
- ABTS_INT_EQUAL(tc, 1, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 1 == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "baton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "baton", val);
apr_skiplist_add(skiplist, "baton");
- ABTS_INT_EQUAL(tc, 2, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 2 == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "baton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "baton", val);
apr_skiplist_remove(skiplist, "baton", NULL);
- ABTS_INT_EQUAL(tc, 1, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 1 == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "baton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "baton", val);
apr_skiplist_add(skiplist, "baton");
- ABTS_INT_EQUAL(tc, 2, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 2 == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "baton", NULL);
ABTS_PTR_NOTNULL(tc, val);
ABTS_STR_EQUAL(tc, "baton", val);
@@ -190,7 +203,7 @@ static void skiplist_remove(abts_case *t
/* remove all "baton"s */
while (apr_skiplist_remove(skiplist, "baton", NULL))
;
- ABTS_INT_EQUAL(tc, 0, apr_skiplist_size(skiplist));
+ ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
val = apr_skiplist_find(skiplist, "baton", NULL);
ABTS_PTR_EQUAL(tc, NULL, val);
}
@@ -206,6 +219,9 @@ static void skiplist_random_loop(abts_ca
ABTS_INT_EQUAL(tc, APR_SUCCESS, apr_skiplist_init(&sl, ptmp));
apr_skiplist_set_compare(sl, (void*)strcmp, (void*)strcmp);
+ apr_skiplist_set_preheight(sl, 7);
+ ABTS_INT_EQUAL(tc, 7, apr_skiplist_preheight(sl));
+
batons = apr_palloc(ptmp, NUM_FIND * sizeof(char*));
for (i = 0; i < NUM_FIND; ++i) {