| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#ifndef POLLFD_RBHASH_H |
|
2
|
|
|
|
|
|
|
#define POLLFD_RBHASH_H |
|
3
|
|
|
|
|
|
|
/* |
|
4
|
|
|
|
|
|
|
Generated by rbhash.cpppp using command |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
cpppp -p 'max_bits=16' \ |
|
7
|
|
|
|
|
|
|
-p 'namespace=pollfd_rbhash' \ |
|
8
|
|
|
|
|
|
|
-p '@default_search_args=('\''int search_fd'\'')' \ |
|
9
|
|
|
|
|
|
|
-p 'default_search_cmp=search_fd - ((struct pollfd*)rbhash)[(int)node_id-1-(int)capacity].fd' \ |
|
10
|
|
|
|
|
|
|
rbhash.cpppp \ |
|
11
|
|
|
|
|
|
|
-o 'public=pollfd_rbhash.h' \ |
|
12
|
|
|
|
|
|
|
-o pollfd_rbhash.c |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
*/ |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
#include |
|
17
|
|
|
|
|
|
|
#include |
|
18
|
|
|
|
|
|
|
#include |
|
19
|
|
|
|
|
|
|
#include |
|
20
|
|
|
|
|
|
|
#include |
|
21
|
|
|
|
|
|
|
#include |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
/* MAX_TREE_HEIGHT is the maximum number of nodes from root to leaf in any |
|
24
|
|
|
|
|
|
|
* correctly balanced tree. The exact formula for the maximum height (including |
|
25
|
|
|
|
|
|
|
* root node) is floor(2*log2(N/2+1)) for a tree of N nodes. |
|
26
|
|
|
|
|
|
|
*/ |
|
27
|
|
|
|
|
|
|
#define POLLFD_RBHASH_MAX_ELEMENTS_8 0x7F |
|
28
|
|
|
|
|
|
|
#define POLLFD_RBHASH_MAX_TREE_HEIGHT_8 12 |
|
29
|
|
|
|
|
|
|
#define POLLFD_RBHASH_MAX_ELEMENTS_16 0x7FFF |
|
30
|
|
|
|
|
|
|
#define POLLFD_RBHASH_MAX_TREE_HEIGHT_16 28 |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
/* This macro tells you the word offset (treating rbhash as an array of words) |
|
33
|
|
|
|
|
|
|
* of the first hash bucket. |
|
34
|
|
|
|
|
|
|
*/ |
|
35
|
|
|
|
|
|
|
#define POLLFD_RBHASH_TABLE_WORD_OFS(capacity) ( (capacity)*2 + 2 ) |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
/* This macro selects the word size needed to index 'capacity' number of |
|
38
|
|
|
|
|
|
|
* user elements. |
|
39
|
|
|
|
|
|
|
*/ |
|
40
|
|
|
|
|
|
|
#define POLLFD_RBHASH_SIZEOF_WORD(capacity) ( \ |
|
41
|
|
|
|
|
|
|
(capacity) <= POLLFD_RBHASH_MAX_ELEMENTS_8? 1 : \ |
|
42
|
|
|
|
|
|
|
2 \ |
|
43
|
|
|
|
|
|
|
) |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
/* This macro defines the total size (in bytes) of the rbhash storage |
|
46
|
|
|
|
|
|
|
* for a given number of elements and buckets. This does not include |
|
47
|
|
|
|
|
|
|
* the user's elements themselves, since those are whatever size the |
|
48
|
|
|
|
|
|
|
* user wants them to be, and rbhash doesn't need to know. |
|
49
|
|
|
|
|
|
|
*/ |
|
50
|
|
|
|
|
|
|
#define POLLFD_RBHASH_SIZEOF(capacity, buckets) ( \ |
|
51
|
|
|
|
|
|
|
POLLFD_RBHASH_SIZEOF_WORD(capacity) \ |
|
52
|
|
|
|
|
|
|
* ( POLLFD_RBHASH_TABLE_WORD_OFS(capacity) + buckets ) \ |
|
53
|
|
|
|
|
|
|
) |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
/* Several functions can operate on a "path", which is a list of |
|
56
|
|
|
|
|
|
|
* references starting at the bucket and ending at a tree node. |
|
57
|
|
|
|
|
|
|
* The path is allocated to the maximum depth that a tree of that |
|
58
|
|
|
|
|
|
|
* word-bits-size could reach. Since this drastically affects the |
|
59
|
|
|
|
|
|
|
* amount of stack used, a struct is declared for each word-bit size. |
|
60
|
|
|
|
|
|
|
* |
|
61
|
|
|
|
|
|
|
* The structs each record their length so that they can be passed |
|
62
|
|
|
|
|
|
|
* interchangably to the functions. You could even allocate custom |
|
63
|
|
|
|
|
|
|
* lengths with alloca, but that seems overcomplicated. |
|
64
|
|
|
|
|
|
|
*/ |
|
65
|
|
|
|
|
|
|
struct pollfd_rbhash_path_8 { |
|
66
|
|
|
|
|
|
|
uint8_t len, lim; |
|
67
|
|
|
|
|
|
|
size_t refs[POLLFD_RBHASH_MAX_TREE_HEIGHT_8]; |
|
68
|
|
|
|
|
|
|
}; |
|
69
|
|
|
|
|
|
|
|
|
70
|
0
|
|
|
|
|
|
inline void pollfd_rbhash_path_8_init(struct pollfd_rbhash_path_8 *p) { |
|
71
|
0
|
|
|
|
|
|
p->len= 0; |
|
72
|
0
|
|
|
|
|
|
p->lim= POLLFD_RBHASH_MAX_TREE_HEIGHT_8; |
|
73
|
0
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
struct pollfd_rbhash_path_16 { |
|
76
|
|
|
|
|
|
|
uint8_t len, lim; |
|
77
|
|
|
|
|
|
|
size_t refs[POLLFD_RBHASH_MAX_TREE_HEIGHT_16]; |
|
78
|
|
|
|
|
|
|
}; |
|
79
|
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
|
inline void pollfd_rbhash_path_16_init(struct pollfd_rbhash_path_16 *p) { |
|
81
|
0
|
|
|
|
|
|
p->len= 0; |
|
82
|
0
|
|
|
|
|
|
p->lim= POLLFD_RBHASH_MAX_TREE_HEIGHT_16; |
|
83
|
0
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
// Different template output may end up with different structs claiming |
|
87
|
|
|
|
|
|
|
// the name of pollfd_rbhash_path, but that should be OK. |
|
88
|
|
|
|
|
|
|
typedef struct pollfd_rbhash_path_16 pollfd_rbhash_path; |
|
89
|
|
|
|
|
|
|
#define pollfd_rbhash_path_init(p) pollfd_rbhash_path_16_init(p) |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
// Iterate one or more places through the R/B tree of a bucket, updating 'path' |
|
92
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_path_step(void *rbhash, size_t capacity, pollfd_rbhash_path *path, int ofs); |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
// Exchange the tree node of one node_id (at the end of 'path') for another node_id |
|
95
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_path_swap(void *rbhash, size_t capacity, pollfd_rbhash_path *path, size_t new_node_id); |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
// implementation detail used to reduce size of inline functions |
|
98
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_capacity_bounds_assertion(size_t capacity); |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
// Add a node_id at the end of 'path', and balance the tree if needed |
|
101
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_path_insert_8(uint8_t *rbhash, pollfd_rbhash_path *path, size_t node_id); |
|
102
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_path_insert_16(uint16_t *rbhash, pollfd_rbhash_path *path, size_t node_id); |
|
103
|
|
|
|
|
|
|
inline size_t pollfd_rbhash_path_insert(void *rbhash, size_t capacity, pollfd_rbhash_path *path, size_t node) { |
|
104
|
|
|
|
|
|
|
return |
|
105
|
|
|
|
|
|
|
(capacity <= POLLFD_RBHASH_MAX_ELEMENTS_8)? pollfd_rbhash_path_insert_8((uint8_t*) rbhash, path, node) : |
|
106
|
|
|
|
|
|
|
(capacity <= POLLFD_RBHASH_MAX_ELEMENTS_16)? pollfd_rbhash_path_insert_16((uint16_t*) rbhash, path, node) : |
|
107
|
|
|
|
|
|
|
pollfd_rbhash_capacity_bounds_assertion(capacity); |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
// Remove the node_id from the end of 'path', and balance the tree if needed |
|
111
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_path_delete_8(uint8_t *rbhash, pollfd_rbhash_path *path); |
|
112
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_path_delete_16(uint16_t *rbhash, pollfd_rbhash_path *path); |
|
113
|
|
|
|
|
|
|
inline size_t pollfd_rbhash_path_delete(void *rbhash, size_t capacity, pollfd_rbhash_path *path) { |
|
114
|
|
|
|
|
|
|
return |
|
115
|
|
|
|
|
|
|
(capacity <= POLLFD_RBHASH_MAX_ELEMENTS_8)? pollfd_rbhash_path_delete_8((uint8_t*) rbhash, path) : |
|
116
|
|
|
|
|
|
|
(capacity <= POLLFD_RBHASH_MAX_ELEMENTS_16)? pollfd_rbhash_path_delete_16((uint16_t*) rbhash, path) : |
|
117
|
|
|
|
|
|
|
pollfd_rbhash_capacity_bounds_assertion(capacity); |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
// Find a node_id matching the search criteria and fill in the 'path' to it, else return 0 |
|
121
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_find_path(void *rbhash, size_t capacity, pollfd_rbhash_path *path, size_t bucket_idx, int search_fd); |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
// Simplified search for node_id, without building a path |
|
124
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_find(void *rbhash, size_t capacity, size_t bucket_idx, int search_fd); |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
// Insert a node_id, unless one already matches the search criteria |
|
127
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_insert(void *rbhash, size_t capacity, size_t node_id, size_t bucket_idx, int search_fd); |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
// Delete a node matching the search criteria |
|
130
|
|
|
|
|
|
|
extern size_t pollfd_rbhash_delete(void *rbhash, size_t capacity, size_t bucket_idx, int search_fd); |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
// Handy for gdb: |
|
134
|
|
|
|
|
|
|
// p pollfd_rbhash_print(rbhash, capacity, buckets, NULL, NULL, stdout) |
|
135
|
|
|
|
|
|
|
extern void pollfd_rbhash_print(void *rbhash, size_t capacity, size_t n_buckets, |
|
136
|
|
|
|
|
|
|
void (*print_node)(void*,size_t,FILE*), void* userdata, FILE *out); |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
#endif |