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