MCPcopy Create free account
hub / github.com/dmlc/dmlc-core / enqueue_bulk

Function enqueue_bulk

include/dmlc/concurrentqueue.h:2598–2762  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2596
2597 template<AllocationMode allocMode, typename It>
2598 bool enqueue_bulk(It itemFirst, size_t count) {
2599 // First, we need to make sure we have enough room to enqueue all of the elements;
2600 // this means pre-allocating blocks and putting them in the block index (but only if
2601 // all the allocations succeeded).
2602
2603 // Note that the tailBlock we start off with may not be owned by us any more;
2604 // this happens if it was filled up exactly to the top (setting tailIndex to
2605 // the first index of the next block which is not yet allocated), then dequeued
2606 // completely (putting it on the free list) before we enqueue again.
2607
2608 index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed);
2609 auto startBlock = this->tailBlock;
2610 Block *firstAllocatedBlock = nullptr;
2611 auto endBlock = this->tailBlock;
2612
2613 // Figure out how many blocks we'll need to allocate, and do so
2614 size_t blockBaseDiff =
2615 ((startTailIndex + count - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1)) -
2616 ((startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1));
2617 index_t currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);
2618 if (blockBaseDiff > 0) {
2619#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX
2620 debug::DebugLock lock(mutex);
2621#endif
2622 do {
2623 blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);
2624 currentTailIndex += static_cast<index_t>(BLOCK_SIZE);
2625
2626 // Find out where we'll be inserting this block in the block index
2627 BlockIndexEntry *idxEntry = nullptr; // initialization here unnecessary but compiler can't always tell
2628 Block *newBlock;
2629 bool indexInserted = false;
2630 auto head = this->headIndex.load(std::memory_order_relaxed);
2631 assert(!details::circular_less_than<index_t>(currentTailIndex, head));
2632 bool full = !details::circular_less_than<index_t>(head, currentTailIndex + BLOCK_SIZE) ||
2633 (MAX_SUBQUEUE_SIZE != details::const_numeric_max<size_t>::value &&
2634 (MAX_SUBQUEUE_SIZE == 0 ||
2635 MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head));
2636 if (full ||
2637 !(indexInserted = insert_block_index_entry<allocMode>(idxEntry, currentTailIndex)) ||
2638 (newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>()) ==
2639 nullptr) {
2640 // Index allocation or block allocation failed; revert any other allocations
2641 // and index insertions done so far for this operation
2642 if (indexInserted) {
2643 rewind_block_index_tail();
2644 idxEntry->value.store(nullptr, std::memory_order_relaxed);
2645 }
2646 currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);
2647 for (auto block = firstAllocatedBlock; block != nullptr; block = block->next) {
2648 currentTailIndex += static_cast<index_t>(BLOCK_SIZE);
2649 idxEntry = get_block_index_entry_for_index(currentTailIndex);
2650 idxEntry->value.store(nullptr, std::memory_order_relaxed);
2651 rewind_block_index_tail();
2652 }
2653 this->parent->add_blocks_to_free_list(firstAllocatedBlock);
2654 this->tailBlock = startBlock;
2655

Callers

nothing calls this directly

Calls 3

rewind_block_index_tailFunction · 0.85
deref_noexceptFunction · 0.85

Tested by

no test coverage detected