splay v1/p4; __skiplist_path with intersection
This commit is contained in:
parent
b62fd4bf6a
commit
8703fbb5a9
195
include/sl.h
195
include/sl.h
|
@ -195,12 +195,12 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
#endif
|
||||
|
||||
/*
|
||||
* A Skiplist contains elements, a portion of which is used to manage those
|
||||
* elements while the rest is defined by the use case for this declaration. The
|
||||
* housekeeping portion is the SKIPLIST_ENTRY below. It maintains the array of
|
||||
* forward pointers to nodes and has a height (a zero-based count of levels, so
|
||||
* a height of `0` means one (1) level and a height of `4` means five (5)
|
||||
* levels).
|
||||
* Every Skiplist node has to hvae an additional section of data used to manage
|
||||
* nodes in the list. The rest of the datastructure is defined by the use case.
|
||||
* This housekeeping portion is the SKIPLIST_ENTRY, see below. It maintains the
|
||||
* array of forward pointers to nodes and has a height, this height is a a
|
||||
* zero-based count of levels, so a height of `0` means one (1) level and a
|
||||
* height of `4` means five (5) forward pointers (levels) in the node, [0-4).
|
||||
*/
|
||||
#define SKIPLIST_ENTRY(decl) \
|
||||
struct __skiplist_##decl##_entry { \
|
||||
|
@ -240,8 +240,11 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
/* Skiplist node type */ \
|
||||
typedef struct decl##_node decl##_node_t; \
|
||||
\
|
||||
/* Skiplist structure and type */ \
|
||||
typedef struct decl { \
|
||||
/* Skiplist type. */ \
|
||||
typedef struct decl decl##_t; \
|
||||
\
|
||||
/* Skiplist structure */ \
|
||||
struct decl { \
|
||||
size_t slh_length, slh_height, slh_max_height; \
|
||||
void *slh_aux; \
|
||||
decl##_node_t *slh_head; \
|
||||
|
@ -251,14 +254,14 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
int (*update_entry)(decl##_node_t *, void *); \
|
||||
int (*archive_entry)(decl##_node_t *, const decl##_node_t *); \
|
||||
size_t (*sizeof_entry)(decl##_node_t *); \
|
||||
int (*compare_entries)(struct decl *, decl##_node_t *, decl##_node_t *, void *); \
|
||||
int (*compare_entries)(decl##_t *, decl##_node_t *, decl##_node_t *, void *); \
|
||||
\
|
||||
/* Optional: Snapshots */ \
|
||||
int (*preserve_node)(struct decl * slist, const decl##_node_t *src, decl##_node_t **preserved); \
|
||||
void (*release_snapshots)(struct decl *); \
|
||||
size_t (*snapshot_current_era)(struct decl *); \
|
||||
size_t (*snapshot_incr_era)(struct decl *); \
|
||||
void (*snapshot_record_era)(struct decl *, decl##_node_t *); \
|
||||
int (*preserve_node)(decl##_t * slist, const decl##_node_t *src, decl##_node_t **preserved); \
|
||||
void (*release_snapshots)(decl##_t *); \
|
||||
size_t (*snapshot_current_era)(decl##_t *); \
|
||||
size_t (*snapshot_incr_era)(decl##_t *); \
|
||||
void (*snapshot_record_era)(decl##_t *, decl##_node_t *); \
|
||||
} slh_fns; \
|
||||
struct { \
|
||||
size_t threshold; /* `k`, the floor of log(max height) */ \
|
||||
|
@ -268,7 +271,12 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
size_t era; \
|
||||
decl##_node_t *pres; \
|
||||
} slh_snap; \
|
||||
} decl##_t; \
|
||||
}; \
|
||||
\
|
||||
typedef struct __skiplist_path_##decl { \
|
||||
decl##_node_t *node; /* node traversed in the act of location */ \
|
||||
size_t intersection; /* level at which the node was intersected */ \
|
||||
} __skiplist_path_##decl##_t; \
|
||||
\
|
||||
/** \
|
||||
* -- __skip_compare_entries_fn_ \
|
||||
|
@ -592,29 +600,31 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
* -- __skip_rebalence_ TODO \
|
||||
* \
|
||||
*/ \
|
||||
static void __skip_rebalence_##decl(decl##_t *slist, size_t len, decl##_node_t **path, size_t par_sum) \
|
||||
static void __skip_rebalence_##decl(decl##_t *slist, size_t len, __skiplist_path_##decl##_t path[], size_t par_sum) \
|
||||
{ \
|
||||
size_t i; \
|
||||
double asc_cond, dsc_cond; \
|
||||
\
|
||||
return; /* TODO GSB */ \
|
||||
/* Moving backwards along the path... */ \
|
||||
for (i = 1; i < len; i++) { \
|
||||
if (par_sum > 0) { \
|
||||
/* check the decent condition: \
|
||||
par_sum <= hits total / (2 ^ (height of head - height of node)) \
|
||||
* par_sum <= hits total / (2 ^ (height of head - height of node)) \
|
||||
*/ \
|
||||
dsc_cond = pow(2.0, slist->slh_head->field.sle_height - path[i]->field.sle_height); \
|
||||
dsc_cond = pow(2.0, slist->slh_head->field.sle_height - path[i].node->field.sle_height); \
|
||||
if (par_sum <= dsc_cond) { \
|
||||
/* reduce height by one, change forward pointer */ \
|
||||
path[i - 1]->field.sle_next[i] = path[i]->field.sle_next[i]; \
|
||||
path[i]->field.sle_next[i] = slist->slh_tail; \
|
||||
path[i]->field.sle_height--; \
|
||||
path[i - 1].node->field.sle_next[i] = path[i].node->field.sle_next[i]; \
|
||||
path[i].node->field.sle_next[i] = slist->slh_tail; \
|
||||
path[i].node->field.sle_height--; \
|
||||
} \
|
||||
/* check the ascent condition \
|
||||
par_sum + node_hits > hits total / (2 ^ (height of head - height of node - 1)) \
|
||||
/* check the ascent condition: \
|
||||
* par_sum + node_hits > hits total / (2 ^ (height of head - height of node - 1)) \
|
||||
*/ \
|
||||
asc_cond = pow(2.0, slist->slh_head->field.sle_height - path[i]->field.sle_height - 1); \
|
||||
if (+path[i]->field.sle_hits > asc_cond) { \
|
||||
asc_cond = pow(2.0, slist->slh_head->field.sle_height - path[i].node->field.sle_height - 1); \
|
||||
if (path[i].node->field.sle_hits > asc_cond) { \
|
||||
((void)0); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
|
@ -628,7 +638,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
* node in path[0], or NULL at path[0] where there wasn't a match. \
|
||||
* sizeof(path) should be `slist->slh_max_height + 1` \
|
||||
*/ \
|
||||
static size_t __skip_locate_##decl(decl##_t *slist, decl##_node_t *n, decl##_node_t **path) \
|
||||
static size_t __skip_locate_##decl(decl##_t *slist, decl##_node_t *n, __skiplist_path_##decl##_t path[]) \
|
||||
{ \
|
||||
unsigned int i; \
|
||||
size_t par_sum = 0, len = 0; \
|
||||
|
@ -640,16 +650,18 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
/* Find the node that matches `node` or NULL. */ \
|
||||
i = slist->slh_head->field.sle_height; \
|
||||
do { \
|
||||
while (elm != slist->slh_tail && elm->field.sle_next[i] && __skip_compare_nodes_##decl(slist, elm->field.sle_next[i], n, slist->slh_aux) < 0) \
|
||||
while (elm != slist->slh_tail && elm->field.sle_next[i] && __skip_compare_nodes_##decl(slist, elm->field.sle_next[i], n, slist->slh_aux) < 0) { \
|
||||
elm = elm->field.sle_next[i]; \
|
||||
path[i + 1] = elm; \
|
||||
path[i + 1].intersection = i; \
|
||||
} \
|
||||
path[i + 1].node = elm; \
|
||||
par_sum += elm->field.sle_hits; \
|
||||
len++; \
|
||||
} while (i--); \
|
||||
elm = elm->field.sle_next[0]; \
|
||||
if (__skip_compare_nodes_##decl(slist, elm, n, slist->slh_aux) == 0) { \
|
||||
path[0] = elm; \
|
||||
path[0]->field.sle_hits++; \
|
||||
path[0].node = elm; \
|
||||
path[0].node->field.sle_hits++; \
|
||||
__skip_rebalence_##decl(slist, len, path, par_sum); \
|
||||
} \
|
||||
return len; \
|
||||
|
@ -664,25 +676,26 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
static int __skip_insert_##decl(decl##_t *slist, decl##_node_t *new, int flags) \
|
||||
{ \
|
||||
static decl##_node_t *apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
static __skiplist_path_##decl##_t apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
int rc = 0; \
|
||||
size_t i, len, loc = 0, cur_height, new_height; \
|
||||
decl##_node_t *node, **path = apath; \
|
||||
decl##_node_t *node; \
|
||||
__skiplist_path_##decl##_t *path = apath; \
|
||||
\
|
||||
if (slist == NULL || new == NULL) \
|
||||
return ENOENT; \
|
||||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
path = malloc(sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
if (path == NULL) \
|
||||
return ENOMEM; \
|
||||
} \
|
||||
memset(path, 0, sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
memset(path, 0, sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
\
|
||||
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||
len = __skip_locate_##decl(slist, new, path); \
|
||||
node = path[0]; \
|
||||
node = path[0].node; \
|
||||
if (len > 0) { \
|
||||
if ((node != NULL) && (flags == 0)) { \
|
||||
/* Don't insert, duplicate if flag not set. */ \
|
||||
|
@ -695,7 +708,7 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
/* Trim the path to at most the new height for the new node. */ \
|
||||
if (new_height > cur_height) { \
|
||||
for (i = cur_height + 1; i <= new_height; i++) { \
|
||||
path[i + 1] = slist->slh_tail; \
|
||||
path[i + 1].node = slist->slh_tail; \
|
||||
} \
|
||||
} \
|
||||
/* Ensure all next[] point to tail. */ \
|
||||
|
@ -708,23 +721,23 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
/* The tail's next[i] is always NULL, we don't want that in the \
|
||||
next[i] for our new node. Also, don't set the tail's next[i] \
|
||||
because it is always NULL. */ \
|
||||
if (path[i + 1] != slist->slh_tail) { \
|
||||
new->field.sle_next[i] = path[i + 1]->field.sle_next[i]; \
|
||||
path[i + 1]->field.sle_next[i] = new; \
|
||||
loc = path[i + 1] == slist->slh_head ? i : loc; \
|
||||
if (path[i + 1].node != slist->slh_tail) { \
|
||||
new->field.sle_next[i] = path[i + 1].node->field.sle_next[i]; \
|
||||
path[i + 1].node->field.sle_next[i] = new; \
|
||||
loc = path[i + 1].node == slist->slh_head ? i : loc; \
|
||||
} else { \
|
||||
new->field.sle_next[i] = slist->slh_tail; \
|
||||
} \
|
||||
} \
|
||||
/* Ensure all slh_head->next[] above loc point to tail. */ \
|
||||
if (path[1] == slist->slh_head) { \
|
||||
if (path[1].node == slist->slh_head) { \
|
||||
__SKIP_ENTRIES_B2T_FROM(field, slist->slh_head, loc + 1) \
|
||||
{ \
|
||||
slist->slh_head->field.sle_next[lvl] = slist->slh_tail; \
|
||||
} \
|
||||
} \
|
||||
/* Adujust the previous pointers in the nodes. */ \
|
||||
new->field.sle_prev = path[1]; \
|
||||
new->field.sle_prev = path[1].node; \
|
||||
new->field.sle_next[0]->field.sle_prev = new; \
|
||||
/* Account for insert at tail. */ \
|
||||
if (new->field.sle_next[0] == slist->slh_tail) { \
|
||||
|
@ -778,30 +791,26 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
decl##_node_t *prefix##skip_position_eq_##decl(decl##_t *slist, decl##_node_t *query) \
|
||||
{ \
|
||||
static decl##_node_t *apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
size_t len = 0; \
|
||||
decl##_node_t *rc = NULL, *node, **path = apath; \
|
||||
static __skiplist_path_##decl##_t apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
decl##_node_t *node = NULL; \
|
||||
__skiplist_path_##decl##_t *path = apath; \
|
||||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
path = malloc(sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
if (path == NULL) \
|
||||
goto done; \
|
||||
} \
|
||||
memset(path, 0, sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
memset(path, 0, sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
\
|
||||
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||
len = __skip_locate_##decl(slist, query, path); \
|
||||
if (len == 0) \
|
||||
goto done; \
|
||||
node = path[0]; \
|
||||
if (node != NULL) \
|
||||
rc = node; \
|
||||
__skip_locate_##decl(slist, query, path); \
|
||||
node = path[0].node; \
|
||||
done:; \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
||||
free(path); \
|
||||
\
|
||||
return rc; \
|
||||
return node; \
|
||||
} \
|
||||
\
|
||||
/** \
|
||||
|
@ -813,21 +822,22 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
decl##_node_t *prefix##skip_position_gte_##decl(decl##_t *slist, decl##_node_t *query) \
|
||||
{ \
|
||||
static decl##_node_t *apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
static __skiplist_path_##decl##_t apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
int cmp; \
|
||||
decl##_node_t *node, **path = apath; \
|
||||
decl##_node_t *node; \
|
||||
__skiplist_path_##decl##_t *path = apath; \
|
||||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
path = malloc(sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
if (path == NULL) \
|
||||
goto done; \
|
||||
} \
|
||||
memset(path, 0, sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
memset(path, 0, sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
\
|
||||
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||
__skip_locate_##decl(slist, query, path); \
|
||||
node = path[1]; \
|
||||
node = path[1].node; \
|
||||
do { \
|
||||
node = node->field.sle_next[0]; \
|
||||
cmp = __skip_compare_nodes_##decl(slist, node, query, slist->slh_aux); \
|
||||
|
@ -849,21 +859,22 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
decl##_node_t *prefix##skip_position_gt_##decl(decl##_t *slist, decl##_node_t *query) \
|
||||
{ \
|
||||
static decl##_node_t *apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
static __skiplist_path_##decl##_t apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
int cmp; \
|
||||
decl##_node_t *node, **path = apath; \
|
||||
decl##_node_t *node; \
|
||||
__skiplist_path_##decl##_t *path = apath; \
|
||||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
path = malloc(sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
if (path == NULL) \
|
||||
goto done; \
|
||||
} \
|
||||
memset(path, 0, sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
memset(path, 0, sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
\
|
||||
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||
__skip_locate_##decl(slist, query, path); \
|
||||
node = path[1]; \
|
||||
node = path[1].node; \
|
||||
if (node == slist->slh_tail) \
|
||||
goto done; \
|
||||
do { \
|
||||
|
@ -887,23 +898,24 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
decl##_node_t *prefix##skip_position_lte_##decl(decl##_t *slist, decl##_node_t *query) \
|
||||
{ \
|
||||
static decl##_node_t *apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
decl##_node_t *node, **path = apath; \
|
||||
static __skiplist_path_##decl##_t apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
decl##_node_t *node; \
|
||||
__skiplist_path_##decl##_t *path = apath; \
|
||||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
path = malloc(sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
if (path == NULL) \
|
||||
goto done; \
|
||||
} \
|
||||
memset(path, 0, sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
memset(path, 0, sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
\
|
||||
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||
__skip_locate_##decl(slist, query, path); \
|
||||
node = path[0]; \
|
||||
node = path[0].node; \
|
||||
if (node) \
|
||||
goto done; \
|
||||
node = path[1]; \
|
||||
node = path[1].node; \
|
||||
\
|
||||
done:; \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
||||
|
@ -920,20 +932,21 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
decl##_node_t *prefix##skip_position_lt_##decl(decl##_t *slist, decl##_node_t *query) \
|
||||
{ \
|
||||
static decl##_node_t *apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
decl##_node_t *node, **path = apath; \
|
||||
static __skiplist_path_##decl##_t apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
decl##_node_t *node; \
|
||||
__skiplist_path_##decl##_t *path = apath; \
|
||||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
path = malloc(sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
if (path == NULL) \
|
||||
goto done; \
|
||||
} \
|
||||
memset(path, 0, sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
memset(path, 0, sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
\
|
||||
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||
__skip_locate_##decl(slist, query, path); \
|
||||
node = path[1]; \
|
||||
node = path[1].node; \
|
||||
\
|
||||
done:; \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
||||
|
@ -983,23 +996,24 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
int prefix##skip_update_##decl(decl##_t *slist, decl##_node_t *query, void *value) \
|
||||
{ \
|
||||
static decl##_node_t *apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
static __skiplist_path_##decl##_t apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
int rc = 0, np; \
|
||||
decl##_node_t *node, **path = apath; \
|
||||
decl##_node_t *node; \
|
||||
__skiplist_path_##decl##_t *path = apath; \
|
||||
\
|
||||
if (slist == NULL) \
|
||||
return -1; \
|
||||
\
|
||||
/* Allocate a buffer, or use a static one. */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
path = malloc(sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
if (path == NULL) \
|
||||
return ENOMEM; \
|
||||
} \
|
||||
memset(path, 0, sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
memset(path, 0, sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
\
|
||||
__skip_locate_##decl(slist, query, path); \
|
||||
node = path[0]; \
|
||||
node = path[0].node; \
|
||||
\
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
||||
free(path); \
|
||||
|
@ -1032,10 +1046,11 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
*/ \
|
||||
int prefix##skip_remove_node_##decl(decl##_t *slist, decl##_node_t *query) \
|
||||
{ \
|
||||
static decl##_node_t *apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
static __skiplist_path_##decl##_t apath[SKIPLIST_MAX_HEIGHT + 1]; \
|
||||
int np = 0; \
|
||||
size_t i, len, height; \
|
||||
decl##_node_t *node, **path = apath; \
|
||||
decl##_node_t *node; \
|
||||
__skiplist_path_##decl##_t *path = apath; \
|
||||
\
|
||||
if (slist == NULL || query == NULL) \
|
||||
return -1; \
|
||||
|
@ -1044,15 +1059,15 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
\
|
||||
/* Allocate a buffer */ \
|
||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
||||
path = malloc(sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
path = malloc(sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
if (path == NULL) \
|
||||
return ENOMEM; \
|
||||
} \
|
||||
memset(path, 0, sizeof(decl##_node_t *) * slist->slh_max_height + 1); \
|
||||
memset(path, 0, sizeof(__skiplist_path_##decl##_t) * slist->slh_max_height + 1); \
|
||||
\
|
||||
/* Attempt to locate the node in the list. */ \
|
||||
len = __skip_locate_##decl(slist, query, path); \
|
||||
node = path[0]; \
|
||||
node = path[0].node; \
|
||||
if (node) { \
|
||||
/* If the optional snapshots feature is configured, use it now. \
|
||||
Snapshots preserve the node if it is younger than our snapshot \
|
||||
|
@ -1068,15 +1083,15 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
|||
/* Walk the path, stop when the next node is not the one we're \
|
||||
removing. At each step along our walk... */ \
|
||||
for (i = 0; i < len; i++) { \
|
||||
if (path[i + 1]->field.sle_next[i] != node) \
|
||||
if (path[i + 1].node->field.sle_next[i] != node) \
|
||||
break; \
|
||||
/* ... adjust the next pointer at that level. */ \
|
||||
path[i + 1]->field.sle_next[i] = node->field.sle_next[i]; \
|
||||
path[i + 1].node->field.sle_next[i] = node->field.sle_next[i]; \
|
||||
/* Adjust the height so we're only pointing at the tail once at \
|
||||
the top so we don't waste steps later when searching. */ \
|
||||
if (path[i + 1]->field.sle_next[i] == slist->slh_tail) { \
|
||||
height = path[i + 1]->field.sle_height; \
|
||||
path[i + 1]->field.sle_height = height - 1; \
|
||||
if (path[i + 1].node->field.sle_next[i] == slist->slh_tail) { \
|
||||
height = path[i + 1].node->field.sle_height; \
|
||||
path[i + 1].node->field.sle_height = height - 1; \
|
||||
} \
|
||||
} \
|
||||
/* Account for delete at tail. */ \
|
||||
|
|
Loading…
Reference in a new issue