Allocate memory for a given number of elements
| 257 | |
| 258 | /// Allocate memory for a given number of elements |
| 259 | void reserve(uint64 capacity) { |
| 260 | |
| 261 | if (capacity <= mHashSize) return; |
| 262 | |
| 263 | if (capacity < 16) capacity = 16; |
| 264 | |
| 265 | // Make sure we have a power of two size |
| 266 | if (!isPowerOfTwo(capacity)) { |
| 267 | capacity = nextPowerOfTwo64Bits(capacity); |
| 268 | } |
| 269 | |
| 270 | assert(capacity < INVALID_INDEX); |
| 271 | |
| 272 | assert(capacity > mHashSize); |
| 273 | |
| 274 | // Allocate memory for the buckets |
| 275 | uint64* newBuckets = static_cast<uint64*>(mAllocator.allocate(capacity * sizeof(uint64))); |
| 276 | |
| 277 | // Allocate memory for the entries |
| 278 | uint64 nbAllocatedEntries = static_cast<uint64>(capacity * double(DEFAULT_LOAD_FACTOR)); |
| 279 | assert(nbAllocatedEntries > 0); |
| 280 | |
| 281 | // Make sure capacity is an integral multiple of alignment |
| 282 | nbAllocatedEntries = std::ceil(nbAllocatedEntries / float(GLOBAL_ALIGNMENT)) * GLOBAL_ALIGNMENT; |
| 283 | |
| 284 | V* newEntries = static_cast<V*>(mAllocator.allocate(nbAllocatedEntries * sizeof(V))); |
| 285 | uint64* newNextEntries = static_cast<uint64*>(mAllocator.allocate(nbAllocatedEntries * sizeof(uint64))); |
| 286 | |
| 287 | assert(newEntries != nullptr); |
| 288 | assert(newNextEntries != nullptr); |
| 289 | |
| 290 | // Initialize the new buckets |
| 291 | for (uint64 i=0; i<capacity; i++) { |
| 292 | newBuckets[i] = INVALID_INDEX; |
| 293 | } |
| 294 | |
| 295 | if (mNbAllocatedEntries > 0) { |
| 296 | |
| 297 | assert(mNextEntries != nullptr); |
| 298 | |
| 299 | // Copy the free nodes indices in the nextEntries array |
| 300 | std::memcpy(newNextEntries, mNextEntries, mNbAllocatedEntries * sizeof(uint64)); |
| 301 | } |
| 302 | |
| 303 | // Recompute the buckets (hash) with the new hash size |
| 304 | for (uint64 i=0; i<mHashSize; i++) { |
| 305 | |
| 306 | uint64 entryIndex = mBuckets[i]; |
| 307 | while(entryIndex != INVALID_INDEX) { |
| 308 | |
| 309 | // Get the corresponding bucket |
| 310 | const size_t hashCode = Hash()(mEntries[entryIndex]); |
| 311 | const size_t divider = capacity - 1; |
| 312 | const uint64 bucketIndex = static_cast<uint64>(hashCode & divider); |
| 313 | |
| 314 | newNextEntries[entryIndex] = newBuckets[bucketIndex]; |
| 315 | newBuckets[bucketIndex] = entryIndex; |
| 316 |
nothing calls this directly
no test coverage detected