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