// File: /workspace/github_cpp_makefile_star2_O1/HQarroum[P]thread-pool/examples/working-with-tokens/./../../includes/concurrent_queue.hpp
// Function: bool moodycamel::ConcurrentQueue<std::function<void ()>, moodycamel::ConcurrentQueueDefaultTraits>::ExplicitProducer::enqueue_bulk<(moodycamel::ConcurrentQueue<std::function<void ()>, moodycamel::ConcurrentQueueDefaultTraits>::AllocationMode)0, std::function<void ()> const*>(std::function<void ()> const*, unsigned long)
bool MOODYCAMEL_NO_TSAN enqueue_bulk(It itemFirst, size_t count)
		{
			// First, we need to make sure we have enough room to enqueue all of the elements;
			// this means pre-allocating blocks and putting them in the block index (but only if
			// all the allocations succeeded).
			index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed);
			auto startBlock = this->tailBlock;
			auto originalBlockIndexFront = pr_blockIndexFront;
			auto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed;
			
			Block* firstAllocatedBlock = nullptr;
			
			// Figure out how many blocks we'll need to allocate, and do so
			size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1));
			index_t currentTailIndex = (startTailIndex - 1) & ~static_cast<index_t>(BLOCK_SIZE - 1);
			if (blockBaseDiff > 0) {
				// Allocate as many blocks as possible from ahead
				while (blockBaseDiff > 0 && this->tailBlock != nullptr && this->tailBlock->next != firstAllocatedBlock && this->tailBlock->next->ConcurrentQueue::Block::template is_empty<explicit_context>()) {
					blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);
					currentTailIndex += static_cast<index_t>(BLOCK_SIZE);
					
					this->tailBlock = this->tailBlock->next;
					firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock;
					
					auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];
					entry.base = currentTailIndex;
					entry.block = this->tailBlock;
					pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);
				}
				
				// Now allocate as many blocks as necessary from the block pool
				while (blockBaseDiff > 0) {
					blockBaseDiff -= static_cast<index_t>(BLOCK_SIZE);
					currentTailIndex += static_cast<index_t>(BLOCK_SIZE);
					
					auto head = this->headIndex.load(std::memory_order_relaxed);
					assert(!details::circular_less_than<index_t>(currentTailIndex, head));
					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));
					if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize || full) {
						MOODYCAMEL_CONSTEXPR_IF (allocMode == CannotAlloc) {
							// Failed to allocate, undo changes (but keep injected blocks)
							pr_blockIndexFront = originalBlockIndexFront;
							pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;
							this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;
							return false;
						}
						else if (full || !new_block_index(originalBlockIndexSlotsUsed)) {
							// Failed to allocate, undo changes (but keep injected blocks)
							pr_blockIndexFront = originalBlockIndexFront;
							pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;
							this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;
							return false;
						}
						
						// pr_blockIndexFront is updated inside new_block_index, so we need to
						// update our fallback value too (since we keep the new index even if we
						// later fail)
						originalBlockIndexFront = originalBlockIndexSlotsUsed;
					}
					
					// Insert a new block in the circular linked list
					auto newBlock = this->parent->ConcurrentQueue::template requisition_block<allocMode>();
					if (newBlock == nullptr) {
						pr_blockIndexFront = originalBlockIndexFront;
						pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;
						this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;
						return false;
					}
					
#ifdef MCDBGQ_TRACKMEM
					newBlock->owner = this;
