| 2929 | } |
| 2930 | |
| 2931 | inline size_t get_block_index_index_for_index(index_t index, BlockIndexHeader*& localBlockIndex) const |
| 2932 | { |
| 2933 | #ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX |
| 2934 | debug::DebugLock lock(mutex); |
| 2935 | #endif |
| 2936 | index &= ~static_cast<index_t>(BLOCK_SIZE - 1); |
| 2937 | localBlockIndex = blockIndex.load(std::memory_order_acquire); |
| 2938 | auto tail = localBlockIndex->tail.load(std::memory_order_acquire); |
| 2939 | auto tailBase = localBlockIndex->index[tail]->key.load(std::memory_order_relaxed); |
| 2940 | assert(tailBase != INVALID_BLOCK_BASE); |
| 2941 | // Note: Must use division instead of shift because the index may wrap around, causing a negative |
| 2942 | // offset, whose negativity we want to preserve |
| 2943 | auto offset = static_cast<size_t>(static_cast<typename std::make_signed<index_t>::type>(index - tailBase) / BLOCK_SIZE); |
| 2944 | size_t idx = (tail + offset) & (localBlockIndex->capacity - 1); |
| 2945 | assert(localBlockIndex->index[idx]->key.load(std::memory_order_relaxed) == index && localBlockIndex->index[idx]->value.load(std::memory_order_relaxed) != nullptr); |
| 2946 | return idx; |
| 2947 | } |
| 2948 | |
| 2949 | bool new_block_index() |
| 2950 | { |
no outgoing calls
no test coverage detected