MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / MOODYCAMEL_NO_TSAN enqueue_bulk

Function MOODYCAMEL_NO_TSAN enqueue_bulk

deps/concurrentqueue/concurrentqueue.h:2040–2214  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2038
2039 template<AllocationMode allocMode, typename It>
2040 bool MOODYCAMEL_NO_TSAN enqueue_bulk(It itemFirst, size_t count)
2041 {
2042 // First, we need to make sure we have enough room to enqueue all of the elements;
2043 // this means pre-allocating blocks and putting them in the block index (but only if
2044 // all the allocations succeeded).
2045 index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed);
2046 auto startBlock = this->tailBlock;
2047 auto originalBlockIndexFront = pr_blockIndexFront;
2048 auto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed;
2049
2050 Block* firstAllocatedBlock = nullptr;
2051
2052 // Figure out how many blocks we'll need to allocate, and do so
2053 size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1));
2054 index_t currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);
2055 if (blockBaseDiff > 0) {
2056 // Allocate as many blocks as possible from ahead
2057 while (blockBaseDiff > 0 && this->tailBlock != nullptr && this->tailBlock->next != firstAllocatedBlock && this->tailBlock->next->ConcurrentQueue::Block::template is_empty<explicit_context>()) {
2058 blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);
2059 currentTailIndex += static_cast<index_t>(BLOCK_SIZE);
2060
2061 this->tailBlock = this->tailBlock->next;
2062 firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock;
2063
2064 auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];
2065 entry.base = currentTailIndex;
2066 entry.block = this->tailBlock;
2067 pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);
2068 }
2069
2070 // Now allocate as many blocks as necessary from the block pool
2071 while (blockBaseDiff > 0) {
2072 blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);
2073 currentTailIndex += static_cast<index_t>(BLOCK_SIZE);
2074
2075 auto head = this->headIndex.load(std::memory_order_relaxed);
2076 assert(!details::circular_less_than<index_t>(currentTailIndex, head));
2077 bool full = !details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head));
2078 if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize || full) {
2079 MOODYCAMEL_CONSTEXPR_IF (allocMode == CannotAlloc) {
2080 // Failed to allocate, undo changes (but keep injected blocks)
2081 pr_blockIndexFront = originalBlockIndexFront;
2082 pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;
2083 this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;
2084 return false;
2085 }
2086 else if (full || !new_block_index(originalBlockIndexSlotsUsed)) {
2087 // Failed to allocate, undo changes (but keep injected blocks)
2088 pr_blockIndexFront = originalBlockIndexFront;
2089 pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;
2090 this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;
2091 return false;
2092 }
2093
2094 // pr_blockIndexFront is updated inside new_block_index, so we need to
2095 // update our fallback value too (since we keep the new index even if we
2096 // later fail)
2097 originalBlockIndexFront = originalBlockIndexSlotsUsed;

Callers

nothing calls this directly

Calls 3

MOODYCAMEL_CONSTEXPR_IFFunction · 0.85
new_block_indexFunction · 0.85
deref_noexceptFunction · 0.85

Tested by

no test coverage detected