Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT 2 : // This file is part of AsmJit project <https://asmjit.com> 3 : // 4 : // See asmjit.h or LICENSE.md for license and copyright information 5 : // SPDX-License-Identifier: Zlib 6 : 7 : #ifndef ASMJIT_CORE_ZONEHASH_H_INCLUDED 8 : #define ASMJIT_CORE_ZONEHASH_H_INCLUDED 9 : 10 : #include "zone.h" 11 : 12 : ASMJIT_BEGIN_NAMESPACE 13 : 14 : //! \addtogroup asmjit_zone 15 : //! \{ 16 : 17 : //! Node used by \ref ZoneHash template. 18 : //! 19 : //! You must provide function `bool eq(const Key& key)` in order to make `ZoneHash::get()` working. 20 : class ZoneHashNode { 21 : public: 22 : ASMJIT_NONCOPYABLE(ZoneHashNode) 23 : 24 : inline ZoneHashNode(uint32_t hashCode = 0) noexcept 25 : : _hashNext(nullptr), 26 : _hashCode(hashCode), 27 : _customData(0) {} 28 : 29 : //! Next node in the chain, null if it terminates the chain. 30 : ZoneHashNode* _hashNext; 31 : //! Precalculated hash-code of key. 32 : uint32_t _hashCode; 33 : //! Padding, can be reused by any Node that inherits `ZoneHashNode`. 34 : uint32_t _customData; 35 : }; 36 : 37 : //! Base class used by \ref ZoneHash template 38 : class ZoneHashBase { 39 : public: 40 : ASMJIT_NONCOPYABLE(ZoneHashBase) 41 : 42 : //! Buckets data. 43 : ZoneHashNode** _data; 44 : //! Count of records inserted into the hash table. 45 : size_t _size; 46 : //! Count of hash buckets. 47 : uint32_t _bucketsCount; 48 : //! When buckets array should grow (only checked after insertion). 49 : uint32_t _bucketsGrow; 50 : //! Reciprocal value of `_bucketsCount`. 51 : uint32_t _rcpValue; 52 : //! How many bits to shift right when hash is multiplied with `_rcpValue`. 53 : uint8_t _rcpShift; 54 : //! Prime value index in internal prime array. 55 : uint8_t _primeIndex; 56 : 57 : //! Embedded data, used by empty hash tables. 58 : ZoneHashNode* _embedded[1]; 59 : 60 : //! \name Construction & Destruction 61 : //! \{ 62 : 63 27492 : inline ZoneHashBase() noexcept { 64 : reset(); 65 : } 66 : 67 : inline ZoneHashBase(ZoneHashBase&& other) noexcept { 68 : _data = other._data; 69 : _size = other._size; 70 : _bucketsCount = other._bucketsCount; 71 : _bucketsGrow = other._bucketsGrow; 72 : _rcpValue = other._rcpValue; 73 : _rcpShift = other._rcpShift; 74 : _primeIndex = other._primeIndex; 75 : _embedded[0] = other._embedded[0]; 76 : 77 : if (_data == other._embedded) _data = _embedded; 78 : } 79 : 80 : inline void reset() noexcept { 81 54984 : _data = _embedded; 82 54984 : _size = 0; 83 54984 : _bucketsCount = 1; 84 54984 : _bucketsGrow = 1; 85 54984 : _rcpValue = 1; 86 54984 : _rcpShift = 0; 87 54984 : _primeIndex = 0; 88 27492 : _embedded[0] = nullptr; 89 : } 90 : 91 : inline void release(ZoneAllocator* allocator) noexcept { 92 : ZoneHashNode** oldData = _data; 93 : if (oldData != _embedded) 94 : allocator->release(oldData, _bucketsCount * sizeof(ZoneHashNode*)); 95 : reset(); 96 : } 97 : 98 : //! \} 99 : 100 : //! \name Accessors 101 : //! \{ 102 : 103 : inline bool empty() const noexcept { return _size == 0; } 104 : inline size_t size() const noexcept { return _size; } 105 : 106 : //! \} 107 : 108 : //! \name Utilities 109 : //! \{ 110 : 111 : inline void _swap(ZoneHashBase& other) noexcept { 112 : std::swap(_data, other._data); 113 : std::swap(_size, other._size); 114 : std::swap(_bucketsCount, other._bucketsCount); 115 : std::swap(_bucketsGrow, other._bucketsGrow); 116 : std::swap(_rcpValue, other._rcpValue); 117 : std::swap(_rcpShift, other._rcpShift); 118 : std::swap(_primeIndex, other._primeIndex); 119 : std::swap(_embedded[0], other._embedded[0]); 120 : 121 : if (_data == other._embedded) _data = _embedded; 122 : if (other._data == _embedded) other._data = other._embedded; 123 : } 124 : 125 : //! \cond INTERNAL 126 : inline uint32_t _calcMod(uint32_t hash) const noexcept { 127 0 : uint32_t x = uint32_t((uint64_t(hash) * _rcpValue) >> _rcpShift); 128 0 : return hash - x * _bucketsCount; 129 : } 130 : 131 : ASMJIT_API void _rehash(ZoneAllocator* allocator, uint32_t newCount) noexcept; 132 : ASMJIT_API ZoneHashNode* _insert(ZoneAllocator* allocator, ZoneHashNode* node) noexcept; 133 : ASMJIT_API ZoneHashNode* _remove(ZoneAllocator* allocator, ZoneHashNode* node) noexcept; 134 : //! \endcond 135 : 136 : //! \} 137 : }; 138 : 139 : //! Low-level hash table specialized for storing string keys and POD values. 140 : //! 141 : //! This hash table allows duplicates to be inserted (the API is so low level that it's up to you if you allow it or 142 : //! not, as you should first `get()` the node and then modify it or insert a new node by using `insert()`, depending 143 : //! on the intention). 144 : template<typename NodeT> 145 : class ZoneHash : public ZoneHashBase { 146 : public: 147 : ASMJIT_NONCOPYABLE(ZoneHash) 148 : 149 : typedef NodeT Node; 150 : 151 : //! \name Construction & Destruction 152 : //! \{ 153 : 154 : inline ZoneHash() noexcept 155 : : ZoneHashBase() {} 156 : 157 : inline ZoneHash(ZoneHash&& other) noexcept 158 : : ZoneHash(other) {} 159 : 160 : //! \} 161 : 162 : //! \name Utilities 163 : //! \{ 164 : 165 : inline void swap(ZoneHash& other) noexcept { ZoneHashBase::_swap(other); } 166 : 167 : template<typename KeyT> 168 0 : inline NodeT* get(const KeyT& key) const noexcept { 169 : uint32_t hashMod = _calcMod(key.hashCode()); 170 0 : NodeT* node = static_cast<NodeT*>(_data[hashMod]); 171 : 172 0 : while (node && !key.matches(node)) 173 0 : node = static_cast<NodeT*>(node->_hashNext); 174 0 : return node; 175 : } 176 : 177 0 : inline NodeT* insert(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_insert(allocator, node)); } 178 : inline NodeT* remove(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_remove(allocator, node)); } 179 : 180 : //! \} 181 : }; 182 : 183 : //! \} 184 : 185 : ASMJIT_END_NAMESPACE 186 : 187 : #endif // ASMJIT_CORE_ZONEHASH_H_INCLUDED 188 : 189 : #endif // __PLUMED_HAS_ASMJIT