static apr_skiplist *timer_skiplist;
-static int indexing_comp(void *a, void *b)
+/* The following compare function is used by apr_skiplist_insert() to keep the
+ * elements (timers) sorted and provide O(log n) complexity (this is also true
+ * for apr_skiplist_{find,remove}(), but those are not used in MPM event where
+ * inserted timers are not searched nor removed, but with apr_skiplist_pop()
+ * which does use any compare function). It is meant to return 0 when a == b,
+ * <0 when a < b, and >0 when a > b. However apr_skiplist_insert() will not
+ * add duplicates (i.e. a == b), and apr_skiplist_add() is only available in
+ * APR 1.6, yet multiple timers could possibly be created in the same micro-
+ * second (duplicates with regard to apr_time_t); therefore we implement the
+ * compare function to return +1 instead of 0 when compared timers are equal,
+ * thus duplicates are still added after each other (in order of insertion).
+ */
+static int timer_comp(void *a, void *b)
{
- apr_time_t t1 = (apr_time_t) (((timer_event_t *) a)->when);
- apr_time_t t2 = (apr_time_t) (((timer_event_t *) b)->when);
+ apr_time_t t1 = (apr_time_t) ((timer_event_t *)a)->when;
+ apr_time_t t2 = (apr_time_t) ((timer_event_t *)b)->when;
AP_DEBUG_ASSERT(t1);
AP_DEBUG_ASSERT(t2);
- return ((t1 < t2) ? -1 : ((t1 > t2) ? 1 : 0));
-}
-
-static int indexing_compk(void *ac, void *b)
-{
- apr_time_t *t1 = (apr_time_t *) ac;
- apr_time_t t2 = (apr_time_t) (((timer_event_t *) b)->when);
- AP_DEBUG_ASSERT(t2);
- return ((*t1 < t2) ? -1 : ((*t1 > t2) ? 1 : 0));
+ return ((t1 < t2) ? -1 : 1);
}
static apr_thread_mutex_t *g_timer_skiplist_mtx;
/* XXXXX: optimize */
te->when = t + apr_time_now();
- /* Okay, insert sorted by when.. */
- apr_skiplist_insert(timer_skiplist, (void *)te);
+ /* Okay, add sorted by when.. */
+ apr_skiplist_insert(timer_skiplist, te);
apr_thread_mutex_unlock(g_timer_skiplist_mtx);
apr_thread_mutex_create(&g_timer_skiplist_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
APR_RING_INIT(&timer_free_ring, timer_event_t, link);
apr_skiplist_init(&timer_skiplist, pchild);
- apr_skiplist_set_compare(timer_skiplist, indexing_comp, indexing_compk);
+ apr_skiplist_set_compare(timer_skiplist, timer_comp, timer_comp);
ap_run_child_init(pchild, ap_server_conf);
/* done with init critical section */