44
55#include <stddef.h>
66
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>
1410
15- struct list_entry {
16- struct list_entry * next , * prev ;
11+ struct hlist_head {
12+ struct hlist_node * first ;
1713};
1814
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+ };
2118
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)
2422
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 )
2724{
28- if (( root == root -> next ) || ( current -> next == root )) return NULL ;
29- return current -> next ;
25+ h -> next = NULL ;
26+ h -> pprev = NULL ;
3027}
3128
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+ }
4433
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 )
4635{
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 ;
4842}
4943
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 )
5147{
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 ;
5649}
5750
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+ })
5958
60- #define list_empty ( root ) (root == (root)->next )
59+ #define hlist_entry ( ptr , type , member ) container_of(ptr,type,member )
6160
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+ }
6497
6598typedef uint32_t hash_t ;
6699
67100/* A node of the table */
68101struct ht_node {
69102 hash_t hash ;
70- struct list_entry list ;
103+ struct hlist_node list ;
71104};
72105
73106/* user-defined functions */
@@ -79,7 +112,7 @@ struct htable {
79112 hashfunc_t * hashfunc ;
80113 cmp_t * cmp ;
81114 uint32_t n_buckets ;
82- struct list_entry * buckets ;
115+ struct hlist_head * buckets ;
83116};
84117
85118/* Initializes a hash table */
@@ -90,9 +123,8 @@ static inline int ht_init(struct htable *h,
90123{
91124 h -> hashfunc = hashfunc , h -> cmp = cmp ;
92125 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 );
96128 return 0 ;
97129}
98130
@@ -112,9 +144,9 @@ static inline struct ht_node *ht_find(struct htable *h, void *key)
112144 uint32_t bkt ;
113145 h -> hashfunc (key , & hval , & bkt );
114146
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 ) {
118150 if (n -> hash == hval ) {
119151 int res = h -> cmp (n , key );
120152 if (!res ) return n ;
@@ -127,45 +159,56 @@ static inline struct ht_node *ht_find(struct htable *h, void *key)
127159/* Insert a new element with the key 'key' in the htable.
128160 * Return 0 if success.
129161 */
162+ #include <stdio.h>
163+
130164static inline int ht_insert (struct htable * h , struct ht_node * n , void * key )
131165{
132166 hash_t hval ;
133167 uint32_t bkt ;
134168 h -> hashfunc (key , & hval , & bkt );
135169 n -> hash = hval ;
136170
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 );
140175 if (tmp -> hash >= hval ) {
141176 int cmp = h -> cmp (tmp , key );
142177 if (!cmp ) /* already exist */
143178 return -1 ;
144179 if (cmp > 0 ) {
145- list_add_prev ( iter , & n -> list );
180+ hlist_add_head ( & n -> list , head );
146181 return 0 ;
147182 }
148183 }
149184 }
150185
151- list_add_prev ( head , & n -> list );
186+ hlist_add_head ( & n -> list , head );
152187 return 0 ;
153188}
154189
155190static inline struct ht_node * ht_get_first (struct htable * h , uint32_t bucket )
156191{
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 ;
160202}
161203
162204static 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 )
165207{
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 );
167210 if (!ln ) return NULL ;
168- return list_element (ln , struct ht_node , list );
211+ return hlist_entry (ln , struct ht_node , list );
169212}
170213
171214/* 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;
211254static inline int __wc_cmp (struct ht_node * n , void * key , char m )
212255{
213256 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 );
215258 return strcasecmp (GET_WORD (w ), (char * ) key );
216259}
217260
@@ -384,8 +427,8 @@ int wc_print(int id)
384427 for (; iter ; iter = ht_get_next (& cache -> htable , j , iter )) {
385428 struct wc_word * w =
386429 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);
389432 bkt_total ++ , total ++ ;
390433 count_total += w -> counter ;
391434 }
@@ -402,13 +445,16 @@ static int __wc_destroy(struct wc_cache *wcc, int id)
402445 int valid = (id == -1 );
403446 for (uint32_t j = 0 ; j < n_buckets ; j ++ ) {
404447 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 )) {
406450 struct wc_word * w =
407451 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+
409454 free (w -> full_word );
410455 free (w );
411456 }
457+
412458 }
413459 return 0 ;
414460}
0 commit comments