#endif
					newBlock->ConcurrentQueue::Block::template set_all_empty<explicit_context>();
					if (this->tailBlock == nullptr) {
						newBlock->next = newBlock;
					}
					else {
						newBlock->next = this->tailBlock->next;
						this->tailBlock->next = newBlock;
					}
					this->tailBlock = newBlock;
					firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock;
					
					++pr_blockIndexSlotsUsed;
					
					auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront];
					entry.base = currentTailIndex;
					entry.block = this->tailBlock;
					pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1);
				}
				
				// Excellent, all allocations succeeded. Reset each block's emptiness before we fill them up, and
				// publish the new block index front
				auto block = firstAllocatedBlock;
				while (true) {
					block->ConcurrentQueue::Block::template reset_empty<explicit_context>();
					if (block == this->tailBlock) {
						break;
					}
					block = block->next;
				}
				
				MOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))) {
					blockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release);
				}
			}
			
			// Enqueue, one block at a time
			index_t newTailIndex = startTailIndex + static_cast<index_t>(count);
			currentTailIndex = startTailIndex;
			auto endBlock = this->tailBlock;
			this->tailBlock = startBlock;
			assert((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || count == 0);
			if ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) {
				this->tailBlock = firstAllocatedBlock;
			}
			while (true) {
				index_t stopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);
				if (details::circular_less_than<index_t>(newTailIndex, stopIndex)) {
					stopIndex = newTailIndex;
				}
				MOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))) {
					while (currentTailIndex != stopIndex) {
						new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++);
					}
				}
				else {
					MOODYCAMEL_TRY {
						while (currentTailIndex != stopIndex) {
							// Must use copy constructor even if move constructor is available
							// because we may have to revert if there's an exception.
							// Sorry about the horrible templated next line, but it was the only way
							// to disable moving *at compile time*, which is important because a type
							// may only define a (noexcept) move constructor, and so calls to the
							// cctor will not compile, even if they are in an if branch that will never
							// be executed
							new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast<T*>(nullptr)) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst));
							++currentTailIndex;
							++itemFirst;
						}
					}
					MOODYCAMEL_CATCH (...) {
						// Oh dear, an exception's been thrown -- destroy the elements that
						// were enqueued so far and revert the entire bulk operation (we'll keep
						// any allocated blocks in our linked list for later, though).
						auto constructedStopIndex = currentTailIndex;
						auto lastBlockEnqueued = this->tailBlock;
						
						pr_blockIndexFront = originalBlockIndexFront;
						pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed;
						this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock;
						
						if (!details::is_trivially_destructible<T>::value) {
							auto block = startBlock;
							if ((startTailIndex & static_cast<index_t>(BLOCK_SIZE - 1)) == 0) {
								block = firstAllocatedBlock;
							}
							currentTailIndex = startTailIndex;
							while (true) {
								stopIndex = (currentTailIndex & ~static_cast<index_t>(BLOCK_SIZE - 1)) + static_cast<index_t>(BLOCK_SIZE);
								if (details::circular_less_than<index_t>(constructedStopIndex, stopIndex)) {
									stopIndex = constructedStopIndex;
								}
								while (currentTailIndex != stopIndex) {
									(*block)[currentTailIndex++]->~T();
								}
								if (block == lastBlockEnqueued) {
									break;
								}
								block = block->next;
							}
						}
						MOODYCAMEL_RETHROW;
					}
				}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, %r12
