MCPcopy Create free account
hub / github.com/danoon2/Boxedwine / enqueue_bulk

Function enqueue_bulk

source/util/concurrentqueue.h:2626–2764  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2624#endif
2625 template<AllocationMode allocMode, typename It>
2626 bool enqueue_bulk(It itemFirst, size_t count)
2627 {
2628 // First, we need to make sure we have enough room to enqueue all of the elements;
2629 // this means pre-allocating blocks and putting them in the block index (but only if
2630 // all the allocations succeeded).
2631
2632 // Note that the tailBlock we start off with may not be owned by us any more;
2633 // this happens if it was filled up exactly to the top (setting tailIndex to
2634 // the first index of the next block which is not yet allocated), then dequeued
2635 // completely (putting it on the free list) before we enqueue again.
2636
2637 index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed);
2638 auto startBlock = this->tailBlock;
2639 Block* firstAllocatedBlock = nullptr;
2640 auto endBlock = this->tailBlock;
2641
2642 // Figure out how many blocks we'll need to allocate, and do so
2643 size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1));
2644 index_t currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);
2645 if (blockBaseDiff > 0) {
2646#ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX
2647 debug::DebugLock lock(mutex);
2648#endif
2649 do {
2650 blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);
2651 currentTailIndex += static_cast<index_t>(BLOCK_SIZE);
2652
2653 // Find out where we'll be inserting this block in the block index
2654 BlockIndexEntry* idxEntry = nullptr; // initialization here unnecessary but compiler can't always tell
2655 Block* newBlock;
2656 bool indexInserted = false;
2657 auto head = this->headIndex.load(std::memory_order_relaxed);
2658 assert(!details::circular_less_than<index_t>(currentTailIndex, head));
2659 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));
2660
2661 if (full || !(indexInserted = insert_block_index_entry<allocMode>(idxEntry, currentTailIndex)) || (newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>()) == nullptr) {
2662 // Index allocation or block allocation failed; revert any other allocations
2663 // and index insertions done so far for this operation
2664 if (indexInserted) {
2665 rewind_block_index_tail();
2666 idxEntry->value.store(nullptr, std::memory_order_relaxed);
2667 }
2668 currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);
2669 for (auto block = firstAllocatedBlock; block != nullptr; block = block->next) {
2670 currentTailIndex += static_cast<index_t>(BLOCK_SIZE);
2671 idxEntry = get_block_index_entry_for_index(currentTailIndex);
2672 idxEntry->value.store(nullptr, std::memory_order_relaxed);
2673 rewind_block_index_tail();
2674 }
2675 this->parent->add_blocks_to_free_list(firstAllocatedBlock);
2676 this->tailBlock = startBlock;
2677
2678 return false;
2679 }
2680
2681#ifdef MCDBGQ_TRACKMEM
2682 newBlock->owner = this;
2683#endif

Callers

nothing calls this directly

Calls 5

rewind_block_index_tailFunction · 0.85
deref_noexceptFunction · 0.85
loadMethod · 0.45
storeMethod · 0.45

Tested by

no test coverage detected