forked from greensky00/skiplist
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpure_c_example.c
135 lines (118 loc) · 4.24 KB
/
pure_c_example.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "skiplist.h"
#include <stdio.h>
#include <stdlib.h>
// Define a node that contains key and value pair.
struct my_node {
// Metadata for skiplist node.
skiplist_node snode;
// My data here: {int, int} pair.
int key;
int value;
};
// Define a comparison function for `my_node`.
static int my_cmp(skiplist_node* a, skiplist_node* b, void* aux) {
// Get `my_node` from skiplist node `a` and `b`.
struct my_node *aa, *bb;
aa = _get_entry(a, struct my_node, snode);
bb = _get_entry(b, struct my_node, snode);
// aa < bb: return neg
// aa == bb: return 0
// aa > bb: return pos
if (aa->key < bb->key) return -1;
if (aa->key > bb->key) return 1;
return 0;
}
int main() {
skiplist_raw slist;
// Initialize skiplist.
skiplist_init(&slist, my_cmp);
// << Insertion >>
// Allocate & insert 3 KV pairs: {0, 0}, {1, 10}, {2, 20}.
struct my_node* nodes[3];
for (int i=0; i<3; ++i) {
// Allocate memory.
nodes[i] = (struct my_node*)malloc(sizeof(struct my_node));
// Initialize node.
skiplist_init_node(&nodes[i]->snode);
// Assign key and value.
nodes[i]->key = i;
nodes[i]->value = i*10;
// Insert into skiplist.
skiplist_insert(&slist, &nodes[i]->snode);
}
// << Point lookup >>
for (int i=0; i<3; ++i) {
// Define a query.
struct my_node query;
query.key = i;
// Find a skiplist node `cursor`.
skiplist_node* cursor = skiplist_find(&slist, &query.snode);
// If `cursor` is NULL, key doesn't exist.
if (!cursor) continue;
// Get `my_node` from `cursor`.
// Note: found->snode == *cursor
struct my_node* found = _get_entry(cursor, struct my_node, snode);
printf("[point lookup] key: %d, value: %d\n", found->key, found->value);
// Release `cursor` (== &found->snode).
// Other thread cannot free `cursor` until `cursor` is released.
skiplist_release_node(cursor);
}
// << Erase >>
// Erase the KV pair for key 1: {1, 10}.
{
// Define a query.
struct my_node query;
query.key = 1;
// Find a skiplist node `cursor`.
skiplist_node* cursor = skiplist_find(&slist, &query.snode);
// Get `my_node` from `cursor`.
// Note: found->snode == *cursor
struct my_node* found = _get_entry(cursor, struct my_node, snode);
printf("[erase] key: %d, value: %d\n", found->key, found->value);
// Detach `found` from skiplist.
skiplist_erase_node(&slist, &found->snode);
// Release `found`, to free its memory.
skiplist_release_node(&found->snode);
// Free `found` after it becomes safe.
skiplist_wait_for_free(&found->snode);
skiplist_free_node(&found->snode);
free(found);
}
// << Iteration >>
{
// Get the first cursor.
skiplist_node* cursor = skiplist_begin(&slist);
while (cursor) {
// Get `entry` from `cursor`.
// Note: entry->snode == *cursor
struct my_node* entry = _get_entry(cursor, struct my_node, snode);
printf("[iteration] key: %d, value: %d\n", entry->key, entry->value);
// Get next `cursor`.
cursor = skiplist_next(&slist, cursor);
// Release `entry`.
skiplist_release_node(&entry->snode);
}
}
// << Destroy >>
{
// Iterate and free all nodes.
skiplist_node* cursor = skiplist_begin(&slist);
while (cursor) {
struct my_node* entry = _get_entry(cursor, struct my_node, snode);
printf("[destroy] key: %d, value: %d\n", entry->key, entry->value);
// Get next `cursor`.
cursor = skiplist_next(&slist, cursor);
// Detach `entry` from skiplist.
skiplist_erase_node(&slist, &entry->snode);
// Release `entry`, to free its memory.
skiplist_release_node(&entry->snode);
// Free `entry` after it becomes safe.
skiplist_wait_for_free(&entry->snode);
skiplist_free_node(&entry->snode);
free(entry);
}
}
// Free skiplist.
skiplist_free(&slist);
return 0;
}