/* * * Thread-safe Skiplist Using Integer Identifiers * Copyright 1998-2000 Scott Shambarger (scott@shambarger.net) * * This software is open source. Permission to use, copy, modify, and * distribute this software for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies. No * warranty of any kind is expressed or implied. Use at your own risk. * * 1/14/2001 blong * Made it use neo errs... probably need to check locking functions * for error returns... * */ #ifndef __SKIPLIST_H_ #define __SKIPLIST_H_ #include "util/neo_err.h" __BEGIN_DECLS /* * Larger values of <root> means fewer levels and faster lookups, * but more variability in those lookup times (range limited from 2 to 4). * * <maxLevel> should be calculated from expected list size using (^ = power): * * <root> ^ <maxLevel> == expected # of items * * I've capped <maxLevel> at 20, which would be good for a minimum of * 1 million items on lists with <root> == 2. * * * Example * skipNewList(&(my_wdb->ondisk), 0, 4, 2, 0, NULL, NULL); */ #define SKIP_MAXLEVEL 20 /* SKIP LIST TYPEDEFS */ typedef struct skipList_struct *skipList; typedef void (*skipFreeValue)(void *value, void *ctx); NEOERR *skipNewList(skipList *skip, int threaded, int root, int maxLevel, int flushLimit, skipFreeValue freeValue, void *ctx); /* * Function: skipNewList - create a skip list. * Description: Returns a new skip list. If <threaded> is true, list is * multi-thread safe. <root> and <maxLevel> determine * performance and expected size (see discussion above). * <flushLimit> is for threaded lists and determines the * maximum number of deleted items to keep cached during * concurrent searches. Once the limit is reached, new * concurrent reads are blocked until all deleted items are * flushed. * Input: threaded - true if list should be thread-safe. * root - performance parameter (see above). * maxLevel - performance parameter (see above). * flushLimit - max deleted items to keep cached before * forcing a flush. * freeValue - callback made whenever a value is flushed. * ctx - context to pass to <freeValue>. * Output: None. * Return: New skip list, NULL on error. * MT-Level: Safe. */ void skipFreeList(skipList list); /* * Function: skipFreeList - free a skip list. * Description: Release all resources used by <list> including all key/value * pairs. * Input: list - list to free. * Output: None. * Return: None. * MT-Level: Safe for unique <list>. */ void *skipNext(skipList list, UINT32 *pkey, void **plock); /* * Function: skipNext - find next item. * Description: Searches in list <list> for item with key next larger * that the one in <pkey>, and returns its value if * found, or NULL if not. If <plock> is non-NULL, then * the lock returned in <plock> will be associated with * the returned value. Until this lock is passed to * skipRelease(), the value will not be freed with the * freeValue callback (see skipNewList()). * Input: list - list to search in. * pkey - pointer to previous key (0 to start). * plock - place for value lock (or NULL). * Output: pkey - set to new key. * plock - set to value lock. * Return: Value associated with new <pkey>, or NULL last item. * MT-Level: Safe if <list> thread-safe. */ void *skipSearch(skipList list, UINT32 key, void **plock); /* * Function: skipSearch - search a skip list. * Description: Searches for <key> in <list>, and returns value if * found, or NULL if not. If <plock> is non-NULL, then * the lock returned in <plock> will be associated with * the returned value. Until this lock is passed to * skipRelease(), the value will not be freed with the * freeValue callback (see skipNewList()). * Input: list - list to search in. * key - key to look for. * plock - place for value lock (or NULL). * Output: plock - set to value lock. * Return: Value associated with <key>, or NULL if <key> not found. * MT-Level: Safe if <list> thread-safe. */ void skipRelease(skipList list, void *lock); /* * Function: skipRelease - release lock on value. * Description: Releases the lock on the value associated with <lock>. Once * the lock is released, the freeValue callback can be called * and the item freed (see skipNewList()). * Input: list - list containing value to release. * lock - lock to release. * Output: None. * Return: None. * MT-Level: Safe if <list> thread-safe. */ NEOERR *skipInsert(skipList list, UINT32 key, void *value, int allowUpdate); /* * Function: skipInsert - insert an item. * Description: Inserts the <key>/<value> pair into the <list>. * Key values 0 and -1 are reserved (and illegal). * If key is already in list, and <allowUpdate> is true, * value is updated, otherwise SKIPERR_EXISTS is returned. * Input: list - list to add pair to. * key - key identifying <value>. * value - value to store (may NOT be NULL) * Output: None. * Return: NERR_ASSERT on invalid key or value * NERR_DUPLICATE if allowUpdate is 0 and key exists * NERR_NOMEM * MT-Level: Safe if <list> thread-safe. */ void skipDelete(skipList list, UINT32 key); /* * Function: skipDelete - delete an item. * Description: Delete the item associated with <key> from <list>. * Input: list - list to delete item from. * key - key identifying value to delete. * Output: None. * Return: None. * MT-Level: Safe if <list> thread-safe. */ __END_DECLS #endif /* __SKIPLIST_H_ */