// File: dragazo[P]cpp-gc/GarbageCollection.cpp
// Function: GC::disjoint_module_container::BACKGROUND_COLLECTOR_ONLY___collect(bool)
void GC::disjoint_module_container::BACKGROUND_COLLECTOR_ONLY___collect(bool collect)
{
	{
		std::lock_guard<std::mutex> internal_lock(internal_mutex);

		// we should not already be collecting (this is background collector only)
		assert(!collecting);

		// enter collecting mode
		collecting = true;

		// the add cache should be empty (just came out of a non-collecting phase)
		assert(disjunction_add_cache.empty());
	}

	// if performing a real collection
	if (collect)
	{
		// for each stored disjunction:
		// (the EXPLICIT std::list::iterator ensures it is indeed a LIST).
		// (otherwise we need to constantly update the end iterator after each erasure).
		for (auto i = disjunctions.begin(), end = disjunctions.end(); i != end; )
		{
			// lock and use this disjunction as the local disjunction - then get the raw handle
			disjoint_module *const raw_handle = (disjoint_module::local_handle() = *i).get();

			// if it's still allive, perform a collection on it
			if (raw_handle)
			{
				// perform the collection
				raw_handle->collect();
				++i;

				// afterwards unlink the handle - we don't want to keep them alive longer than they need to be
				disjoint_module::local_handle() = nullptr;
			}
			// otherwise it's invalid (dangling) - erase it
			else i = disjunctions.erase(i);
		}
	}
	// otherwise just performing a cull
	else
	{
		// for each stored disjunction:
		// (the EXPLICIT std::list::iterator ensures it is indeed a LIST).
		// (otherwise we need to constantly update the end iterator after each erasure).
		for (auto i = disjunctions.begin(), end = disjunctions.end(); i != end; )
		{
			// if this is a dangling pointer, erase it
			if (i->expired()) i = disjunctions.erase(i);
			else ++i;
		}
	}

	{
		std::lock_guard<std::mutex> internal_lock(internal_mutex);

		// exit collecting mode
		collecting = false;

		// apply all the cached disjunction insertions
		disjunctions.splice(disjunctions.begin(), disjunction_add_cache);
		disjunction_add_cache.clear(); // just to be sure
	}
}

// Assembly:
subq $0xa8, %rsp
movb %sil, %al
movq %rdi, 0xa0(%rsp)
andb $0x1, %al
movb %al, 0x9f(%rsp)
movq 0xa0(%rsp), %rsi
movq %rsi, 0x28(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x95b0
movq 0x28(%rsp), %rax
movb 0x28(%rax), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x8025
jmp 0x8027
jmp 0x8046
leaq 0x5c485(%rip), %rdi     # 0x644b3
leaq 0x5c128(%rip), %rsi     # 0x6415d
movl $0x350, %edx            # imm = 0x350
leaq 0x5c47e(%rip), %rcx     # 0x644bf
callq 0x51e0
movq 0x28(%rsp), %rdi
movb $0x1, 0x28(%rdi)
addq $0x48, %rdi
callq 0xa000
testb $0x1, %al
jne 0x805e
jmp 0x8060
jmp 0x807f
leaq 0x5c4a6(%rip), %rdi     # 0x6450d
leaq 0x5c0ef(%rip), %rsi     # 0x6415d
movl $0x356, %edx            # imm = 0x356
leaq 0x5c445(%rip), %rcx     # 0x644bf
callq 0x51e0
leaq 0x90(%rsp), %rdi
callq 0x96d0
testb $0x1, 0x9f(%rsp)
je 0x8192
movq 0x28(%rsp), %rdi
addq $0x30, %rdi
callq 0xa020
movq 0x28(%rsp), %rdi
movq %rax, 0x88(%rsp)
addq $0x30, %rdi
callq 0xa050
movq %rax, 0x80(%rsp)
leaq 0x88(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0xa080
testb $0x1, %al
jne 0x80e4
jmp 0x818d
leaq 0x88(%rsp), %rdi
callq 0xa0a0
movq %rax, 0x20(%rsp)
callq 0x7c70
movq 0x20(%rsp), %rsi
movq %rax, %rdi
callq 0x82b0
movq %rax, %rdi
callq 0x9da0
movq %rax, 0x78(%rsp)
cmpq $0x0, 0x78(%rsp)
je 0x8147
movq 0x78(%rsp), %rdi
callq 0x5e50
leaq 0x88(%rsp), %rdi
callq 0xa0c0
callq 0x7c70
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x82e0
jmp 0x8188
movq 0x28(%rsp), %rax
addq $0x30, %rax
movq %rax, 0x18(%rsp)
leaq 0x68(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0xa130
movq 0x18(%rsp), %rdi
movq 0x68(%rsp), %rsi
callq 0xa0e0
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rax
movq %rax, 0x88(%rsp)
jmp 0x80c6
jmp 0x8230
movq 0x28(%rsp), %rdi
addq $0x30, %rdi
callq 0xa020
movq 0x28(%rsp), %rdi
movq %rax, 0x60(%rsp)
addq $0x30, %rdi
callq 0xa050
movq %rax, 0x58(%rsp)
leaq 0x60(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0xa080
testb $0x1, %al
jne 0x81cd
jmp 0x822e
leaq 0x60(%rsp), %rdi
callq 0xa150
movq %rax, %rdi
callq 0x8310
testb $0x1, %al
jne 0x81e5
jmp 0x8222
movq 0x28(%rsp), %rax
addq $0x30, %rax
movq %rax, 0x10(%rsp)
leaq 0x48(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0xa130
movq 0x10(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0xa0e0
movq %rax, 0x50(%rsp)
movq 0x50(%rsp), %rax
movq %rax, 0x60(%rsp)
jmp 0x822c
leaq 0x60(%rsp), %rdi
callq 0xa0c0
jmp 0x81b8
jmp 0x8230
movq 0x28(%rsp), %rsi
leaq 0x40(%rsp), %rdi
callq 0x95b0
movq 0x28(%rsp), %rdi
movb $0x0, 0x28(%rdi)
movq %rdi, %rax
addq $0x30, %rax
movq %rax, 0x8(%rsp)
addq $0x30, %rdi
callq 0xa020
movq %rax, 0x30(%rsp)
leaq 0x38(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xa130
movq 0x8(%rsp), %rdi
movq 0x28(%rsp), %rdx
addq $0x48, %rdx
movq 0x38(%rsp), %rsi
callq 0xa170
movq 0x28(%rsp), %rdi
addq $0x48, %rdi
callq 0xa1b0
leaq 0x40(%rsp), %rdi
callq 0x96d0
addq $0xa8, %rsp
retq
nopl (%rax)