| 2894 | |
| 2895 | template<AllocationMode allocMode> |
| 2896 | inline bool insert_block_index_entry(BlockIndexEntry *&idxEntry, index_t blockStartIndex) { |
| 2897 | auto localBlockIndex = blockIndex.load( |
| 2898 | std::memory_order_relaxed); // We're the only writer thread, relaxed is OK |
| 2899 | if (localBlockIndex == nullptr) { |
| 2900 | return false; // this can happen if new_block_index failed in the constructor |
| 2901 | } |
| 2902 | auto newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & |
| 2903 | (localBlockIndex->capacity - 1); |
| 2904 | idxEntry = localBlockIndex->index[newTail]; |
| 2905 | if (idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE || |
| 2906 | idxEntry->value.load(std::memory_order_relaxed) == nullptr) { |
| 2907 | |
| 2908 | idxEntry->key.store(blockStartIndex, std::memory_order_relaxed); |
| 2909 | localBlockIndex->tail.store(newTail, std::memory_order_release); |
| 2910 | return true; |
| 2911 | } |
| 2912 | |
| 2913 | // No room in the old block index, try to allocate another one! |
| 2914 | if (allocMode == CannotAlloc || !new_block_index()) { |
| 2915 | return false; |
| 2916 | } |
| 2917 | localBlockIndex = blockIndex.load(std::memory_order_relaxed); |
| 2918 | newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & |
| 2919 | (localBlockIndex->capacity - 1); |
| 2920 | idxEntry = localBlockIndex->index[newTail]; |
| 2921 | assert(idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE); |
| 2922 | idxEntry->key.store(blockStartIndex, std::memory_order_relaxed); |
| 2923 | localBlockIndex->tail.store(newTail, std::memory_order_release); |
| 2924 | return true; |
| 2925 | } |
| 2926 | |
| 2927 | inline void rewind_block_index_tail() { |
| 2928 | auto localBlockIndex = blockIndex.load(std::memory_order_relaxed); |
nothing calls this directly
no test coverage detected