4
4
5
5
#include <stddef.h>
6
6
7
- #define container_of (list_ptr , container_type , member_name ) \
8
- ({ \
9
- const typeof(((container_type *) 0)->member_name) *__member_ptr = \
10
- (list_ptr); \
11
- (container_type *) ((char *) __member_ptr - \
12
- offsetof(container_type, member_name)); \
13
- })
7
+ #include <stdint.h>
8
+ #include <stdlib.h>
9
+ #include <stdbool.h>
14
10
15
- struct list_entry {
16
- struct list_entry * next , * prev ;
11
+ struct hlist_head {
12
+ struct hlist_node * first ;
17
13
};
18
14
19
- #define list_element (list_ptr , type , member ) \
20
- container_of(list_ptr, type, member)
15
+ struct hlist_node {
16
+ struct hlist_node * next , * * pprev ;
17
+ };
21
18
22
- #define list_first (root_ptr , type , member ) \
23
- list_element((root_ptr)->next, type, member)
19
+ #define HLIST_HEAD_INIT { .first = NULL }
20
+ #define HLIST_HEAD (name ) struct hlist_head name = { .first = NULL }
21
+ #define INIT_HLIST_HEAD (ptr ) ((ptr)->first = NULL)
24
22
25
- static inline struct list_entry * list_next (struct list_entry * root ,
26
- struct list_entry * current )
23
+ static inline void INIT_HLIST_NODE (struct hlist_node * h )
27
24
{
28
- if (( root == root -> next ) || ( current -> next == root )) return NULL ;
29
- return current -> next ;
25
+ h -> next = NULL ;
26
+ h -> pprev = NULL ;
30
27
}
31
28
32
- /* FIXME: this forbids having 2 list_for_each in the same function, because the
33
- * variable __ptr will be defined twice, which results in a compilation error.
34
- * The __ptr is necessary because some functions delete iter while traversing
35
- * the list.
36
- */
37
- #define list_for_each_forward (root_ptr , iter ) \
38
- struct list_entry *__ptr; \
39
- for (iter = (root_ptr)->next, __ptr = (struct list_entry *) (iter)->next; \
40
- iter != (root_ptr); iter = (typeof((iter))) __ptr, \
41
- __ptr = (struct list_entry *) iter->next)
42
-
43
- #define list_for_each (root_ptr , iter ) list_for_each_forward(root_ptr, iter)
29
+ static inline int hlist_empty (const struct hlist_head * h )
30
+ {
31
+ return !h -> first ;
32
+ }
44
33
45
- static inline void list_root_init (struct list_entry * root )
34
+ static inline void hlist_add_head (struct hlist_node * n , struct hlist_head * h )
46
35
{
47
- root -> next = root -> prev = root ;
36
+ struct hlist_node * first = h -> first ;
37
+ n -> next = first ;
38
+ if (first )
39
+ first -> pprev = & n -> next ;
40
+ h -> first = n ;
41
+ n -> pprev = & h -> first ;
48
42
}
49
43
50
- static inline void list_add (struct list_entry * root , struct list_entry * entry )
44
+ #include <stdbool.h>
45
+
46
+ static inline bool hlist_is_singular_node (struct hlist_node * n , struct hlist_head * h )
51
47
{
52
- struct list_entry * prev_entry = root ;
53
- struct list_entry * next_entry = root -> next ;
54
- entry -> next = next_entry , entry -> prev = prev_entry ;
55
- prev_entry -> next = entry , next_entry -> prev = entry ;
48
+ return !n -> next && n -> pprev == & h -> first ;
56
49
}
57
50
58
- #define list_add_prev (root , entry ) list_add((root)->prev, (entry))
51
+ #define container_of (list_ptr , container_type , member_name ) \
52
+ ({ \
53
+ const typeof(((container_type *) 0)->member_name) *__member_ptr = \
54
+ (list_ptr); \
55
+ (container_type *) ((char *) __member_ptr - \
56
+ offsetof(container_type, member_name)); \
57
+ })
59
58
60
- #define list_empty ( root ) (root == (root)->next )
59
+ #define hlist_entry ( ptr , type , member ) container_of(ptr,type,member )
61
60
62
- #include <stdint.h>
63
- #include <stdlib.h>
61
+ #define hlist_first_entry (head , type , member ) \
62
+ hlist_entry((head)->first, type, member)
63
+
64
+ #define hlist_for_each (pos , head ) \
65
+ for (pos = (head)->first; pos ; pos = pos->next)
66
+
67
+ #define hlist_for_each_safe (pos , n , head ) \
68
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
69
+ pos = n)
70
+
71
+ #define hlist_entry_safe (ptr , type , member ) \
72
+ ({ typeof(ptr) ____ptr = (ptr); \
73
+ ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
74
+ })
75
+
76
+ #define hlist_for_each_entry (pos , head , member ) \
77
+ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
78
+ pos; \
79
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
80
+
81
+ #define hlist_for_each_entry_safe (pos , n , head , member ) \
82
+ for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
83
+ pos && ({ n = pos->member.next; 1; }); \
84
+ pos = hlist_entry_safe(n, typeof(*pos), member))
85
+
86
+ /* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
87
+ #define hash_min (val , bits ) \
88
+ (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
89
+
90
+ static inline void __hash_init (struct hlist_head * ht , unsigned int sz )
91
+ {
92
+ unsigned int i ;
93
+
94
+ for (i = 0 ; i < sz ; i ++ )
95
+ INIT_HLIST_HEAD (& ht [i ]);
96
+ }
64
97
65
98
typedef uint32_t hash_t ;
66
99
67
100
/* A node of the table */
68
101
struct ht_node {
69
102
hash_t hash ;
70
- struct list_entry list ;
103
+ struct hlist_node list ;
71
104
};
72
105
73
106
/* user-defined functions */
@@ -79,7 +112,7 @@ struct htable {
79
112
hashfunc_t * hashfunc ;
80
113
cmp_t * cmp ;
81
114
uint32_t n_buckets ;
82
- struct list_entry * buckets ;
115
+ struct hlist_head * buckets ;
83
116
};
84
117
85
118
/* Initializes a hash table */
@@ -90,9 +123,8 @@ static inline int ht_init(struct htable *h,
90
123
{
91
124
h -> hashfunc = hashfunc , h -> cmp = cmp ;
92
125
h -> n_buckets = n_buckets ;
93
- h -> buckets = malloc (sizeof (struct list_entry ) * n_buckets );
94
- for (size_t i = 0 ; i < h -> n_buckets ; i ++ ) list_root_init (& h -> buckets [i ]);
95
-
126
+ h -> buckets = malloc (sizeof (struct hlist_head ) * n_buckets );
127
+ __hash_init (h -> buckets , h -> n_buckets );
96
128
return 0 ;
97
129
}
98
130
@@ -112,9 +144,9 @@ static inline struct ht_node *ht_find(struct htable *h, void *key)
112
144
uint32_t bkt ;
113
145
h -> hashfunc (key , & hval , & bkt );
114
146
115
- struct list_entry * head = & h -> buckets [bkt ], * iter ;
116
- list_for_each ( head , iter ) {
117
- struct ht_node * n = list_element ( iter , struct ht_node , list );
147
+ struct hlist_head * head = & h -> buckets [bkt ];
148
+ struct ht_node * n ;
149
+ hlist_for_each_entry ( n , head , list ) {
118
150
if (n -> hash == hval ) {
119
151
int res = h -> cmp (n , key );
120
152
if (!res ) return n ;
@@ -127,45 +159,56 @@ static inline struct ht_node *ht_find(struct htable *h, void *key)
127
159
/* Insert a new element with the key 'key' in the htable.
128
160
* Return 0 if success.
129
161
*/
162
+ #include <stdio.h>
163
+
130
164
static inline int ht_insert (struct htable * h , struct ht_node * n , void * key )
131
165
{
132
166
hash_t hval ;
133
167
uint32_t bkt ;
134
168
h -> hashfunc (key , & hval , & bkt );
135
169
n -> hash = hval ;
136
170
137
- struct list_entry * head = & h -> buckets [bkt ], * iter ;
138
- list_for_each (head , iter ) {
139
- struct ht_node * tmp = list_element (iter , struct ht_node , list );
171
+ struct hlist_head * head = & h -> buckets [bkt ];
172
+ struct hlist_node * iter ;
173
+ hlist_for_each (iter , head ) {
174
+ struct ht_node * tmp = hlist_entry (iter , struct ht_node , list );
140
175
if (tmp -> hash >= hval ) {
141
176
int cmp = h -> cmp (tmp , key );
142
177
if (!cmp ) /* already exist */
143
178
return -1 ;
144
179
if (cmp > 0 ) {
145
- list_add_prev ( iter , & n -> list );
180
+ hlist_add_head ( & n -> list , head );
146
181
return 0 ;
147
182
}
148
183
}
149
184
}
150
185
151
- list_add_prev ( head , & n -> list );
186
+ hlist_add_head ( & n -> list , head );
152
187
return 0 ;
153
188
}
154
189
155
190
static inline struct ht_node * ht_get_first (struct htable * h , uint32_t bucket )
156
191
{
157
- struct list_entry * head = & h -> buckets [bucket ];
158
- if (list_empty (head )) return NULL ;
159
- return list_first (head , struct ht_node , list );
192
+ struct hlist_head * head = & h -> buckets [bucket ];
193
+ if (hlist_empty (head )) return NULL ;
194
+ return hlist_first_entry (head , struct ht_node , list );
195
+ }
196
+
197
+ static inline struct hlist_node * hlist_next (struct hlist_head * root ,
198
+ struct hlist_node * current )
199
+ {
200
+ if ((hlist_empty (root )) || hlist_is_singular_node (current , root ) || !current ) return NULL ;
201
+ return current -> next ;
160
202
}
161
203
162
204
static inline struct ht_node * ht_get_next (struct htable * h ,
163
- uint32_t bucket ,
164
- struct ht_node * n )
205
+ uint32_t bucket ,
206
+ struct ht_node * n )
165
207
{
166
- struct list_entry * ln = list_next (& h -> buckets [bucket ], & n -> list );
208
+ printf ("%s" , & n -> list ? "" : "0" );
209
+ struct hlist_node * ln = hlist_next (& h -> buckets [bucket ], & n -> list );
167
210
if (!ln ) return NULL ;
168
- return list_element (ln , struct ht_node , list );
211
+ return hlist_entry (ln , struct ht_node , list );
169
212
}
170
213
171
214
/* cache of words. Count the number of word using a modified hash table */
@@ -211,7 +254,7 @@ static struct wc_cache main_cache, *thread_caches;
211
254
static inline int __wc_cmp (struct ht_node * n , void * key , char m )
212
255
{
213
256
struct wc_word * w = m ? container_of (n , struct wc_word , node_main )
214
- : container_of (n , struct wc_word , node );
257
+ : container_of (n , struct wc_word , node );
215
258
return strcasecmp (GET_WORD (w ), (char * ) key );
216
259
}
217
260
@@ -384,8 +427,8 @@ int wc_print(int id)
384
427
for (; iter ; iter = ht_get_next (& cache -> htable , j , iter )) {
385
428
struct wc_word * w =
386
429
valid ? container_of (iter , struct wc_word , node_main )
387
- : container_of (iter , struct wc_word , node );
388
- printf ("%s : %d\n" , GET_WORD (w ), w -> counter );
430
+ : container_of (iter , struct wc_word , node );
431
+ // printf("%s : %d\n", GET_WORD(w), w->counter);
389
432
bkt_total ++ , total ++ ;
390
433
count_total += w -> counter ;
391
434
}
@@ -402,13 +445,16 @@ static int __wc_destroy(struct wc_cache *wcc, int id)
402
445
int valid = (id == -1 );
403
446
for (uint32_t j = 0 ; j < n_buckets ; j ++ ) {
404
447
struct ht_node * iter = ht_get_first (& wcc -> htable , j );
405
- for (; iter ; iter = ht_get_next (& wcc -> htable , j , iter )) {
448
+ struct ht_node * tmp = ht_get_next (& wcc -> htable , j , iter );
449
+ for (; tmp ; iter = tmp , tmp = ht_get_next (& wcc -> htable , j , tmp )) {
406
450
struct wc_word * w =
407
451
valid ? container_of (iter , struct wc_word , node_main )
408
- : container_of (iter , struct wc_word , node );
452
+ : container_of (iter , struct wc_word , node );
453
+
409
454
free (w -> full_word );
410
455
free (w );
411
456
}
457
+
412
458
}
413
459
return 0 ;
414
460
}
0 commit comments