| 2339 | |
| 2340 | |
| 2341 | bool new_block_index(size_t numberOfFilledSlotsToExpose) |
| 2342 | { |
| 2343 | auto prevBlockSizeMask = pr_blockIndexSize - 1; |
| 2344 | |
| 2345 | // Create the new block |
| 2346 | pr_blockIndexSize <<= 1; |
| 2347 | auto newRawPtr = static_cast<char*>((Traits::malloc)(sizeof(BlockIndexHeader) + std::alignment_of<BlockIndexEntry>::value - 1 + sizeof(BlockIndexEntry) * pr_blockIndexSize)); |
| 2348 | if (newRawPtr == nullptr) { |
| 2349 | pr_blockIndexSize >>= 1; // Reset to allow graceful retry |
| 2350 | return false; |
| 2351 | } |
| 2352 | |
| 2353 | auto newBlockIndexEntries = reinterpret_cast<BlockIndexEntry*>(details::align_for<BlockIndexEntry>(newRawPtr + sizeof(BlockIndexHeader))); |
| 2354 | |
| 2355 | // Copy in all the old indices, if any |
| 2356 | size_t j = 0; |
| 2357 | if (pr_blockIndexSlotsUsed != 0) { |
| 2358 | auto i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & prevBlockSizeMask; |
| 2359 | do { |
| 2360 | newBlockIndexEntries[j++] = pr_blockIndexEntries[i]; |
| 2361 | i = (i + 1) & prevBlockSizeMask; |
| 2362 | } while (i != pr_blockIndexFront); |
| 2363 | } |
| 2364 | |
| 2365 | // Update everything |
| 2366 | auto header = new (newRawPtr) BlockIndexHeader; |
| 2367 | header->size = pr_blockIndexSize; |
| 2368 | header->front.store(numberOfFilledSlotsToExpose - 1, std::memory_order_relaxed); |
| 2369 | header->entries = newBlockIndexEntries; |
| 2370 | header->prev = pr_blockIndexRaw; // we link the new block to the old one so we can free it later |
| 2371 | |
| 2372 | pr_blockIndexFront = j; |
| 2373 | pr_blockIndexEntries = newBlockIndexEntries; |
| 2374 | pr_blockIndexRaw = newRawPtr; |
| 2375 | blockIndex.store(header, std::memory_order_release); |
| 2376 | |
| 2377 | return true; |
| 2378 | } |
| 2379 | |
| 2380 | private: |
| 2381 | std::atomic<BlockIndexHeader*> blockIndex; |
no outgoing calls
no test coverage detected