// File: /workspace/github_cpp_makefile_star2_O2/HQarroum[P]thread-pool/examples/one-producer-many-consumers/./../../includes/concurrent_queue.hpp
// Function: moodycamel::ConcurrentQueue<std::function<void ()>, moodycamel::ConcurrentQueueDefaultTraits>::ImplicitProducer::~ImplicitProducer()
~ImplicitProducer()
		{
			// Note that since we're in the destructor we can assume that all enqueue/dequeue operations
			// completed already; this means that all undequeued elements are placed contiguously across
			// contiguous blocks, and that only the first and last remaining blocks can be only partially
			// empty (all other remaining blocks must be completely full).
			
#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED
			// Unregister ourselves for thread termination notification
			if (!this->inactive.load(std::memory_order_relaxed)) {
				details::ThreadExitNotifier::unsubscribe(&threadExitListener);
			}
#endif
			
			// Destroy all remaining elements!
			auto tail = this->tailIndex.load(std::memory_order_relaxed);
			auto index = this->headIndex.load(std::memory_order_relaxed);
			Block* block = nullptr;
			assert(index == tail || details::circular_less_than(index, tail));
			bool forceFreeLastBlock = index != tail;		// If we enter the loop, then the last (tail) block will not be freed
			while (index != tail) {
				if ((index & static_cast<index_t>(BLOCK_SIZE - 1)) == 0 || block == nullptr) {
					if (block != nullptr) {
						// Free the old block
						this->parent->add_block_to_free_list(block);
					}
					
					block = get_block_index_entry_for_index(index)->value.load(std::memory_order_relaxed);
				}
				
				((*block)[index])->~T();
				++index;
			}
			// Even if the queue is empty, there's still one block that's not on the free list
			// (unless the head index reached the end of it, in which case the tail will be poised
			// to create a new block).
			if (this->tailBlock != nullptr && (forceFreeLastBlock || (tail & static_cast<index_t>(BLOCK_SIZE - 1)) != 0)) {
				this->parent->add_block_to_free_list(this->tailBlock);
			}
			
			// Destroy block index
			auto localBlockIndex = blockIndex.load(std::memory_order_relaxed);
			if (localBlockIndex != nullptr) {
				for (size_t i = 0; i != localBlockIndex->capacity; ++i) {
					localBlockIndex->index[i]->~BlockIndexEntry();
				}
				do {
					auto prev = localBlockIndex->prev;
					localBlockIndex->~BlockIndexHeader();
					(Traits::free)(localBlockIndex);
					localBlockIndex = prev;
				} while (localBlockIndex != nullptr);
			}
		}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
leaq 0x68f4(%rip), %rax      # 0xcd28
movq %rax, (%rdi)
movq 0x20(%rdi), %r13
movq 0x28(%rdi), %rbp
movq %rbp, %rax
subq %r13, %rax
setne %cl
movabsq $-0x7fffffffffffffff, %rdx # imm = 0x8000000000000001
cmpq %rdx, %rax
setb %al
testb %al, %cl
jne 0x6505
movq %rdi, %rbx
xorl %r15d, %r15d
movq %rbp, %r14
cmpq %r14, %r13
je 0x64ba
movq %r14, %r12
andq $0x1f, %r12
setne %al
testq %r15, %r15
setne %cl
testb %al, %cl
jne 0x64a6
testq %r15, %r15
je 0x6497
movq 0x50(%rbx), %rdi
addq $0x28, %rdi
movq %r15, %rsi
callq 0x4a92
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6544
movq 0x8(%rax), %r15
shll $0x5, %r12d
addq %r15, %r12
movq %r12, %rdi
callq 0x5276
incq %r14
jmp 0x6469
movq 0x40(%rbx), %rsi
testq %rsi, %rsi
je 0x64dc
xorq %r13, %rbp
andl $0x1f, %r13d
orq %rbp, %r13
je 0x64dc
movq 0x50(%rbx), %rdi
addq $0x28, %rdi
callq 0x4a92
movq 0x60(%rbx), %rdi
testq %rdi, %rdi
je 0x64f6
movq 0x20(%rdi), %rbx
callq 0x3290
movq %rbx, %rdi
testq %rbx, %rbx
jne 0x64e5
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x15e1(%rip), %rdi      # 0x7aed
leaq 0xb2b(%rip), %rsi       # 0x703e
leaq 0x160d(%rip), %rcx      # 0x7b27
movl $0x982, %edx            # imm = 0x982
callq 0x3170
jmp 0x6526
movq %rax, %rdi
callq 0x3914