155
static apr_status_t skiplist_qpush(apr_skiplist_q *q, apr_skiplistnode *m)
157
if (q->pos >= q->size) {
158
apr_skiplistnode **data;
159
size_t size = (q->pos) ? q->pos * 2 : 32;
161
data = apr_palloc(q->p, size * sizeof(*data));
163
memcpy(data, q->data, q->pos * sizeof(*data));
167
data = realloc(q->data, size * sizeof(*data));
175
q->data[q->pos++] = m;
179
static APR_INLINE apr_skiplistnode *skiplist_qpop(apr_skiplist_q *q)
181
return (q->pos > 0) ? q->data[--q->pos] : NULL;
184
static APR_INLINE void skiplist_qclear(apr_skiplist_q *q)
189
static apr_skiplistnode *skiplist_new_node(apr_skiplist *sl)
191
apr_skiplistnode *m = skiplist_qpop(&sl->nodes_q);
194
m = apr_palloc(sl->pool, sizeof *m);
197
m = malloc(sizeof *m);
203
static apr_status_t skiplist_free_node(apr_skiplist *sl, apr_skiplistnode *m)
205
return skiplist_qpush(&sl->nodes_q, m);
152
208
static apr_status_t skiplisti_init(apr_skiplist **s, apr_pool_t *p)
154
210
apr_skiplist *sl;
156
212
sl = apr_pcalloc(p, sizeof(apr_skiplist));
157
213
sl->memlist = apr_array_make(p, 20, sizeof(memlist_t));
214
sl->pool = sl->nodes_q.p = sl->stack_q.p = p;
160
217
sl = calloc(1, sizeof(apr_skiplist));
163
sl->compare = (apr_skiplist_compare) NULL;
164
sl->comparek = (apr_skiplist_compare) NULL;
174
223
return APR_SUCCESS;
251
APR_DECLARE(apr_skiplistnode *) apr_skiplist_getlist(apr_skiplist *sl)
256
return sl->bottom->next;
259
APR_DECLARE(void *) apr_skiplist_find(apr_skiplist *sl, void *data, apr_skiplistnode **iter)
262
apr_skiplistnode *aiter;
267
ret = apr_skiplist_find_compare(sl, data, iter, sl->compare);
270
ret = apr_skiplist_find_compare(sl, data, &aiter, sl->compare);
275
300
static int skiplisti_find_compare(apr_skiplist *sl, void *data,
276
301
apr_skiplistnode **ret,
277
302
apr_skiplist_compare comp)
279
apr_skiplistnode *m = NULL;
284
compared = (m->next) ? comp(data, m->next->data) : -1;
293
if ((m->next == NULL) || (compared < 0)) {
309
int compared = comp(data, m->next->data);
307
332
apr_skiplistnode **iter,
308
333
apr_skiplist_compare comp)
310
apr_skiplistnode *m = NULL;
311
336
apr_skiplist *sl;
312
343
if (comp == sli->compare || !sli->index) {
316
347
apr_skiplist_find(sli->index, (void *)comp, &m);
317
354
sl = (apr_skiplist *) m->data;
319
skiplisti_find_compare(sl, data, iter, sl->comparek);
320
return (iter && *iter) ? ((*iter)->data) : NULL;
356
skiplisti_find_compare(sl, data, &m, sl->comparek);
360
return (m) ? m->data : NULL;
363
APR_DECLARE(void *) apr_skiplist_find(apr_skiplist *sl, void *data, apr_skiplistnode **iter)
365
return apr_skiplist_find_compare(sl, data, iter, sl->compare);
369
APR_DECLARE(apr_skiplistnode *) apr_skiplist_getlist(apr_skiplist *sl)
374
return sl->bottom->next;
324
377
APR_DECLARE(void *) apr_skiplist_next(apr_skiplist *sl, apr_skiplistnode **iter)
339
392
return (*iter) ? ((*iter)->data) : NULL;
342
APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist *sl, void *data)
395
static APR_INLINE int skiplist_height(const apr_skiplist *sl)
347
return apr_skiplist_insert_compare(sl, data, sl->compare);
397
/* Skiplists (even empty) always have a top node, although this
398
* implementation defers its creation until the first insert, or
399
* deletes it with the last remove. We want the real height here.
401
return sl->height ? sl->height : 1;
350
404
APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert_compare(apr_skiplist *sl, void *data,
351
405
apr_skiplist_compare comp)
353
apr_skiplistnode *m, *p, *tmp, *ret = NULL, **stack;
354
int nh = 1, ch, stacki;
357
sl->topend = sl->bottomend = sl->top = sl->bottom =
358
(apr_skiplistnode *)apr_skiplist_alloc(sl, sizeof(apr_skiplistnode));
360
sl->top->next = (apr_skiplistnode *)NULL;
361
sl->top->data = (apr_skiplistnode *)NULL;
362
sl->top->prev = (apr_skiplistnode *)NULL;
363
sl->top->up = (apr_skiplistnode *)NULL;
364
sl->top->down = (apr_skiplistnode *)NULL;
365
sl->top->nextindex = (apr_skiplistnode *)NULL;
366
sl->top->previndex = (apr_skiplistnode *)NULL;
407
apr_skiplistnode *m, *p, *tmp, *ret = NULL;
414
ch = skiplist_height(sl);
370
415
if (sl->preheight) {
371
416
while (nh < sl->preheight && get_b_rand()) {
376
while (nh <= sl->height && get_b_rand()) {
421
while (nh <= ch && get_b_rand()) {
380
/* Now we have the new height at which we wish to insert our new node */
382
* Let us make sure that our tree is a least that tall (grow if
426
/* Now we have in nh the height at which we wish to insert our new node,
427
* and in ch the current height: don't create skip paths to the inserted
428
* element until the walk down through the tree (which decrements ch)
429
* reaches nh. From there, any walk down pushes the current node on a
430
* stack (the node(s) after which we would insert) to pop back through
431
* for insertion later.
385
for (; sl->height < nh; sl->height++) {
387
(apr_skiplistnode *)apr_skiplist_alloc(sl, sizeof(apr_skiplistnode));
388
sl->top->up->down = sl->top;
389
sl->top = sl->topend = sl->top->up;
391
sl->top->prev = sl->top->next = sl->top->nextindex =
392
sl->top->previndex = sl->top->up = NULL;
393
sl->top->data = NULL;
398
/* Find the node (or node after which we would insert) */
399
/* Keep a stack to pop back through for insertion */
400
/* malloc() is OK since we free the temp stack */
402
stack = (apr_skiplistnode **)malloc(sizeof(apr_skiplistnode *) * (nh));
407
compared = comp(data, m->next->data);
410
free(stack); /* OK. was malloc'ed */
413
if ((m->next == NULL) || (compared < 0)) {
436
int compared = comp(data, m->next->data);
438
/* Keep the existing element(s) */
439
skiplist_qclear(&sl->stack_q);
449
skiplist_qpush(&sl->stack_q, m);
425
454
/* Pop the stack and insert nodes */
427
for (; stacki > 0; stacki--) {
428
m = stack[stacki - 1];
429
tmp = (apr_skiplistnode *)apr_skiplist_alloc(sl, sizeof(apr_skiplistnode));
456
while ((m = skiplist_qpop(&sl->stack_q))) {
457
tmp = skiplist_new_node(sl);
430
458
tmp->next = m->next;
432
460
m->next->prev = tmp;
436
465
tmp->nextindex = tmp->previndex = NULL;
471
/* This sets ret to the bottom-most node we are inserting */
441
474
tmp->data = data;
479
/* Now we are sure the node is inserted, grow our tree to 'nh' tall */
480
for (; sl->height < nh; sl->height++) {
481
m = skiplist_new_node(sl);
482
tmp = skiplist_new_node(sl);
483
m->up = m->prev = m->nextindex = m->previndex = NULL;
444
/* This sets ret to the bottom-most node we are inserting */
492
sl->bottom = sl->bottomend = m;
494
sl->top = sl->topend = tmp->prev = m;
495
tmp->up = tmp->next = tmp->nextindex = tmp->previndex = NULL;
503
/* This sets ret to the bottom-most node we are inserting */
447
sl->size++; /* this seems to go here got each element to be counted */
451
free(stack); /* OK. was malloc'ed */
452
508
if (sl->index != NULL) {
454
510
* this is a external insertion, we must insert into each index as
457
513
apr_skiplistnode *ni, *li;
459
515
for (p = apr_skiplist_getlist(sl->index); p; apr_skiplist_next(sl->index, &p)) {
460
ni = apr_skiplist_insert((apr_skiplist *) p->data, ret->data);
516
apr_skiplist *sli = (apr_skiplist *)p->data;
517
ni = apr_skiplist_insert_compare(sli, ret->data, sli->compare);
461
518
li->nextindex = ni;
462
519
ni->previndex = li;
473
APR_DECLARE(int) apr_skiplist_remove(apr_skiplist *sl, void *data, apr_skiplist_freefunc myfree)
527
APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist *sl, void *data)
478
return apr_skiplist_remove_compare(sl, data, myfree, sl->comparek);
529
return apr_skiplist_insert_compare(sl, data, sl->compare);