remove cruft, api TODOs
This commit is contained in:
parent
e8d3645ed4
commit
81d2f817f2
2 changed files with 304 additions and 344 deletions
|
@ -28,9 +28,21 @@ struct slex_node {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate all the access functions for our type of Skiplist.
|
* Generate all the access functions for our type of Skiplist.
|
||||||
* The last argument to this macro is a block of code used to
|
*/
|
||||||
* compare the nodes you defined above.
|
SKIPLIST_DECL(slex, api_, entries, { (void)node; })
|
||||||
* This block can expect four arguments:
|
|
||||||
|
/*
|
||||||
|
* Getter
|
||||||
|
* It can be useful to have simple get/put-style API, but to
|
||||||
|
* do that you'll have to supply some blocks of code used to
|
||||||
|
* extract data from within your nodes.
|
||||||
|
*/
|
||||||
|
SKIPLIST_GETTER(
|
||||||
|
slex, api_, get, int, int, { query.key = key; }, { return node->value; })
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we need a way to compare the nodes you defined above.
|
||||||
|
* Let's create a function with four arguments:
|
||||||
* - a reference to the Skiplist, `slist`
|
* - a reference to the Skiplist, `slist`
|
||||||
* - the two nodes to compare, `a` and `b`
|
* - the two nodes to compare, `a` and `b`
|
||||||
* - and `aux`, which you can use to pass into this function
|
* - and `aux`, which you can use to pass into this function
|
||||||
|
@ -38,18 +50,17 @@ struct slex_node {
|
||||||
* `aux` is passed from the value in the Skiplist, you can
|
* `aux` is passed from the value in the Skiplist, you can
|
||||||
* modify that value at any time to suit your needs.
|
* modify that value at any time to suit your needs.
|
||||||
*
|
*
|
||||||
* Your block should result in a return statement:
|
* Your function should result in a return statement:
|
||||||
* a < b : return -1
|
* a < b : return -1
|
||||||
* a == b : return 0
|
* a == b : return 0
|
||||||
* a > b : return 1
|
* a > b : return 1
|
||||||
*
|
*
|
||||||
* This result provides the ordering within the Skiplist. Sometimes
|
* This result provides the ordering within the Skiplist. Sometimes
|
||||||
* your block of code will not be used when comparing nodes. This
|
* your function will not be used when comparing nodes. This will
|
||||||
* happens when `a` or `b` are references to the head or tail of the
|
* happen when `a` or `b` are references to the head or tail of the
|
||||||
* list or when `a == b`. In those cases the comparison function
|
* list or when `a == b`. In those cases the comparison function
|
||||||
* returns before using the code in your block, don't panic. :)
|
* returns before using the code in your block, don't panic. :)
|
||||||
*/
|
*/
|
||||||
SKIPLIST_DECL(slex, api_, entries)
|
|
||||||
int
|
int
|
||||||
__slm_key_compare(slex_t *list, slex_node_t *a, slex_node_t *b, void *aux)
|
__slm_key_compare(slex_t *list, slex_node_t *a, slex_node_t *b, void *aux)
|
||||||
{
|
{
|
||||||
|
@ -85,12 +96,16 @@ main()
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
rc = api_skip_init_slex(list, 12, 4, __slm_key_compare);
|
rc = api_skip_init_slex(list, 12, 4, __slm_key_compare);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
struct slex_node *n;
|
struct slex_node *n;
|
||||||
|
|
||||||
/* Insert 7 key/value pairs into the list. */
|
/* Insert 7 key/value pairs into the list. */
|
||||||
for (int i = -2; i <= 2; i++) {
|
for (int i = -2; i <= 2; i++) {
|
||||||
SKIP_ALLOC_NODE(list, n, slex_node, entries);
|
rc = api_skip_alloc_node_slex(list, &n);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
n->key = i;
|
n->key = i;
|
||||||
n->value = i;
|
n->value = i;
|
||||||
api_skip_insert_slex(list, n);
|
api_skip_insert_slex(list, n);
|
||||||
|
|
307
include/sl.h
307
include/sl.h
|
@ -25,88 +25,23 @@
|
||||||
* - https://github.com/paulross/skiplist
|
* - https://github.com/paulross/skiplist
|
||||||
* Copyright (c) 2017-2023 Paul Ross
|
* Copyright (c) 2017-2023 Paul Ross
|
||||||
* - gist skiplist.c
|
* - gist skiplist.c
|
||||||
* - queue.h
|
|
||||||
* - khash.h
|
* - khash.h
|
||||||
* - async_nif.h
|
* - async_nif.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_SKIPLIST_H_
|
#ifndef _SKIPLIST_H_
|
||||||
#define _SYS_SKIPLIST_H_
|
#define _SKIPLIST_H_
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file defines a skiplist data structure with a similar API to those
|
* This file defines a skiplist data structure.
|
||||||
* datastructures defined in FreeBSD's <sys/queue.h> header.
|
|
||||||
*
|
*
|
||||||
* In 1990 William Pugh published:
|
* In 1990 William Pugh published:
|
||||||
* - Skiplists: a probabilistic alternative to balanced trees.
|
* - Skiplists: a probabilistic alternative to balanced trees.
|
||||||
* https://www.cl.cam.ac.uk/teaching/2005/Algorithms/skiplists.pdf
|
* https://www.cl.cam.ac.uk/teaching/2005/Algorithms/skiplists.pdf
|
||||||
* A Skiplist is an ordered data structure providing expected O(Log(n)) lookup,
|
* A Skiplist is an ordered data structure providing expected O(Log(n)) lookup,
|
||||||
* insertion, and deletion complexity.
|
* insertion, and deletion complexity.
|
||||||
*
|
|
||||||
*
|
|
||||||
* For details on the use of these macros, see the queue(3) manual page.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* SKIP SPLAYED_SKIP
|
|
||||||
* _HEAD + +
|
|
||||||
* _HEAD_INITIALIZER + +
|
|
||||||
* _ENTRY + +
|
|
||||||
* _INIT + +
|
|
||||||
* _DISPOSE + +
|
|
||||||
* _EMPTY + +
|
|
||||||
* _FIRST + +
|
|
||||||
* _NEXT + +
|
|
||||||
* _PREV + +
|
|
||||||
* _LAST - +
|
|
||||||
* _FOREACH + +
|
|
||||||
* _FOREACH_REVERSE + +
|
|
||||||
* _INSERT + +
|
|
||||||
* _UPDATE + +
|
|
||||||
* _BULK_INSERT + +
|
|
||||||
* _REMOVE + +
|
|
||||||
* _LOCATE + +
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SKIPLIST_MACRO_DEBUG 0
|
|
||||||
#if SKIPLIST_MACRO_DEBUG
|
|
||||||
/* Store the last 2 places the element or head was altered */
|
|
||||||
struct sl_trace {
|
|
||||||
char *lastfile;
|
|
||||||
int lastline;
|
|
||||||
char *prevfile;
|
|
||||||
int prevline;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TRACEBUF struct sl_trace trace;
|
|
||||||
#define TRASHIT(x) \
|
|
||||||
do { \
|
|
||||||
(x) = (void *)-1; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SLD_TRACE_HEAD(head) \
|
|
||||||
do { \
|
|
||||||
(head)->trace.prevline = (head)->trace.lastline; \
|
|
||||||
(head)->trace.prevfile = (head)->trace.lastfile; \
|
|
||||||
(head)->trace.lastline = __LINE__; \
|
|
||||||
(head)->trace.lastfile = __FILE__; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SLD_TRACE_ELEM(elem) \
|
|
||||||
do { \
|
|
||||||
(elem)->trace.prevline = (elem)->trace.lastline; \
|
|
||||||
(elem)->trace.prevfile = (elem)->trace.lastfile; \
|
|
||||||
(elem)->trace.lastline = __LINE__; \
|
|
||||||
(elem)->trace.lastfile = __FILE__; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define SLD_TRACE_ELEM(elem)
|
|
||||||
#define SLD_TRACE_HEAD(head)
|
|
||||||
#define TRACEBUF
|
|
||||||
#define TRASHIT(x)
|
|
||||||
#endif /* QUEUE_MACRO_DEBUG */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private, internal API.
|
* Private, internal API.
|
||||||
*/
|
*/
|
||||||
|
@ -142,24 +77,12 @@ struct sl_trace {
|
||||||
void *aux; \
|
void *aux; \
|
||||||
struct type *slh_head; \
|
struct type *slh_head; \
|
||||||
struct type *slh_tail; \
|
struct type *slh_tail; \
|
||||||
TRACEBUF \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SKIP_HEAD_DEFAULT_INITIALIZER(cmp) \
|
|
||||||
{ \
|
|
||||||
0, 0, 12, 4, cmp, NULL, NULL, NULL \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SKIP_HEAD_INITIALIZER(cmp, max, fanout) \
|
|
||||||
{ \
|
|
||||||
0, 0, max, fanout, cmp, NULL, NULL, NULL \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIP_ENTRY(type) \
|
#define SKIP_ENTRY(type) \
|
||||||
struct { \
|
struct { \
|
||||||
struct type **sle_next; \
|
struct type **sle_next; \
|
||||||
struct type *sle_prev; \
|
struct type *sle_prev; \
|
||||||
TRACEBUF \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -171,25 +94,6 @@ struct sl_trace {
|
||||||
#define SKIP_PREV(elm, field) ((elm)->field.sle_prev)
|
#define SKIP_PREV(elm, field) ((elm)->field.sle_prev)
|
||||||
#define SKIP_EMPTY(head) ((head)->length == 0)
|
#define SKIP_EMPTY(head) ((head)->length == 0)
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define SKIP_FOREACH(var, head, field) \
|
|
||||||
for ((var) = SKIP_FIRST(head); (var) != SKIP_END(head); \
|
|
||||||
(var) = SKIP_NEXT(var, field))
|
|
||||||
|
|
||||||
#define SKIP_FOREACH_SAFE(var, head, field, tvar) \
|
|
||||||
for ((var) = SKIP_FIRST(head); (var) && ((tvar) = SKIP_NEXT(var, field), 1); \
|
|
||||||
(var) = (tvar))
|
|
||||||
|
|
||||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
|
||||||
for ((var) = TAILQ_LAST(head, headname); (var) != TAILQ_END(head); \
|
|
||||||
(var) = TAILQ_PREV(var, headname, field))
|
|
||||||
|
|
||||||
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
|
|
||||||
for ((var) = TAILQ_LAST(head, headname); (var) != TAILQ_END(head) && \
|
|
||||||
((tvar) = TAILQ_PREV(var, headname, field), 1); \
|
|
||||||
(var) = (tvar))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip List functions.
|
* Skip List functions.
|
||||||
*/
|
*/
|
||||||
|
@ -207,65 +111,7 @@ struct sl_trace {
|
||||||
fn \
|
fn \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIP_INIT(head, max, fanout, type, field, fn) \
|
#define SKIPLIST_DECL(decl, prefix, field, free_node_blk) \
|
||||||
do { \
|
|
||||||
(head)->level = 0; \
|
|
||||||
(head)->length = 0; \
|
|
||||||
(head)->max = max; \
|
|
||||||
(head)->fanout = fanout; \
|
|
||||||
(head)->cmp = fn; \
|
|
||||||
SKIP_ALLOC_NODE(head, (head)->slh_head, type, field); \
|
|
||||||
SKIP_ALLOC_NODE(head, (head)->slh_tail, type, field); \
|
|
||||||
ARRAY_SET_LENGTH((head)->slh_head->field.sle_next, max); \
|
|
||||||
for (size_t __i = 0; __i < ARRAY_SIZE((head)->slh_head->field.sle_next); \
|
|
||||||
__i++) { \
|
|
||||||
(head)->slh_head->field.sle_next[__i] = (head)->slh_tail; \
|
|
||||||
} \
|
|
||||||
(head)->slh_head->field.sle_prev = NULL; \
|
|
||||||
ARRAY_SET_LENGTH((head)->slh_tail->field.sle_next, max); \
|
|
||||||
for (size_t __i = 0; __i < ARRAY_SIZE((head)->slh_tail->field.sle_next); \
|
|
||||||
__i++) { \
|
|
||||||
(head)->slh_tail->field.sle_next[__i] = NULL; \
|
|
||||||
} \
|
|
||||||
(head)->slh_head->field.sle_prev = (head)->slh_tail; \
|
|
||||||
SLD_TRACE_HEAD(head); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SKIP_DEFAULT_INIT(head, fn, type, field) \
|
|
||||||
do { \
|
|
||||||
(head)->level = 0; \
|
|
||||||
(head)->length = 0; \
|
|
||||||
(head)->max = 12; \
|
|
||||||
(head)->fanout = 4; \
|
|
||||||
(head)->cmp = fn; \
|
|
||||||
SKIP_ALLOC_NODE(head, (head)->slh_head, type, field); \
|
|
||||||
SKIP_ALLOC_NODE(head, (head)->slh_tail, type, field); \
|
|
||||||
ARRAY_SET_LENGTH((head)->slh_head->field.sle_next, (head)->max); \
|
|
||||||
for (size_t __i = 0; __i < ARRAY_SIZE((head)->slh_head->field.sle_next); \
|
|
||||||
__i++) { \
|
|
||||||
(head)->slh_head->field.sle_next[__i] = (head)->slh_tail; \
|
|
||||||
} \
|
|
||||||
(head)->slh_head->field.sle_prev = NULL; \
|
|
||||||
ARRAY_SET_LENGTH((head)->slh_tail->field.sle_next, (head)->max); \
|
|
||||||
for (size_t __i = 0; __i < ARRAY_SIZE((head)->slh_tail->field.sle_next); \
|
|
||||||
__i++) { \
|
|
||||||
(head)->slh_tail->field.sle_next[__i] = NULL; \
|
|
||||||
} \
|
|
||||||
(head)->slh_head->field.sle_prev = (head)->slh_tail; \
|
|
||||||
SLD_TRACE_HEAD(head); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SKIP_ALLOC_NODE(head, var, type, field) \
|
|
||||||
do { \
|
|
||||||
(var) = (struct type *)calloc(1, sizeof(struct type)); \
|
|
||||||
ARRAY_ALLOC((var)->field.sle_next, struct type, (head)->max); \
|
|
||||||
if ((var) && (var)->field.sle_next) { \
|
|
||||||
ARRAY_SET_SIZE((var)->field.sle_next, (head)->max); \
|
|
||||||
ARRAY_SET_LENGTH((var)->field.sle_next, 0); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SKIPLIST_DECL(decl, prefix, field) \
|
|
||||||
\
|
\
|
||||||
/* Skiplist node type */ \
|
/* Skiplist node type */ \
|
||||||
typedef struct decl##_node decl##_node_t; \
|
typedef struct decl##_node decl##_node_t; \
|
||||||
|
@ -277,7 +123,6 @@ struct sl_trace {
|
||||||
void *aux; \
|
void *aux; \
|
||||||
decl##_node_t *slh_head; \
|
decl##_node_t *slh_head; \
|
||||||
decl##_node_t *slh_tail; \
|
decl##_node_t *slh_tail; \
|
||||||
TRACEBUF \
|
|
||||||
} decl##_t; \
|
} decl##_t; \
|
||||||
\
|
\
|
||||||
/* -- __skip_key_compare_ \
|
/* -- __skip_key_compare_ \
|
||||||
|
@ -364,10 +209,58 @@ struct sl_trace {
|
||||||
/* -- skip_free_node_ */ \
|
/* -- skip_free_node_ */ \
|
||||||
void prefix##skip_free_node_##decl(decl##_node_t *node) \
|
void prefix##skip_free_node_##decl(decl##_node_t *node) \
|
||||||
{ \
|
{ \
|
||||||
|
free_node_blk; \
|
||||||
free(node->field.sle_next); \
|
free(node->field.sle_next); \
|
||||||
free(node); \
|
free(node); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
/* -- skip_destroy_ */ \
|
||||||
|
int prefix##skip_destroy_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_size_ */ \
|
||||||
|
int prefix##skip_size_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_empty_ */ \
|
||||||
|
int prefix##skip_empty_##decl(decl##_t *slist) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_head_ */ \
|
||||||
|
int prefix##skip_head_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_tail_ */ \
|
||||||
|
int prefix##skip_tail_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_locate_ */ \
|
||||||
|
decl##_node_t *prefix##skip_locate_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return NULL; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
/* -- skip_insert_ */ \
|
/* -- skip_insert_ */ \
|
||||||
int prefix##skip_insert_##decl(decl##_t *slist, decl##_node_t *n) \
|
int prefix##skip_insert_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -418,6 +311,70 @@ struct sl_trace {
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
/* -- skip_insert_dup_ */ \
|
||||||
|
int prefix##skip_insert_dup_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_update_ */ \
|
||||||
|
int prefix##skip_update_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_delete_ */ \
|
||||||
|
int prefix##skip_delete_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_find_ */ \
|
||||||
|
int prefix##skip_find_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_find_gte */ \
|
||||||
|
int prefix##skip_find_gte_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_find_lte */ \
|
||||||
|
int prefix##skip_find_lte_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_next_node_ */ \
|
||||||
|
int prefix##skip_next_node_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
/* -- skip_prev_node_ */ \
|
||||||
|
int prefix##skip_prev_node_##decl(decl##_t *slist, decl##_node_t *n) \
|
||||||
|
{ \
|
||||||
|
((void)slist); /* TODO */ \
|
||||||
|
((void)n); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
/* -- __skip_integrity_check_ */ \
|
/* -- __skip_integrity_check_ */ \
|
||||||
static int __skip_integrity_check_##decl(decl##_t *slist) \
|
static int __skip_integrity_check_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -425,6 +382,15 @@ struct sl_trace {
|
||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SKIPLIST_GETTER(decl, prefix, name, ktype, vtype, qblk, rblk) \
|
||||||
|
vtype prefix##skip_##name##_##decl(decl##_t *slist, ktype key) \
|
||||||
|
{ \
|
||||||
|
decl##_node_t *node, query; \
|
||||||
|
qblk; \
|
||||||
|
node = prefix##skip_locate_##decl(slist, &query); \
|
||||||
|
rblk; \
|
||||||
|
}
|
||||||
|
|
||||||
#define SKIPLIST_DECL_DOT(decl, prefix, field) \
|
#define SKIPLIST_DECL_DOT(decl, prefix, field) \
|
||||||
\
|
\
|
||||||
/* A type for a function that writes into a char[2048] buffer \
|
/* A type for a function that writes into a char[2048] buffer \
|
||||||
|
@ -602,25 +568,4 @@ struct sl_trace {
|
||||||
return 0; \
|
return 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#endif /* _SKIPLIST_H_ */
|
||||||
#define SKIP_REMOVE(head, elm, field) \
|
|
||||||
do { \
|
|
||||||
if ((elm)->field.le_next != NULL) \
|
|
||||||
(elm)->field.le_next->field.le_prev = (elm)->field.le_prev; \
|
|
||||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
|
||||||
_Q_INVALIDATE((elm)->field.le_prev); \
|
|
||||||
_Q_INVALIDATE((elm)->field.le_next); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SKIP_REPLACE(elm, elm2, field) \
|
|
||||||
do { \
|
|
||||||
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
|
|
||||||
(elm2)->field.le_next->field.le_prev = &(elm2)->field.le_next; \
|
|
||||||
(elm2)->field.le_prev = (elm)->field.le_prev; \
|
|
||||||
*(elm2)->field.le_prev = (elm2); \
|
|
||||||
_Q_INVALIDATE((elm)->field.le_prev); \
|
|
||||||
_Q_INVALIDATE((elm)->field.le_next); \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _SYS_SKIPLIST_H_ */
|
|
||||||
|
|
Loading…
Reference in a new issue