WIP snaps, pt2
This commit is contained in:
parent
25f86f9e32
commit
b0a2918cf9
2 changed files with 80 additions and 27 deletions
|
@ -4,6 +4,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -136,6 +137,11 @@ main()
|
||||||
q.key = 0;
|
q.key = 0;
|
||||||
api_skip_remove_slex(list, &q);
|
api_skip_remove_slex(list, &q);
|
||||||
|
|
||||||
|
slex_snap_t *snap = api_skip_snapshot_slex(list);
|
||||||
|
slex_t *restored = api_skip_restore_snapshot_slex(snap, __skip_key_compare_slex);
|
||||||
|
api_skip_dispose_snapshot_slex(snap);
|
||||||
|
api_skip_destroy_slex(restored);
|
||||||
|
|
||||||
// assert(api_skip_gte_slex(list, -3000000) == -20);
|
// assert(api_skip_gte_slex(list, -3000000) == -20);
|
||||||
assert(api_skip_gte_slex(list, -2) == -20);
|
assert(api_skip_gte_slex(list, -2) == -20);
|
||||||
assert(api_skip_gte_slex(list, 0) == 10);
|
assert(api_skip_gte_slex(list, 0) == 10);
|
||||||
|
|
97
include/sl.h
97
include/sl.h
|
@ -139,12 +139,6 @@
|
||||||
|
|
||||||
#define SKIPLIST_DECL(decl, prefix, field, free_node_blk, update_node_blk, snap_node_blk, array_type, into_array_blk) \
|
#define SKIPLIST_DECL(decl, prefix, field, free_node_blk, update_node_blk, snap_node_blk, array_type, into_array_blk) \
|
||||||
\
|
\
|
||||||
struct __##decl##_path { \
|
|
||||||
size_t cap; \
|
|
||||||
size_t len; \
|
|
||||||
struct decl##_node **nodes; \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
/* Skiplist node type */ \
|
/* Skiplist node type */ \
|
||||||
typedef struct decl##_node decl##_node_t; \
|
typedef struct decl##_node decl##_node_t; \
|
||||||
\
|
\
|
||||||
|
@ -157,6 +151,17 @@
|
||||||
decl##_node_t *slh_tail; \
|
decl##_node_t *slh_tail; \
|
||||||
} decl##_t; \
|
} decl##_t; \
|
||||||
\
|
\
|
||||||
|
typedef struct decl##_snap { \
|
||||||
|
decl##_t list; \
|
||||||
|
decl##_node_t **nodes; \
|
||||||
|
} decl##_snap_t; \
|
||||||
|
\
|
||||||
|
struct __##decl##_path { \
|
||||||
|
size_t cap; \
|
||||||
|
size_t len; \
|
||||||
|
struct decl##_node **nodes; \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
/* -- __skip_key_compare_ \
|
/* -- __skip_key_compare_ \
|
||||||
* \
|
* \
|
||||||
* This function takes four arguments: \
|
* This function takes four arguments: \
|
||||||
|
@ -578,53 +583,95 @@
|
||||||
* NOTE: There are many fancy algorithms for this, for now \
|
* NOTE: There are many fancy algorithms for this, for now \
|
||||||
* this implementation will simply create a copy of the nodes. \
|
* this implementation will simply create a copy of the nodes. \
|
||||||
*/ \
|
*/ \
|
||||||
decl##_node_t **prefix##skip_snapshot_##decl(decl##_t *slist) \
|
decl##_snap_t *prefix##skip_snapshot_##decl(decl##_t *slist) \
|
||||||
{ \
|
{ \
|
||||||
decl##_node_t **array, *node, *new; \
|
size_t i; \
|
||||||
|
decl##_snap_t *snap; \
|
||||||
|
decl##_node_t *node, *new; \
|
||||||
\
|
\
|
||||||
if (slist == NULL) \
|
if (slist == NULL) \
|
||||||
return 0; \
|
return 0; \
|
||||||
if (prefix##skip_size_##decl(slist) == 0) \
|
if (prefix##skip_size_##decl(slist) == 0) \
|
||||||
return 0; \
|
return 0; \
|
||||||
\
|
\
|
||||||
new = array = calloc(slist->length, sizeof(decl##_node_t) + 1); \
|
snap = (decl##_snap_t *)calloc(1, sizeof(decl##_snap_t) + (slist->length * sizeof(decl##_node_t))); \
|
||||||
if (array == NULL) \
|
if (snap == NULL) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
\
|
\
|
||||||
|
memcpy(&snap->list, slist, sizeof(decl##_t)); \
|
||||||
|
snap->list.cmp = NULL; \
|
||||||
|
snap->nodes = (decl##_node_t **)(snap + sizeof(decl##_snap_t)); \
|
||||||
|
\
|
||||||
node = prefix##skip_head_##decl(slist); \
|
node = prefix##skip_head_##decl(slist); \
|
||||||
|
i = 0; \
|
||||||
do { \
|
do { \
|
||||||
memcopy(new, node, sizeof(decl##_node_t)); \
|
new = (decl##_node_t *)snap->nodes + i; \
|
||||||
|
memcpy(new, node, sizeof(decl##_node_t)); \
|
||||||
snap_node_blk; \
|
snap_node_blk; \
|
||||||
node = prefix##skip_next_node_##decl(slist, node); \
|
node = prefix##skip_next_node_##decl(slist, node); \
|
||||||
new += sizeof(decl##_node_t); \
|
} while (++i < slist->length); \
|
||||||
} while (node != NULL); \
|
return snap; \
|
||||||
return 0; \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_restore_snapshot_ */ \
|
/* -- skip_restore_snapshot_ */ \
|
||||||
decl##_t *prefix##skip_restore_snapshot_##decl(decl##_node_t **snap, int (*cmp)(struct list * head, struct type * a, struct type * b, void *aux)) \
|
decl##_t *prefix##skip_restore_snapshot_##decl(decl##_snap_t *snap, int (*cmp)(decl##_t * head, decl##_node_t * a, decl##_node_t * b, void *aux)) \
|
||||||
{ \
|
{ \
|
||||||
int rc = 0; \
|
int rc; \
|
||||||
decl##_t *slist(decl##_t *) cmalloc(1, sizeof(decl##_t)); \
|
size_t i; \
|
||||||
|
decl##_t *slist; \
|
||||||
|
decl##_node_t *n; \
|
||||||
\
|
\
|
||||||
if (slist == NULL) { \
|
if (snap == NULL || cmp == NULL) \
|
||||||
errno = ENOMEM; \
|
return 0; \
|
||||||
|
slist = (decl##_t *)calloc(1, sizeof(decl##_t)); \
|
||||||
|
if (slist == NULL) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
\
|
||||||
|
memcpy(slist, &snap->list, sizeof(decl##_t)); \
|
||||||
|
slist->cmp = cmp; \
|
||||||
|
rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_head); \
|
||||||
|
if (rc) \
|
||||||
|
goto fail; \
|
||||||
|
rc = prefix##skip_alloc_node_##decl(slist, &slist->slh_tail); \
|
||||||
|
if (rc) \
|
||||||
|
goto fail; \
|
||||||
|
slist->slh_head->field.sle.len = slist->max; \
|
||||||
|
for (i = 0; i < slist->max; i++) \
|
||||||
|
slist->slh_head->field.sle.next[i] = slist->slh_tail; \
|
||||||
|
slist->slh_head->field.sle.prev = NULL; \
|
||||||
|
slist->slh_tail->field.sle.len = slist->max; \
|
||||||
|
for (i = 0; i < slist->max; i++) \
|
||||||
|
slist->slh_tail->field.sle.next[i] = NULL; \
|
||||||
|
slist->slh_head->field.sle.prev = slist->slh_tail; \
|
||||||
|
\
|
||||||
|
i = 0; \
|
||||||
|
do { \
|
||||||
/* memcpy head from snap, set cmp fn, memcpy each node into newly \
|
/* memcpy head from snap, set cmp fn, memcpy each node into newly \
|
||||||
allocated node, insert into list allow dups */ \
|
allocated node, insert into list allow dups */ \
|
||||||
((void)slist); \
|
n = calloc(1, sizeof(decl##_node_t)); \
|
||||||
|
memcpy(n, snap->nodes + i, sizeof(decl##_node_t)); \
|
||||||
|
__skip_insert_##decl(slist, n, 1); \
|
||||||
|
} while (++i < slist->length); \
|
||||||
return 0; \
|
return 0; \
|
||||||
|
fail:; \
|
||||||
|
if (slist->slh_head) \
|
||||||
|
free(slist->slh_head); \
|
||||||
|
if (slist->slh_tail) \
|
||||||
|
free(slist->slh_tail); \
|
||||||
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* -- skip_dispose_snapshot_ */ \
|
/* -- skip_dispose_snapshot_ */ \
|
||||||
int prefix##skip_dispose_snapshot_##decl(decl##_node_t **snap) \
|
int prefix##skip_dispose_snapshot_##decl(decl##_snap_t *snap) \
|
||||||
{ \
|
{ \
|
||||||
decl##_node_t *node = *snap; \
|
size_t i; \
|
||||||
|
decl##_node_t *node = snap->nodes[0]; \
|
||||||
|
\
|
||||||
|
i = 0; \
|
||||||
do { \
|
do { \
|
||||||
|
node = (decl##_node_t *)snap->nodes[i]; \
|
||||||
free_node_blk; \
|
free_node_blk; \
|
||||||
node += sizeof(decl##_node_t); \
|
} while (++i < snap->list.length); \
|
||||||
} while (*node != NULL); \
|
|
||||||
free(snap); \
|
free(snap); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
|
|
Loading…
Reference in a new issue