xref: /f-stack/app/micro_thread/hash_list.h (revision 9bd490e8)
1 
2 /**
3  * Tencent is pleased to support the open source community by making MSEC available.
4  *
5  * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6  *
7  * Licensed under the GNU General Public License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License. You may
9  * obtain a copy of the License at
10  *
11  *     https://opensource.org/licenses/GPL-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software distributed under the
14  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15  * either express or implied. See the License for the specific language governing permissions
16  * and limitations under the License.
17  */
18 
19 
20 /**
21   *   @filename  hash_list.h
22   *   @time  2013-06-11
23   */
24 
25 #ifndef __HASH_LIST_FILE__
26 #define __HASH_LIST_FILE__
27 
28 #include <stdlib.h>
29 #include <math.h>
30 #include <string.h>
31 #include <stdint.h>
32 #include <assert.h>
33 
34 namespace NS_MICRO_THREAD {
35 
36 class HashKey
37 {
38 private:
39     HashKey*  _next_entry;
40     uint32_t  _hash_value;
41     void*     _data_ptr;
42 
43 public:
44 
45     friend class HashList;
46 
47     HashKey():_next_entry(NULL), _hash_value(0), _data_ptr(NULL) {};
48     virtual ~HashKey(){};
49 
50     virtual uint32_t HashValue() = 0;
51 
52     virtual int HashCmp(HashKey* rhs) = 0;
53 
54     virtual void HashIterate() {
55         return;
56     };
57 
58     void* GetDataPtr() {
59         return _data_ptr;
60     };
61     void SetDataPtr(void* data) {
62         _data_ptr = data;
63     };
64 };
65 
66 class HashList
67 {
68 public:
69 
70     explicit HashList(int max = 100000) {
71         _max = GetMaxPrimeNum((max > 2) ? max : 100000);
72         _buckets = (HashKey**)calloc(_max, sizeof(HashKey*));
73         _count = 0;
74     };
75     virtual ~HashList()  {
76         if (_buckets) {
77             free(_buckets);
78             _buckets = NULL;
79         }
80         _count = 0;
81     };
82 
83     int HashSize() {
84         return _count;
85     };
86 
87     /**
88      *  @brief hash insert key.
89      */
90     int HashInsert(HashKey* key) {
91         if (!key || !_buckets) {
92             return -1;
93         }
94 
95         if ((key->_hash_value != 0) || (key->_next_entry != NULL)) {
96             return -2;
97         }
98 
99         key->_hash_value = key->HashValue();
100         int idx = (key->_hash_value) % _max;
101 
102         HashKey* next_item = _buckets[idx];
103         _buckets[idx]      = key;
104         key->_next_entry   = next_item;
105         _count++;
106         return 0;
107     }
108 
109     /**
110      *  @brief hash lookup key.
111      */
112     HashKey* HashFind(HashKey* key) {
113         if (!key || !_buckets) {
114             return NULL;
115         }
116 
117         uint32_t hash = key->HashValue();
118         int idx = hash % _max;
119         HashKey* item = _buckets[idx];
120 
121         for (; item != NULL; item = item->_next_entry) {
122             if (item->_hash_value != hash) {
123                 continue;
124             }
125 
126             if (item->HashCmp(key) == 0) {
127                 break;
128             }
129         }
130 
131         return item;
132     }
133 
134     /**
135      *  @brief hash lookup key.
136      */
137     void* HashFindData(HashKey* key) {
138         HashKey* item = HashFind(key);
139         if (!item) {
140             return NULL;
141         } else {
142             return item->_data_ptr;
143         }
144     };
145 
146 
147     /**
148      *  @brief hash remove key.
149      */
150     void HashRemove(HashKey* key) {
151         if (!key || !_buckets) {
152             return;
153         }
154 
155         uint32_t hash = key->HashValue();
156         int idx = hash % _max;
157         HashKey* item = _buckets[idx];
158         HashKey* prev = NULL;
159 
160         for (; item != NULL; prev = item, item = item->_next_entry) {
161             if ((item->_hash_value == hash) && (item->HashCmp(key) == 0)){
162                 if (prev == NULL) {
163                     _buckets[idx] = item->_next_entry;
164                 } else {
165                     prev->_next_entry = item->_next_entry;
166                 }
167                 item->_hash_value = 0;
168                 item->_next_entry = NULL;
169                 _count--;
170                 break;
171             }
172         }
173     }
174 
175     /**
176      *  @brief hash loop.
177      */
178     void HashForeach() {
179         if (!_buckets) {
180             return;
181         }
182 
183         for (int i = 0; i < _max; i++) {
184             HashKey* item = _buckets[i];
185             for (; item != NULL; item = item->_next_entry) {
186                 item->HashIterate();
187             }
188         }
189     }
190 
191     /**
192      *  @brief traverse hash list, low performance, only for remove.
193      */
194     HashKey* HashGetFirst() {
195         if (!_buckets) {
196             return NULL;
197         }
198 
199         for (int i = 0; i < _max; i++) {
200             if (_buckets[i]) {
201                 return _buckets[i];
202             }
203         }
204 
205         return NULL;
206     }
207 
208 private:
209 
210     int GetMaxPrimeNum(int num)
211     {
212         int sqrt_value = (int)sqrt(num);
213         for (int i = num; i > 0; i--)
214         {
215             int flag = 1;
216             for (int k = 2; k <= sqrt_value; k++)
217             {
218                 if (i % k == 0)
219                 {
220                     flag = 0;
221                     break;
222                 }
223             }
224 
225             if (flag == 1)
226             {
227                 return i;
228             }
229         }
230 
231         return 0;
232     };
233 
234 
235 private:
236     HashKey** _buckets;
237     int       _count;
238     int       _max;
239 };
240 
241 }
242 
243 
244 #endif
245 
246