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