b081c245fd
MFC after: 2 weeks X-MFC-With: r361677
382 lines
14 KiB
C
382 lines
14 KiB
C
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef APR_SKIPLIST_H
|
|
#define APR_SKIPLIST_H
|
|
/**
|
|
* @file apr_skiplist.h
|
|
* @brief APR skip list implementation
|
|
*/
|
|
|
|
#include "apr.h"
|
|
#include "apr_portable.h"
|
|
#include <stdlib.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
/**
|
|
* @defgroup apr_skiplist Skip list implementation
|
|
* Refer to http://en.wikipedia.org/wiki/Skip_list for information
|
|
* about the purpose of and ideas behind skip lists.
|
|
* @ingroup APR
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* apr_skiplist_compare is the function type that must be implemented
|
|
* per object type that is used in a skip list for comparisons to maintain
|
|
* order
|
|
* */
|
|
typedef int (*apr_skiplist_compare) (void *, void *);
|
|
|
|
/**
|
|
* apr_skiplist_freefunc is the function type that must be implemented
|
|
* to handle elements as they are removed from a skip list.
|
|
*/
|
|
typedef void (*apr_skiplist_freefunc) (void *);
|
|
|
|
/** Opaque structure used to represent the skip list */
|
|
struct apr_skiplist;
|
|
/** Opaque structure used to represent the skip list */
|
|
typedef struct apr_skiplist apr_skiplist;
|
|
|
|
/**
|
|
* Opaque structure used to represent abstract nodes in the skip list
|
|
* (an abstraction above the raw elements which are collected in the
|
|
* skip list).
|
|
*/
|
|
struct apr_skiplistnode;
|
|
/** Opaque structure */
|
|
typedef struct apr_skiplistnode apr_skiplistnode;
|
|
|
|
/**
|
|
* Allocate memory using the same mechanism as the skip list.
|
|
* @param sl The skip list
|
|
* @param size The amount to allocate
|
|
* @remark If a pool was provided to apr_skiplist_init(), memory will
|
|
* be allocated from the pool or from a free list maintained with
|
|
* the skip list. Otherwise, memory will be allocated using the
|
|
* C standard library heap functions.
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_alloc(apr_skiplist *sl, size_t size);
|
|
|
|
/**
|
|
* Free memory using the same mechanism as the skip list.
|
|
* @param sl The skip list
|
|
* @param mem The object to free
|
|
* @remark If a pool was provided to apr_skiplist_init(), memory will
|
|
* be added to a free list maintained with the skip list and be available
|
|
* to operations on the skip list or to other calls to apr_skiplist_alloc().
|
|
* Otherwise, memory will be freed using the C standard library heap
|
|
* functions.
|
|
*/
|
|
APR_DECLARE(void) apr_skiplist_free(apr_skiplist *sl, void *mem);
|
|
|
|
/**
|
|
* Allocate a new skip list
|
|
* @param sl The pointer in which to return the newly created skip list
|
|
* @param p The pool from which to allocate the skip list (optional).
|
|
* @remark Unlike most APR functions, a pool is optional. If no pool
|
|
* is provided, the C standard library heap functions will be used instead.
|
|
*/
|
|
APR_DECLARE(apr_status_t) apr_skiplist_init(apr_skiplist **sl, apr_pool_t *p);
|
|
|
|
/**
|
|
* Set the comparison functions to be used for searching the skip list.
|
|
* @param sl The skip list
|
|
* @param XXX1 FIXME
|
|
* @param XXX2 FIXME
|
|
*
|
|
* @remark If existing comparison functions are being replaced, the index
|
|
* will be replaced during this call. That is a potentially expensive
|
|
* operation.
|
|
*/
|
|
APR_DECLARE(void) apr_skiplist_set_compare(apr_skiplist *sl, apr_skiplist_compare XXX1,
|
|
apr_skiplist_compare XXX2);
|
|
|
|
/**
|
|
* Set the indexing functions to the specified comparison functions and
|
|
* rebuild the index.
|
|
* @param sl The skip list
|
|
* @param XXX1 FIXME
|
|
* @param XXX2 FIXME
|
|
*
|
|
* @remark If an index already exists, it will not be replaced and the
|
|
* comparison functions will not be changed.
|
|
*/
|
|
APR_DECLARE(void) apr_skiplist_add_index(apr_skiplist *sl, apr_skiplist_compare XXX1,
|
|
apr_skiplist_compare XXX2);
|
|
|
|
/**
|
|
* Return the list maintained by the skip list abstraction.
|
|
* @param sl The skip list
|
|
*/
|
|
APR_DECLARE(apr_skiplistnode *) apr_skiplist_getlist(apr_skiplist *sl);
|
|
|
|
/**
|
|
* Return the next matching element in the skip list using the specified
|
|
* comparison function.
|
|
* @param sl The skip list
|
|
* @param data The value to search for
|
|
* @param iter A pointer to the returned skip list node representing the element
|
|
* found
|
|
* @param func The comparison function to use
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_find_compare(apr_skiplist *sl,
|
|
void *data,
|
|
apr_skiplistnode **iter,
|
|
apr_skiplist_compare func);
|
|
|
|
/**
|
|
* Return the next matching element in the skip list using the current comparison
|
|
* function.
|
|
* @param sl The skip list
|
|
* @param data The value to search for
|
|
* @param iter A pointer to the returned skip list node representing the element
|
|
* found
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_find(apr_skiplist *sl, void *data, apr_skiplistnode **iter);
|
|
|
|
/**
|
|
* Return the last matching element in the skip list using the specified
|
|
* comparison function.
|
|
* @param sl The skip list
|
|
* @param data The value to search for
|
|
* @param iter A pointer to the returned skip list node representing the element
|
|
* found
|
|
* @param comp The comparison function to use
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_last_compare(apr_skiplist *sl, void *data,
|
|
apr_skiplistnode **iter,
|
|
apr_skiplist_compare comp);
|
|
|
|
/**
|
|
* Return the last matching element in the skip list using the current comparison
|
|
* function.
|
|
* @param sl The skip list
|
|
* @param data The value to search for
|
|
* @param iter A pointer to the returned skip list node representing the element
|
|
* found
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_last(apr_skiplist *sl, void *data,
|
|
apr_skiplistnode **iter);
|
|
|
|
/**
|
|
* Return the next element in the skip list.
|
|
* @param sl The skip list
|
|
* @param iter On entry, a pointer to the skip list node to start with; on return,
|
|
* a pointer to the skip list node representing the element returned
|
|
* @remark If iter points to a NULL value on entry, NULL will be returned.
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_next(apr_skiplist *sl, apr_skiplistnode **iter);
|
|
|
|
/**
|
|
* Return the previous element in the skip list.
|
|
* @param sl The skip list
|
|
* @param iter On entry, a pointer to the skip list node to start with; on return,
|
|
* a pointer to the skip list node representing the element returned
|
|
* @remark If iter points to a NULL value on entry, NULL will be returned.
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_previous(apr_skiplist *sl, apr_skiplistnode **iter);
|
|
|
|
/**
|
|
* Return the element of the skip list node
|
|
* @param iter The skip list node
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_element(apr_skiplistnode *iter);
|
|
|
|
/**
|
|
* Insert an element into the skip list using the specified comparison function
|
|
* if it does not already exist.
|
|
* @param sl The skip list
|
|
* @param data The element to insert
|
|
* @param comp The comparison function to use for placement into the skip list
|
|
*/
|
|
APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert_compare(apr_skiplist *sl,
|
|
void *data, apr_skiplist_compare comp);
|
|
|
|
/**
|
|
* Insert an element into the skip list using the existing comparison function
|
|
* if it does not already exist.
|
|
* @param sl The skip list
|
|
* @param data The element to insert
|
|
* @remark If no comparison function has been set for the skip list, the element
|
|
* will not be inserted and NULL will be returned.
|
|
*/
|
|
APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist* sl, void *data);
|
|
|
|
/**
|
|
* Add an element into the skip list using the specified comparison function
|
|
* allowing for duplicates.
|
|
* @param sl The skip list
|
|
* @param data The element to add
|
|
* @param comp The comparison function to use for placement into the skip list
|
|
*/
|
|
APR_DECLARE(apr_skiplistnode *) apr_skiplist_add_compare(apr_skiplist *sl,
|
|
void *data, apr_skiplist_compare comp);
|
|
|
|
/**
|
|
* Add an element into the skip list using the existing comparison function
|
|
* allowing for duplicates.
|
|
* @param sl The skip list
|
|
* @param data The element to insert
|
|
* @remark If no comparison function has been set for the skip list, the element
|
|
* will not be inserted and NULL will be returned.
|
|
*/
|
|
APR_DECLARE(apr_skiplistnode *) apr_skiplist_add(apr_skiplist* sl, void *data);
|
|
|
|
/**
|
|
* Add an element into the skip list using the specified comparison function
|
|
* removing the existing duplicates.
|
|
* @param sl The skip list
|
|
* @param data The element to insert
|
|
* @param comp The comparison function to use for placement into the skip list
|
|
* @param myfree A function to be called for each removed duplicate
|
|
* @remark If no comparison function has been set for the skip list, the element
|
|
* will not be inserted, none will be replaced, and NULL will be returned.
|
|
*/
|
|
APR_DECLARE(apr_skiplistnode *) apr_skiplist_replace_compare(apr_skiplist *sl,
|
|
void *data, apr_skiplist_freefunc myfree,
|
|
apr_skiplist_compare comp);
|
|
|
|
/**
|
|
* Add an element into the skip list using the existing comparison function
|
|
* removing the existing duplicates.
|
|
* @param sl The skip list
|
|
* @param data The element to insert
|
|
* @param myfree A function to be called for each removed duplicate
|
|
* @remark If no comparison function has been set for the skip list, the element
|
|
* will not be inserted, none will be replaced, and NULL will be returned.
|
|
*/
|
|
APR_DECLARE(apr_skiplistnode *) apr_skiplist_replace(apr_skiplist *sl,
|
|
void *data, apr_skiplist_freefunc myfree);
|
|
|
|
/**
|
|
* Remove a node from the skip list.
|
|
* @param sl The skip list
|
|
* @param iter The skip list node to remove
|
|
* @param myfree A function to be called for the removed element
|
|
*/
|
|
APR_DECLARE(int) apr_skiplist_remove_node(apr_skiplist *sl,
|
|
apr_skiplistnode *iter,
|
|
apr_skiplist_freefunc myfree);
|
|
|
|
/**
|
|
* Remove an element from the skip list using the specified comparison function for
|
|
* locating the element. In the case of duplicates, the 1st entry will be removed.
|
|
* @param sl The skip list
|
|
* @param data The element to remove
|
|
* @param myfree A function to be called for each removed element
|
|
* @param comp The comparison function to use for placement into the skip list
|
|
* @remark If the element is not found, 0 will be returned. Otherwise, the heightXXX
|
|
* will be returned.
|
|
*/
|
|
APR_DECLARE(int) apr_skiplist_remove_compare(apr_skiplist *sl, void *data,
|
|
apr_skiplist_freefunc myfree, apr_skiplist_compare comp);
|
|
|
|
/**
|
|
* Remove an element from the skip list using the existing comparison function for
|
|
* locating the element. In the case of duplicates, the 1st entry will be removed.
|
|
* @param sl The skip list
|
|
* @param data The element to remove
|
|
* @param myfree A function to be called for each removed element
|
|
* @remark If the element is not found, 0 will be returned. Otherwise, the heightXXX
|
|
* will be returned.
|
|
* @remark If no comparison function has been set for the skip list, the element
|
|
* will not be removed and 0 will be returned.
|
|
*/
|
|
APR_DECLARE(int) apr_skiplist_remove(apr_skiplist *sl, void *data, apr_skiplist_freefunc myfree);
|
|
|
|
/**
|
|
* Remove all elements from the skip list.
|
|
* @param sl The skip list
|
|
* @param myfree A function to be called for each removed element
|
|
*/
|
|
APR_DECLARE(void) apr_skiplist_remove_all(apr_skiplist *sl, apr_skiplist_freefunc myfree);
|
|
|
|
/**
|
|
* Remove each element from the skip list.
|
|
* @param sl The skip list
|
|
* @param myfree A function to be called for each removed element
|
|
*/
|
|
APR_DECLARE(void) apr_skiplist_destroy(apr_skiplist *sl, apr_skiplist_freefunc myfree);
|
|
|
|
/**
|
|
* Return the first element in the skip list, removing the element from the skip list.
|
|
* @param sl The skip list
|
|
* @param myfree A function to be called for the removed element
|
|
* @remark NULL will be returned if there are no elements
|
|
*/
|
|
APR_DECLARE(void *) apr_skiplist_pop(apr_skiplist *sl, apr_skiplist_freefunc myfree);
|
|
|
|
/**
|
|
* Return the first element in the skip list, leaving the element in the skip list.
|
|
* @param sl The skip list
|
|
* @remark NULL will be returned if there are no elements
|
|
*/
|
|
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
|
|
*/
|
|
APR_DECLARE(apr_skiplist *) apr_skiplist_merge(apr_skiplist *sl1, apr_skiplist *sl2);
|
|
|
|
/** @} */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* ! APR_SKIPLIST_H */
|