xf86drmSL.c revision e6188e58
122944501Smrg/* xf86drmSL.c -- Skip list support
222944501Smrg * Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com
322944501Smrg *
422944501Smrg * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
522944501Smrg * All Rights Reserved.
622944501Smrg *
722944501Smrg * Permission is hereby granted, free of charge, to any person obtaining a
822944501Smrg * copy of this software and associated documentation files (the "Software"),
922944501Smrg * to deal in the Software without restriction, including without limitation
1022944501Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1122944501Smrg * and/or sell copies of the Software, and to permit persons to whom the
1222944501Smrg * Software is furnished to do so, subject to the following conditions:
1322944501Smrg *
1422944501Smrg * The above copyright notice and this permission notice (including the next
1522944501Smrg * paragraph) shall be included in all copies or substantial portions of the
1622944501Smrg * Software.
1722944501Smrg *
1822944501Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1922944501Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2022944501Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2122944501Smrg * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2222944501Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2322944501Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2422944501Smrg * DEALINGS IN THE SOFTWARE.
2522944501Smrg *
2622944501Smrg * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
2722944501Smrg *
2822944501Smrg * DESCRIPTION
2922944501Smrg *
3022944501Smrg * This file contains a straightforward skip list implementation.n
3122944501Smrg *
3222944501Smrg * FUTURE ENHANCEMENTS
3322944501Smrg *
3422944501Smrg * REFERENCES
3522944501Smrg *
3622944501Smrg * [Pugh90] William Pugh.  Skip Lists: A Probabilistic Alternative to
3722944501Smrg * Balanced Trees. CACM 33(6), June 1990, pp. 668-676.
3822944501Smrg *
3922944501Smrg */
4022944501Smrg
4122944501Smrg#include <stdio.h>
4222944501Smrg#include <stdlib.h>
4322944501Smrg
44e6188e58Smrg#include "xf86drm.h"
4522944501Smrg
4622944501Smrg#define SL_LIST_MAGIC  0xfacade00LU
4722944501Smrg#define SL_ENTRY_MAGIC 0x00fab1edLU
4822944501Smrg#define SL_FREED_MAGIC 0xdecea5edLU
4922944501Smrg#define SL_MAX_LEVEL   16
5022944501Smrg#define SL_RANDOM_SEED 0xc01055a1LU
5122944501Smrg
5222944501Smrg#define SL_RANDOM_DECL        static void *state = NULL
5322944501Smrg#define SL_RANDOM_INIT(seed)  if (!state) state = drmRandomCreate(seed)
5422944501Smrg#define SL_RANDOM             drmRandom(state)
5522944501Smrg
5622944501Smrgtypedef struct SLEntry {
5722944501Smrg    unsigned long     magic;	   /* SL_ENTRY_MAGIC */
5822944501Smrg    unsigned long     key;
5922944501Smrg    void              *value;
6022944501Smrg    int               levels;
6122944501Smrg    struct SLEntry    *forward[1]; /* variable sized array */
6222944501Smrg} SLEntry, *SLEntryPtr;
6322944501Smrg
6422944501Smrgtypedef struct SkipList {
6522944501Smrg    unsigned long    magic;	/* SL_LIST_MAGIC */
6622944501Smrg    int              level;
6722944501Smrg    int              count;
6822944501Smrg    SLEntryPtr       head;
6922944501Smrg    SLEntryPtr       p0;	/* Position for iteration */
7022944501Smrg} SkipList, *SkipListPtr;
7122944501Smrg
7222944501Smrgstatic SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value)
7322944501Smrg{
7422944501Smrg    SLEntryPtr entry;
7522944501Smrg
7622944501Smrg    if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL;
7722944501Smrg
78e6188e58Smrg    entry         = drmMalloc(sizeof(*entry)
7922944501Smrg			     + (max_level + 1) * sizeof(entry->forward[0]));
8022944501Smrg    if (!entry) return NULL;
8122944501Smrg    entry->magic  = SL_ENTRY_MAGIC;
8222944501Smrg    entry->key    = key;
8322944501Smrg    entry->value  = value;
8422944501Smrg    entry->levels = max_level + 1;
8522944501Smrg
8622944501Smrg    return entry;
8722944501Smrg}
8822944501Smrg
8922944501Smrgstatic int SLRandomLevel(void)
9022944501Smrg{
9122944501Smrg    int level = 1;
9222944501Smrg    SL_RANDOM_DECL;
9322944501Smrg
9422944501Smrg    SL_RANDOM_INIT(SL_RANDOM_SEED);
9522944501Smrg
9622944501Smrg    while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level;
9722944501Smrg    return level;
9822944501Smrg}
9922944501Smrg
10022944501Smrgvoid *drmSLCreate(void)
10122944501Smrg{
10222944501Smrg    SkipListPtr  list;
10322944501Smrg    int          i;
10422944501Smrg
105e6188e58Smrg    list           = drmMalloc(sizeof(*list));
10622944501Smrg    if (!list) return NULL;
10722944501Smrg    list->magic    = SL_LIST_MAGIC;
10822944501Smrg    list->level    = 0;
10922944501Smrg    list->head     = SLCreateEntry(SL_MAX_LEVEL, 0, NULL);
11022944501Smrg    list->count    = 0;
11122944501Smrg
11222944501Smrg    for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL;
11322944501Smrg
11422944501Smrg    return list;
11522944501Smrg}
11622944501Smrg
11722944501Smrgint drmSLDestroy(void *l)
11822944501Smrg{
11922944501Smrg    SkipListPtr   list  = (SkipListPtr)l;
12022944501Smrg    SLEntryPtr    entry;
12122944501Smrg    SLEntryPtr    next;
12222944501Smrg
12322944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
12422944501Smrg
12522944501Smrg    for (entry = list->head; entry; entry = next) {
12622944501Smrg	if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */
12722944501Smrg	next         = entry->forward[0];
12822944501Smrg	entry->magic = SL_FREED_MAGIC;
129e6188e58Smrg	drmFree(entry);
13022944501Smrg    }
13122944501Smrg
13222944501Smrg    list->magic = SL_FREED_MAGIC;
133e6188e58Smrg    drmFree(list);
13422944501Smrg    return 0;
13522944501Smrg}
13622944501Smrg
13722944501Smrgstatic SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update)
13822944501Smrg{
13922944501Smrg    SkipListPtr   list  = (SkipListPtr)l;
14022944501Smrg    SLEntryPtr    entry;
14122944501Smrg    int           i;
14222944501Smrg
14322944501Smrg    if (list->magic != SL_LIST_MAGIC) return NULL;
14422944501Smrg
14522944501Smrg    for (i = list->level, entry = list->head; i >= 0; i--) {
14622944501Smrg	while (entry->forward[i] && entry->forward[i]->key < key)
14722944501Smrg	    entry = entry->forward[i];
14822944501Smrg	update[i] = entry;
14922944501Smrg    }
15022944501Smrg
15122944501Smrg    return entry->forward[0];
15222944501Smrg}
15322944501Smrg
15422944501Smrgint drmSLInsert(void *l, unsigned long key, void *value)
15522944501Smrg{
15622944501Smrg    SkipListPtr   list  = (SkipListPtr)l;
15722944501Smrg    SLEntryPtr    entry;
15822944501Smrg    SLEntryPtr    update[SL_MAX_LEVEL + 1];
15922944501Smrg    int           level;
16022944501Smrg    int           i;
16122944501Smrg
16222944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
16322944501Smrg
16422944501Smrg    entry = SLLocate(list, key, update);
16522944501Smrg
16622944501Smrg    if (entry && entry->key == key) return 1; /* Already in list */
16722944501Smrg
16822944501Smrg
16922944501Smrg    level = SLRandomLevel();
17022944501Smrg    if (level > list->level) {
17122944501Smrg	level = ++list->level;
17222944501Smrg	update[level] = list->head;
17322944501Smrg    }
17422944501Smrg
17522944501Smrg    entry = SLCreateEntry(level, key, value);
17622944501Smrg
17722944501Smrg				/* Fix up forward pointers */
17822944501Smrg    for (i = 0; i <= level; i++) {
17922944501Smrg	entry->forward[i]     = update[i]->forward[i];
18022944501Smrg	update[i]->forward[i] = entry;
18122944501Smrg    }
18222944501Smrg
18322944501Smrg    ++list->count;
18422944501Smrg    return 0;			/* Added to table */
18522944501Smrg}
18622944501Smrg
18722944501Smrgint drmSLDelete(void *l, unsigned long key)
18822944501Smrg{
18922944501Smrg    SkipListPtr   list = (SkipListPtr)l;
19022944501Smrg    SLEntryPtr    update[SL_MAX_LEVEL + 1];
19122944501Smrg    SLEntryPtr    entry;
19222944501Smrg    int           i;
19322944501Smrg
19422944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
19522944501Smrg
19622944501Smrg    entry = SLLocate(list, key, update);
19722944501Smrg
19822944501Smrg    if (!entry || entry->key != key) return 1; /* Not found */
19922944501Smrg
20022944501Smrg				/* Fix up forward pointers */
20122944501Smrg    for (i = 0; i <= list->level; i++) {
20222944501Smrg	if (update[i]->forward[i] == entry)
20322944501Smrg	    update[i]->forward[i] = entry->forward[i];
20422944501Smrg    }
20522944501Smrg
20622944501Smrg    entry->magic = SL_FREED_MAGIC;
207e6188e58Smrg    drmFree(entry);
20822944501Smrg
20922944501Smrg    while (list->level && !list->head->forward[list->level]) --list->level;
21022944501Smrg    --list->count;
21122944501Smrg    return 0;
21222944501Smrg}
21322944501Smrg
21422944501Smrgint drmSLLookup(void *l, unsigned long key, void **value)
21522944501Smrg{
21622944501Smrg    SkipListPtr   list = (SkipListPtr)l;
21722944501Smrg    SLEntryPtr    update[SL_MAX_LEVEL + 1];
21822944501Smrg    SLEntryPtr    entry;
21922944501Smrg
22022944501Smrg    entry = SLLocate(list, key, update);
22122944501Smrg
22222944501Smrg    if (entry && entry->key == key) {
22322944501Smrg	*value = entry;
22422944501Smrg	return 0;
22522944501Smrg    }
22622944501Smrg    *value = NULL;
22722944501Smrg    return -1;
22822944501Smrg}
22922944501Smrg
23022944501Smrgint drmSLLookupNeighbors(void *l, unsigned long key,
23122944501Smrg			 unsigned long *prev_key, void **prev_value,
23222944501Smrg			 unsigned long *next_key, void **next_value)
23322944501Smrg{
23422944501Smrg    SkipListPtr   list = (SkipListPtr)l;
235e6188e58Smrg    SLEntryPtr    update[SL_MAX_LEVEL + 1] = {0};
23622944501Smrg    int           retcode = 0;
23722944501Smrg
238e6188e58Smrg    SLLocate(list, key, update);
239e6188e58Smrg
24022944501Smrg    *prev_key   = *next_key   = key;
24122944501Smrg    *prev_value = *next_value = NULL;
242e6188e58Smrg
24322944501Smrg    if (update[0]) {
24422944501Smrg	*prev_key   = update[0]->key;
24522944501Smrg	*prev_value = update[0]->value;
24622944501Smrg	++retcode;
24722944501Smrg	if (update[0]->forward[0]) {
24822944501Smrg	    *next_key   = update[0]->forward[0]->key;
24922944501Smrg	    *next_value = update[0]->forward[0]->value;
25022944501Smrg	    ++retcode;
25122944501Smrg	}
25222944501Smrg    }
25322944501Smrg    return retcode;
25422944501Smrg}
25522944501Smrg
25622944501Smrgint drmSLNext(void *l, unsigned long *key, void **value)
25722944501Smrg{
25822944501Smrg    SkipListPtr   list = (SkipListPtr)l;
25922944501Smrg    SLEntryPtr    entry;
26022944501Smrg
26122944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
26222944501Smrg
26322944501Smrg    entry    = list->p0;
26422944501Smrg
26522944501Smrg    if (entry) {
26622944501Smrg	list->p0 = entry->forward[0];
26722944501Smrg	*key     = entry->key;
26822944501Smrg	*value   = entry->value;
26922944501Smrg	return 1;
27022944501Smrg    }
27122944501Smrg    list->p0 = NULL;
27222944501Smrg    return 0;
27322944501Smrg}
27422944501Smrg
27522944501Smrgint drmSLFirst(void *l, unsigned long *key, void **value)
27622944501Smrg{
27722944501Smrg    SkipListPtr   list = (SkipListPtr)l;
27822944501Smrg
27922944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
28022944501Smrg
28122944501Smrg    list->p0 = list->head->forward[0];
28222944501Smrg    return drmSLNext(list, key, value);
28322944501Smrg}
28422944501Smrg
28522944501Smrg/* Dump internal data structures for debugging. */
28622944501Smrgvoid drmSLDump(void *l)
28722944501Smrg{
28822944501Smrg    SkipListPtr   list = (SkipListPtr)l;
28922944501Smrg    SLEntryPtr    entry;
29022944501Smrg    int           i;
29122944501Smrg
29222944501Smrg    if (list->magic != SL_LIST_MAGIC) {
29322944501Smrg	printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
29422944501Smrg	       list->magic, SL_LIST_MAGIC);
29522944501Smrg	return;
29622944501Smrg    }
29722944501Smrg
29822944501Smrg    printf("Level = %d, count = %d\n", list->level, list->count);
29922944501Smrg    for (entry = list->head; entry; entry = entry->forward[0]) {
30022944501Smrg	if (entry->magic != SL_ENTRY_MAGIC) {
30122944501Smrg	    printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
30222944501Smrg		   list->magic, SL_ENTRY_MAGIC);
30322944501Smrg	}
30422944501Smrg	printf("\nEntry %p <0x%08lx, %p> has %2d levels\n",
30522944501Smrg	       entry, entry->key, entry->value, entry->levels);
30622944501Smrg	for (i = 0; i < entry->levels; i++) {
30722944501Smrg	    if (entry->forward[i]) {
30822944501Smrg		printf("   %2d: %p <0x%08lx, %p>\n",
30922944501Smrg		       i,
31022944501Smrg		       entry->forward[i],
31122944501Smrg		       entry->forward[i]->key,
31222944501Smrg		       entry->forward[i]->value);
31322944501Smrg	    } else {
31422944501Smrg		printf("   %2d: %p\n", i, entry->forward[i]);
31522944501Smrg	    }
31622944501Smrg	}
31722944501Smrg    }
31822944501Smrg}
319