MCPcopy Create free account
hub / github.com/cameron314/readerwriterqueue / inner_enqueue

Function inner_enqueue

readerwriterqueue.h:538–644  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

536#else
537 template<AllocationMode canAlloc, typename U>
538 bool inner_enqueue(U&& element) AE_NO_TSAN
539#endif
540 {
541#ifndef NDEBUG
542 ReentrantGuard guard(this->enqueuing);
543#endif
544
545 // High-level pseudocode (assuming we're allowed to alloc a new block):
546 // If room in tail block, add to tail
547 // Else check next block
548 // If next block is not the head block, enqueue on next block
549 // Else create a new block and enqueue there
550 // Advance tail to the block we just enqueued to
551
552 Block* tailBlock_ = tailBlock.load();
553 size_t blockFront = tailBlock_->localFront;
554 size_t blockTail = tailBlock_->tail.load();
555
556 size_t nextBlockTail = (blockTail + 1) & tailBlock_->sizeMask;
557 if (nextBlockTail != blockFront || nextBlockTail != (tailBlock_->localFront = tailBlock_->front.load())) {
558 fence(memory_order_acquire);
559 // This block has room for at least one more element
560 char* location = tailBlock_->data + blockTail * sizeof(T);
561#if MOODYCAMEL_HAS_EMPLACE
562 new (location) T(std::forward<Args>(args)...);
563#else
564 new (location) T(std::forward<U>(element));
565#endif
566
567 fence(memory_order_release);
568 tailBlock_->tail = nextBlockTail;
569 }
570 else {
571 fence(memory_order_acquire);
572 if (tailBlock_->next.load() != frontBlock) {
573 // Note that the reason we can't advance to the frontBlock and start adding new entries there
574 // is because if we did, then dequeue would stay in that block, eventually reading the new values,
575 // instead of advancing to the next full block (whose values were enqueued first and so should be
576 // consumed first).
577
578 fence(memory_order_acquire); // Ensure we get latest writes if we got the latest frontBlock
579
580 // tailBlock is full, but there's a free block ahead, use it
581 Block* tailBlockNext = tailBlock_->next.load();
582 size_t nextBlockFront = tailBlockNext->localFront = tailBlockNext->front.load();
583 nextBlockTail = tailBlockNext->tail.load();
584 fence(memory_order_acquire);
585
586 // This block must be empty since it's not the head block and we
587 // go through the blocks in a circle
588 assert(nextBlockFront == nextBlockTail);
589 tailBlockNext->localFront = nextBlockFront;
590
591 char* location = tailBlockNext->data + nextBlockTail * sizeof(T);
592#if MOODYCAMEL_HAS_EMPLACE
593 new (location) T(std::forward<Args>(args)...);
594#else
595 new (location) T(std::forward<U>(element));

Callers 3

try_enqueueMethod · 0.85
wait_enqueueMethod · 0.85
wait_enqueue_timedMethod · 0.85

Calls 2

make_blockFunction · 0.85
loadMethod · 0.80

Tested by

no test coverage detected