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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A Skiplist contains elements, a portion of which is used to manage those
|
* Every Skiplist node has to hvae an additional section of data used to manage
|
||||||
* elements while the rest is defined by the use case for this declaration. The
|
* nodes in the list. The rest of the datastructure is defined by the use case.
|
||||||
* housekeeping portion is the SKIPLIST_ENTRY below. It maintains the array of
|
* This housekeeping portion is the SKIPLIST_ENTRY, see below. It maintains the
|
||||||
* forward pointers to nodes and has a height (a zero-based count of levels, so
|
* array of forward pointers to nodes and has a height, this height is a a
|
||||||
* a height of `0` means one (1) level and a height of `4` means five (5)
|
* zero-based count of levels, so a height of `0` means one (1) level and a
|
||||||
* levels).
|
* height of `4` means five (5) forward pointers (levels) in the node, [0-4).
|
||||||
*/
|
*/
|
||||||
#define SKIPLIST_ENTRY(decl) \
|
#define SKIPLIST_ENTRY(decl) \
|
||||||
struct __skiplist_##decl##_entry { \
|
struct __skiplist_##decl##_entry { \
|
||||||
|
@ -240,8 +240,11 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
/* Skiplist node type */ \
|
/* Skiplist node type */ \
|
||||||
typedef struct decl##_node decl##_node_t; \
|
typedef struct decl##_node decl##_node_t; \
|
||||||
\
|
\
|
||||||
/* Skiplist structure and type */ \
|
/* Skiplist type. */ \
|
||||||
typedef struct decl { \
|
typedef struct decl decl##_t; \
|
||||||
|
\
|
||||||
|
/* Skiplist structure */ \
|
||||||
|
struct decl { \
|
||||||
size_t slh_length, slh_height, slh_max_height; \
|
size_t slh_length, slh_height, slh_max_height; \
|
||||||
void *slh_aux; \
|
void *slh_aux; \
|
||||||
decl##_node_t *slh_head; \
|
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 (*update_entry)(decl##_node_t *, void *); \
|
||||||
int (*archive_entry)(decl##_node_t *, const decl##_node_t *); \
|
int (*archive_entry)(decl##_node_t *, const decl##_node_t *); \
|
||||||
size_t (*sizeof_entry)(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 */ \
|
/* Optional: Snapshots */ \
|
||||||
int (*preserve_node)(struct decl * slist, const decl##_node_t *src, decl##_node_t **preserved); \
|
int (*preserve_node)(decl##_t * slist, const decl##_node_t *src, decl##_node_t **preserved); \
|
||||||
void (*release_snapshots)(struct decl *); \
|
void (*release_snapshots)(decl##_t *); \
|
||||||
size_t (*snapshot_current_era)(struct decl *); \
|
size_t (*snapshot_current_era)(decl##_t *); \
|
||||||
size_t (*snapshot_incr_era)(struct decl *); \
|
size_t (*snapshot_incr_era)(decl##_t *); \
|
||||||
void (*snapshot_record_era)(struct decl *, decl##_node_t *); \
|
void (*snapshot_record_era)(decl##_t *, decl##_node_t *); \
|
||||||
} slh_fns; \
|
} slh_fns; \
|
||||||
struct { \
|
struct { \
|
||||||
size_t threshold; /* `k`, the floor of log(max height) */ \
|
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; \
|
size_t era; \
|
||||||
decl##_node_t *pres; \
|
decl##_node_t *pres; \
|
||||||
} slh_snap; \
|
} 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_ \
|
* -- __skip_compare_entries_fn_ \
|
||||||
|
@ -592,29 +600,31 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
* -- __skip_rebalence_ TODO \
|
* -- __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; \
|
size_t i; \
|
||||||
double asc_cond, dsc_cond; \
|
double asc_cond, dsc_cond; \
|
||||||
\
|
\
|
||||||
|
return; /* TODO GSB */ \
|
||||||
/* Moving backwards along the path... */ \
|
/* Moving backwards along the path... */ \
|
||||||
for (i = 1; i < len; i++) { \
|
for (i = 1; i < len; i++) { \
|
||||||
if (par_sum > 0) { \
|
if (par_sum > 0) { \
|
||||||
/* check the decent condition: \
|
/* 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) { \
|
if (par_sum <= dsc_cond) { \
|
||||||
/* reduce height by one, change forward pointer */ \
|
/* reduce height by one, change forward pointer */ \
|
||||||
path[i - 1]->field.sle_next[i] = path[i]->field.sle_next[i]; \
|
path[i - 1].node->field.sle_next[i] = path[i].node->field.sle_next[i]; \
|
||||||
path[i]->field.sle_next[i] = slist->slh_tail; \
|
path[i].node->field.sle_next[i] = slist->slh_tail; \
|
||||||
path[i]->field.sle_height--; \
|
path[i].node->field.sle_height--; \
|
||||||
} \
|
} \
|
||||||
/* check the ascent condition \
|
/* check the ascent condition: \
|
||||||
par_sum + node_hits > hits total / (2 ^ (height of head - height of node - 1)) \
|
* 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); \
|
asc_cond = pow(2.0, slist->slh_head->field.sle_height - path[i].node->field.sle_height - 1); \
|
||||||
if (+path[i]->field.sle_hits > asc_cond) { \
|
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. \
|
* node in path[0], or NULL at path[0] where there wasn't a match. \
|
||||||
* sizeof(path) should be `slist->slh_max_height + 1` \
|
* 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; \
|
unsigned int i; \
|
||||||
size_t par_sum = 0, len = 0; \
|
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. */ \
|
/* Find the node that matches `node` or NULL. */ \
|
||||||
i = slist->slh_head->field.sle_height; \
|
i = slist->slh_head->field.sle_height; \
|
||||||
do { \
|
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]; \
|
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; \
|
par_sum += elm->field.sle_hits; \
|
||||||
len++; \
|
len++; \
|
||||||
} while (i--); \
|
} while (i--); \
|
||||||
elm = elm->field.sle_next[0]; \
|
elm = elm->field.sle_next[0]; \
|
||||||
if (__skip_compare_nodes_##decl(slist, elm, n, slist->slh_aux) == 0) { \
|
if (__skip_compare_nodes_##decl(slist, elm, n, slist->slh_aux) == 0) { \
|
||||||
path[0] = elm; \
|
path[0].node = elm; \
|
||||||
path[0]->field.sle_hits++; \
|
path[0].node->field.sle_hits++; \
|
||||||
__skip_rebalence_##decl(slist, len, path, par_sum); \
|
__skip_rebalence_##decl(slist, len, path, par_sum); \
|
||||||
} \
|
} \
|
||||||
return len; \
|
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 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; \
|
int rc = 0; \
|
||||||
size_t i, len, loc = 0, cur_height, new_height; \
|
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) \
|
if (slist == NULL || new == NULL) \
|
||||||
return ENOENT; \
|
return ENOENT; \
|
||||||
\
|
\
|
||||||
/* Allocate a buffer, or use a static one. */ \
|
/* Allocate a buffer, or use a static one. */ \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
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) \
|
if (path == NULL) \
|
||||||
return ENOMEM; \
|
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. */ \
|
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||||
len = __skip_locate_##decl(slist, new, path); \
|
len = __skip_locate_##decl(slist, new, path); \
|
||||||
node = path[0]; \
|
node = path[0].node; \
|
||||||
if (len > 0) { \
|
if (len > 0) { \
|
||||||
if ((node != NULL) && (flags == 0)) { \
|
if ((node != NULL) && (flags == 0)) { \
|
||||||
/* Don't insert, duplicate if flag not set. */ \
|
/* 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. */ \
|
/* Trim the path to at most the new height for the new node. */ \
|
||||||
if (new_height > cur_height) { \
|
if (new_height > cur_height) { \
|
||||||
for (i = cur_height + 1; i <= new_height; i++) { \
|
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. */ \
|
/* 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 \
|
/* 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] \
|
next[i] for our new node. Also, don't set the tail's next[i] \
|
||||||
because it is always NULL. */ \
|
because it is always NULL. */ \
|
||||||
if (path[i + 1] != slist->slh_tail) { \
|
if (path[i + 1].node != slist->slh_tail) { \
|
||||||
new->field.sle_next[i] = path[i + 1]->field.sle_next[i]; \
|
new->field.sle_next[i] = path[i + 1].node->field.sle_next[i]; \
|
||||||
path[i + 1]->field.sle_next[i] = new; \
|
path[i + 1].node->field.sle_next[i] = new; \
|
||||||
loc = path[i + 1] == slist->slh_head ? i : loc; \
|
loc = path[i + 1].node == slist->slh_head ? i : loc; \
|
||||||
} else { \
|
} else { \
|
||||||
new->field.sle_next[i] = slist->slh_tail; \
|
new->field.sle_next[i] = slist->slh_tail; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
/* Ensure all slh_head->next[] above loc point to 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) \
|
__SKIP_ENTRIES_B2T_FROM(field, slist->slh_head, loc + 1) \
|
||||||
{ \
|
{ \
|
||||||
slist->slh_head->field.sle_next[lvl] = slist->slh_tail; \
|
slist->slh_head->field.sle_next[lvl] = slist->slh_tail; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
/* Adujust the previous pointers in the nodes. */ \
|
/* 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; \
|
new->field.sle_next[0]->field.sle_prev = new; \
|
||||||
/* Account for insert at tail. */ \
|
/* Account for insert at tail. */ \
|
||||||
if (new->field.sle_next[0] == slist->slh_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) \
|
decl##_node_t *prefix##skip_position_eq_##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]; \
|
||||||
size_t len = 0; \
|
decl##_node_t *node = NULL; \
|
||||||
decl##_node_t *rc = NULL, *node, **path = apath; \
|
__skiplist_path_##decl##_t *path = apath; \
|
||||||
\
|
\
|
||||||
/* Allocate a buffer, or use a static one. */ \
|
/* Allocate a buffer, or use a static one. */ \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
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) \
|
if (path == NULL) \
|
||||||
goto done; \
|
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. */ \
|
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||||
len = __skip_locate_##decl(slist, query, path); \
|
__skip_locate_##decl(slist, query, path); \
|
||||||
if (len == 0) \
|
node = path[0].node; \
|
||||||
goto done; \
|
|
||||||
node = path[0]; \
|
|
||||||
if (node != NULL) \
|
|
||||||
rc = node; \
|
|
||||||
done:; \
|
done:; \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
if (SKIPLIST_MAX_HEIGHT == 1) \
|
||||||
free(path); \
|
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) \
|
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; \
|
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. */ \
|
/* Allocate a buffer, or use a static one. */ \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
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) \
|
if (path == NULL) \
|
||||||
goto done; \
|
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. */ \
|
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||||
__skip_locate_##decl(slist, query, path); \
|
__skip_locate_##decl(slist, query, path); \
|
||||||
node = path[1]; \
|
node = path[1].node; \
|
||||||
do { \
|
do { \
|
||||||
node = node->field.sle_next[0]; \
|
node = node->field.sle_next[0]; \
|
||||||
cmp = __skip_compare_nodes_##decl(slist, node, query, slist->slh_aux); \
|
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) \
|
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; \
|
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. */ \
|
/* Allocate a buffer, or use a static one. */ \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
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) \
|
if (path == NULL) \
|
||||||
goto done; \
|
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. */ \
|
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||||
__skip_locate_##decl(slist, query, path); \
|
__skip_locate_##decl(slist, query, path); \
|
||||||
node = path[1]; \
|
node = path[1].node; \
|
||||||
if (node == slist->slh_tail) \
|
if (node == slist->slh_tail) \
|
||||||
goto done; \
|
goto done; \
|
||||||
do { \
|
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) \
|
decl##_node_t *prefix##skip_position_lte_##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]; \
|
||||||
decl##_node_t *node, **path = apath; \
|
decl##_node_t *node; \
|
||||||
|
__skiplist_path_##decl##_t *path = apath; \
|
||||||
\
|
\
|
||||||
/* Allocate a buffer, or use a static one. */ \
|
/* Allocate a buffer, or use a static one. */ \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
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) \
|
if (path == NULL) \
|
||||||
goto done; \
|
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. */ \
|
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||||
__skip_locate_##decl(slist, query, path); \
|
__skip_locate_##decl(slist, query, path); \
|
||||||
node = path[0]; \
|
node = path[0].node; \
|
||||||
if (node) \
|
if (node) \
|
||||||
goto done; \
|
goto done; \
|
||||||
node = path[1]; \
|
node = path[1].node; \
|
||||||
\
|
\
|
||||||
done:; \
|
done:; \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
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) \
|
decl##_node_t *prefix##skip_position_lt_##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]; \
|
||||||
decl##_node_t *node, **path = apath; \
|
decl##_node_t *node; \
|
||||||
|
__skiplist_path_##decl##_t *path = apath; \
|
||||||
\
|
\
|
||||||
/* Allocate a buffer, or use a static one. */ \
|
/* Allocate a buffer, or use a static one. */ \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
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) \
|
if (path == NULL) \
|
||||||
goto done; \
|
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. */ \
|
/* Find a `path` to `new` in the list and a match (`path[0]`) if it exists. */ \
|
||||||
__skip_locate_##decl(slist, query, path); \
|
__skip_locate_##decl(slist, query, path); \
|
||||||
node = path[1]; \
|
node = path[1].node; \
|
||||||
\
|
\
|
||||||
done:; \
|
done:; \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
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) \
|
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; \
|
int rc = 0, np; \
|
||||||
decl##_node_t *node, **path = apath; \
|
decl##_node_t *node; \
|
||||||
|
__skiplist_path_##decl##_t *path = apath; \
|
||||||
\
|
\
|
||||||
if (slist == NULL) \
|
if (slist == NULL) \
|
||||||
return -1; \
|
return -1; \
|
||||||
\
|
\
|
||||||
/* Allocate a buffer, or use a static one. */ \
|
/* Allocate a buffer, or use a static one. */ \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
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) \
|
if (path == NULL) \
|
||||||
return ENOMEM; \
|
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); \
|
__skip_locate_##decl(slist, query, path); \
|
||||||
node = path[0]; \
|
node = path[0].node; \
|
||||||
\
|
\
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) \
|
if (SKIPLIST_MAX_HEIGHT == 1) \
|
||||||
free(path); \
|
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) \
|
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; \
|
int np = 0; \
|
||||||
size_t i, len, height; \
|
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) \
|
if (slist == NULL || query == NULL) \
|
||||||
return -1; \
|
return -1; \
|
||||||
|
@ -1044,15 +1059,15 @@ void __attribute__((format(printf, 4, 5))) __skip_diag_(const char *file, int li
|
||||||
\
|
\
|
||||||
/* Allocate a buffer */ \
|
/* Allocate a buffer */ \
|
||||||
if (SKIPLIST_MAX_HEIGHT == 1) { \
|
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) \
|
if (path == NULL) \
|
||||||
return ENOMEM; \
|
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. */ \
|
/* Attempt to locate the node in the list. */ \
|
||||||
len = __skip_locate_##decl(slist, query, path); \
|
len = __skip_locate_##decl(slist, query, path); \
|
||||||
node = path[0]; \
|
node = path[0].node; \
|
||||||
if (node) { \
|
if (node) { \
|
||||||
/* If the optional snapshots feature is configured, use it now. \
|
/* If the optional snapshots feature is configured, use it now. \
|
||||||
Snapshots preserve the node if it is younger than our snapshot \
|
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 \
|
/* Walk the path, stop when the next node is not the one we're \
|
||||||
removing. At each step along our walk... */ \
|
removing. At each step along our walk... */ \
|
||||||
for (i = 0; i < len; i++) { \
|
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; \
|
break; \
|
||||||
/* ... adjust the next pointer at that level. */ \
|
/* ... 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 \
|
/* Adjust the height so we're only pointing at the tail once at \
|
||||||
the top so we don't waste steps later when searching. */ \
|
the top so we don't waste steps later when searching. */ \
|
||||||
if (path[i + 1]->field.sle_next[i] == slist->slh_tail) { \
|
if (path[i + 1].node->field.sle_next[i] == slist->slh_tail) { \
|
||||||
height = path[i + 1]->field.sle_height; \
|
height = path[i + 1].node->field.sle_height; \
|
||||||
path[i + 1]->field.sle_height = height - 1; \
|
path[i + 1].node->field.sle_height = height - 1; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
/* Account for delete at tail. */ \
|
/* Account for delete at tail. */ \
|
||||||
|
|
Loading…
Reference in a new issue