movq %rdi, %r8
movq 0x20(%rdi), %r15
movq 0x40(%rdi), %rbp
movq 0x60(%rdi), %rax
movq %rax, 0x18(%rsp)
movq 0x70(%rdi), %rax
movq %rax, 0x10(%rsp)
movq %rdx, 0x20(%rsp)
leaq (%r15,%rdx), %r14
decq %r14
andq $-0x20, %r14
leaq -0x1(%r15), %r13
andq $-0x20, %r13
subq %r13, %r14
movq %rdi, 0x30(%rsp)
je 0x4548
movq $0x0, 0x8(%rsp)
movq 0x40(%r8), %rax
testq %rax, %rax
je 0x43b4
movq 0x400(%rax), %rax
cmpq 0x8(%rsp), %rax
je 0x43b4
movb 0x410(%rax), %cl
testb $0x1, %cl
je 0x434a
xorl %ecx, %ecx
cmpq $0x1f, %rcx
je 0x4352
movb 0x411(%rax,%rcx), %dl
incq %rcx
testb $0x1, %dl
jne 0x4329
decq %rcx
cmpq $0x1f, %rcx
setae %al
jmp 0x434c
xorl %eax, %eax
testb %al, %al
jne 0x4355
jmp 0x4355
setae %al
testb %al, %al
je 0x43b4
addq $0x20, %r13
movq 0x40(%r8), %rax
movq 0x400(%rax), %rax
movq %rax, 0x40(%r8)
movq 0x8(%rsp), %rcx
testq %rcx, %rcx
cmoveq %rax, %rcx
movq %rcx, 0x8(%rsp)
movq 0x58(%r8), %rcx
movq 0x10(%rcx), %rcx
movq 0x70(%r8), %rdx
movq %rdx, %rsi
shlq $0x4, %rsi
movq %r13, (%rcx,%rsi)
movq %rax, 0x8(%rcx,%rsi)
incq %rdx
movq 0x68(%r8), %rax
decq %rax
andq %rdx, %rax
movq %rax, 0x70(%r8)
addq $-0x20, %r14
jne 0x42fd
movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000
incq %rax
movq %rax, 0x28(%rsp)
testq %r14, %r14
je 0x4662
movq %r13, %rcx
addq $0x20, %r13
movq 0x28(%r8), %rax
movq %r13, %rdx
subq %rax, %rdx
movabsq $-0x8000000000000000, %rsi # imm = 0x8000000000000000
cmpq %rsi, %rdx
ja 0x4694
subq %rcx, %rax
addq $-0x40, %rax
cmpq $0x0, 0x80(%r8)
je 0x441c
cmpq 0x28(%rsp), %rax
jb 0x441c
movq 0x68(%r8), %rcx
cmpq %rcx, 0x60(%r8)
je 0x441c
movq 0x10(%rsp), %rbx
jmp 0x443c
cmpq 0x28(%rsp), %rax
jb 0x448c
movq %r8, %rdi
movq 0x18(%rsp), %rbx
movq %rbx, %rsi
callq 0x3ade
movq 0x30(%rsp), %r8
testb %al, %al
je 0x448c
movq %rbx, 0x10(%rsp)
movq 0x50(%r8), %rdi
movq %r8, %rbx
callq 0x47b2
testq %rax, %rax
je 0x44b5
movl $0x410, %ecx            # imm = 0x410
movb $0x1, (%rax,%rcx)
incq %rcx
cmpq $0x430, %rcx            # imm = 0x430
jne 0x4457
movq 0x30(%rsp), %r8
movq 0x40(%r8), %rcx
testq %rcx, %rcx
je 0x44e3
movq 0x400(%rcx), %rdx
addq $0x400, %rcx            # imm = 0x400
movq %rdx, 0x400(%rax)
jmp 0x44ea
testq %rbp, %rbp
movq 0x10(%rsp), %rax
movq %rax, 0x70(%r8)
movq 0x18(%rsp), %rax
movq %rax, 0x60(%r8)
movq %rbp, %rax
cmoveq 0x8(%rsp), %rax
movq %rax, 0x40(%r8)
xorl %eax, %eax
jmp 0x4535
testq %rbp, %rbp
movq 0x10(%rsp), %rdx
movq %rdx, 0x70(%rbx)
movq %rbp, %rax
cmoveq 0x8(%rsp), %rax
movq 0x18(%rsp), %rcx
movq %rcx, 0x60(%rbx)
movq %rax, 0x40(%rbx)
xorl %eax, %eax
movq %rdx, 0x10(%rsp)
movq %rbx, %r8
jmp 0x4535
leaq 0x400(%rax), %rcx
movq %rax, (%rcx)
movq 0x8(%rsp), %rcx
testq %rcx, %rcx
cmoveq %rax, %rcx
movq %rcx, 0x8(%rsp)
movq %rax, 0x40(%r8)
incq 0x60(%r8)
movq 0x58(%r8), %rcx
movq 0x10(%rcx), %rcx
movq 0x70(%r8), %rdx
movq %rdx, %rsi
shlq $0x4, %rsi
movq %r13, (%rcx,%rsi)
movq %rax, 0x8(%rcx,%rsi)
incq %rdx
movq 0x68(%r8), %rax
decq %rax
andq %rdx, %rax
movq %rax, 0x70(%r8)
movb $0x1, %al
addq $-0x20, %r14
testb %al, %al
jne 0x43c6
xorl %eax, %eax
jmp 0x4653
movq $0x0, 0x8(%rsp)
movq 0x20(%rsp), %rsi
movq 0x40(%r8), %rdx
movq %rbp, 0x40(%r8)
testq %rsi, %rsi
je 0x4577
movl %r15d, %eax
andl $0x1f, %eax
jne 0x4577
cmpq $0x0, 0x8(%rsp)
je 0x46d2
testb $0x1f, %r15b
jne 0x458e
cmpq $0x0, 0x8(%rsp)
je 0x458e
movq 0x8(%rsp), %rax
movq %rax, 0x40(%r8)
addq %r15, %rsi
movq %r15, %r14
movq %rsi, 0x20(%rsp)
movq %rdx, 0x28(%rsp)
movq %r14, %rbx
andq $-0x20, %rbx
addq $0x20, %rbx
movq %rsi, %rax
subq %rbx, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
cmpq %rcx, %rax
cmovaq %rsi, %rbx
cmpq %rbx, %r14
je 0x4604
movl $0x20, %r13d
subq %r14, %r13
movl %r14d, %edi
andl $0x1f, %edi
shll $0x5, %edi
addq 0x40(%r8), %rdi
movq %r12, %rsi
callq 0x491e
incq %r14
addq $0x20, %r12
decq %r13
cmpq %r14, %rbx
movq 0x30(%rsp), %r8
jne 0x45ce
movq %rbx, %r14
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rdx
movq 0x40(%r8), %rax
cmpq %rdx, %rax
je 0x461a
movq 0x400(%rax), %rcx
movq %rcx, 0x40(%r8)
jmp 0x4623
cmpq %rsi, %r14
jne 0x46b3
cmpq %rdx, %rax
jne 0x459e
cmpq $0x0, 0x8(%rsp)
je 0x464d
movq 0x58(%r8), %rax
movq 0x68(%r8), %rcx
movq 0x70(%r8), %rdx
decq %rdx
decq %rcx
andq %rdx, %rcx
movq %rcx, 0x8(%rax)
movq %rsi, 0x20(%r8)
movb $0x1, %al
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rsp), %rax
movq 0x20(%rsp), %rsi
movl $0x410, %ecx            # imm = 0x410
movb $0x0, (%rax,%rcx)
incq %rcx
cmpq $0x430, %rcx            # imm = 0x430
jne 0x4671
cmpq 0x40(%r8), %rax
je 0x4556
movq 0x400(%rax), %rax
jmp 0x466c
leaq 0x137b(%rip), %rdi      # 0x5a16
leaq 0x9c5(%rip), %rsi       # 0x5067
leaq 0x13ab(%rip), %rcx      # 0x5a54
movl $0x81c, %edx            # imm = 0x81C
callq 0x2100
leaq 0x152c(%rip), %rdi      # 0x5be6
leaq 0x9a6(%rip), %rsi       # 0x5067
leaq 0x138c(%rip), %rcx      # 0x5a54
movl $0x8a9, %edx            # imm = 0x8A9
callq 0x2100
leaq 0x14a0(%rip), %rdi      # 0x5b79
leaq 0x987(%rip), %rsi       # 0x5067
leaq 0x136d(%rip), %rcx      # 0x5a54
movl $0x868, %edx            # imm = 0x868
callq 0x2100
movq %rax, %rdi
callq 0x20a0
testq %rbp, %rbp
movq %rbp, %rax
movq 0x8(%rsp), %rsi
cmoveq %rsi, %rax
testb $0x1f, %r15b
movq 0x30(%rsp), %rcx
movq 0x40(%rcx), %r12
movq 0x10(%rsp), %rdx
movq %rdx, 0x70(%rcx)
movq 0x18(%rsp), %rdx
movq %rdx, 0x60(%rcx)
movq %rax, 0x40(%rcx)
cmoveq %rsi, %rbp
negq %r13
movq %r15, %rbx
andq $-0x20, %rbx
movq %r13, %rax
subq %rbx, %rax
addq $0x20, %rbx
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
cmpq %rcx, %rax
cmovaq %r14, %rbx
cmpq %rbx, %r15
je 0x4784
movl %r15d, %edi
andl $0x1f, %edi
shll $0x5, %edi
movq 0x10(%rbp,%rdi), %rax
testq %rax, %rax
je 0x4779
addq %rbp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
incq %r15
cmpq %r15, %rbx
jne 0x4759
movq %rbx, %r15
cmpq %r12, %rbp
je 0x4792
movq 0x400(%rbp), %rbp
jmp 0x4732
callq 0x21e0
movq %rax, %rbx
callq 0x2210
movq %rbx, %rdi
callq 0x2250
jmp 0x47a9
movq %rax, %rdi
callq 0x2771
nop