// File: olegstrelnikov[P]thread-pool/test/main.cpp
// Function: main
int main() {
	std::size_t fails = 0;
	for (std::size_t j = 0; j < 10000; ++j) {
		{
			ThreadPool threadPool(4);
			threadPool.addTask(f<1>);
			threadPool.addTask(f<2>);
			threadPool.addTask(f<3>);
			threadPool.addTask(f<4>);
			threadPool.addTask(f<5>);
			threadPool.addTask(f<6>);
			threadPool.addTask(f<7>);
			threadPool.addTask(f<8>);
			threadPool.addTask(f<9>);
			threadPool.addTask(f<10>);
			threadPool.addTask(f<11>);
			threadPool.addTask(f<12>);
			threadPool.addTask(f<13>);
			threadPool.addTask(f<14>);
			threadPool.addTask(f<15>);
			threadPool.addTask(f<16>);
		}
		for (std::size_t i = 0; i < FUNCTIONS; ++i) {
			if (calls[i] != 1 + j) {
				++fails;
			}
		}
	} //for j
	for (std::size_t i = 0; i < FUNCTIONS; ++i) {
		std::cout << calls[i] << " ";
	}
	std::cout << "\n";
	std::map<thread_id_t, std::size_t> byThread;
	for (auto id: thread_ids) {
		++byThread[id];
	}
	if (byThread.size() > 4) {
		++fails;
	}
	for (auto pair: byThread) {
		std::cout << pair.first << ": " << pair.second << "\n";
	}
	std::cout << "fails: " << fails << "\n";
	return 0;
}

// Assembly:
subq $0x188, %rsp            # imm = 0x188
movl $0x0, 0x184(%rsp)
movq $0x0, 0x178(%rsp)
movq $0x0, 0x170(%rsp)
cmpq $0x2710, 0x170(%rsp) # imm = 0x2710
jae 0x264f
leaq 0xe0(%rsp), %rdi
movq %rdi, 0x30(%rsp)
movl $0x4, %esi
movl $0x1, %edx
callq 0x29a0
movq 0x30(%rsp), %rdi
leaq 0x6ec(%rip), %rsi       # 0x2b30
callq 0x2ab0
jmp 0x244b
leaq 0x73e(%rip), %rsi       # 0x2b90
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x2461
leaq 0x788(%rip), %rsi       # 0x2bf0
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x2477
leaq 0x7d2(%rip), %rsi       # 0x2c50
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x248d
leaq 0x81c(%rip), %rsi       # 0x2cb0
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x24a3
leaq 0x866(%rip), %rsi       # 0x2d10
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x24b9
leaq 0x8b0(%rip), %rsi       # 0x2d70
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x24cf
leaq 0x8fa(%rip), %rsi       # 0x2dd0
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x24e5
leaq 0x944(%rip), %rsi       # 0x2e30
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x24fb
leaq 0x98e(%rip), %rsi       # 0x2e90
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x2511
leaq 0x9d8(%rip), %rsi       # 0x2ef0
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x2527
leaq 0xa22(%rip), %rsi       # 0x2f50
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x253d
leaq 0xa6c(%rip), %rsi       # 0x2fb0
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x2553
leaq 0xab6(%rip), %rsi       # 0x3010
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x2569
leaq 0xb00(%rip), %rsi       # 0x3070
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x257f
leaq 0xb4a(%rip), %rsi       # 0x30d0
leaq 0xe0(%rsp), %rdi
callq 0x2ab0
jmp 0x2595
leaq 0xe0(%rsp), %rdi
callq 0x3130
movq $0x0, 0xc8(%rsp)
cmpq $0x10, 0xc8(%rsp)
jae 0x2634
movq 0xc8(%rsp), %rcx
leaq 0x8b98(%rip), %rax      # 0xb160
movq (%rax,%rcx,8), %rax
movq 0x170(%rsp), %rcx
addq $0x1, %rcx
cmpq %rcx, %rax
je 0x2619
movq 0x178(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x178(%rsp)
jmp 0x2619
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd8(%rsp)
movl %eax, 0xd4(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x3130
jmp 0x28d8
jmp 0x261b
movq 0xc8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc8(%rsp)
jmp 0x25ae
jmp 0x2636
movq 0x170(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x170(%rsp)
jmp 0x240a
movq $0x0, 0xc0(%rsp)
cmpq $0x10, 0xc0(%rsp)
jae 0x26aa
movq 0xc0(%rsp), %rcx
leaq 0x8aeb(%rip), %rax      # 0xb160
movq (%rax,%rcx,8), %rsi
movq 0x8958(%rip), %rdi      # 0xafd8
callq 0x2060
movq %rax, %rdi
leaq 0x497d(%rip), %rsi      # 0x700c
callq 0x2180
movq 0xc0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc0(%rsp)
jmp 0x265b
movq 0x8927(%rip), %rdi      # 0xafd8
leaq 0x494c(%rip), %rsi      # 0x7004
callq 0x2180
leaq 0x90(%rsp), %rdi
callq 0x3210
leaq 0x8b0f(%rip), %rax      # 0xb1e0
movq %rax, 0x88(%rsp)
leaq 0x8b00(%rip), %rax      # 0xb1e0
movq %rax, 0x80(%rsp)
leaq 0x8af1(%rip), %rax      # 0xb1e0
addq $0x80, %rax
movq %rax, 0x78(%rsp)
movq 0x80(%rsp), %rax
cmpq 0x78(%rsp), %rax
je 0x277d
movq 0x80(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x70(%rsp)
leaq 0x90(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x3220
movq %rax, 0x28(%rsp)
jmp 0x2732
movq 0x28(%rsp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movq 0x80(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x80(%rsp)
jmp 0x26fa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd8(%rsp)
movl %eax, 0xd4(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x3460
jmp 0x28d8
leaq 0x90(%rsp), %rdi
callq 0x3310
cmpq $0x4, %rax
jbe 0x27a4
movq 0x178(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x178(%rsp)
leaq 0x90(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rdi
callq 0x3320
movq %rax, 0x60(%rsp)
movq 0x68(%rsp), %rdi
callq 0x3350
movq %rax, 0x58(%rsp)
leaq 0x60(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x3380
testb $0x1, %al
jne 0x27e7
jmp 0x286d
leaq 0x60(%rsp), %rdi
callq 0x33a0
movups (%rax), %xmm0
movaps %xmm0, 0x40(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rsi
movq 0x87c9(%rip), %rdi      # 0xafd8
callq 0x33c0
movq %rax, 0x20(%rsp)
jmp 0x281b
movq 0x20(%rsp), %rdi
leaq 0x47e4(%rip), %rsi      # 0x700b
callq 0x2180
movq %rax, 0x18(%rsp)
jmp 0x2833
movq 0x18(%rsp), %rdi
movq 0x48(%rsp), %rsi
callq 0x2060
movq %rax, 0x10(%rsp)
jmp 0x2849
movq 0x10(%rsp), %rdi
leaq 0x47af(%rip), %rsi      # 0x7004
callq 0x2180
jmp 0x285c
jmp 0x285e
leaq 0x60(%rsp), %rdi
callq 0x3430
jmp 0x27cf
movq 0x8764(%rip), %rdi      # 0xafd8
leaq 0x478b(%rip), %rsi      # 0x7006
callq 0x2180
movq %rax, 0x8(%rsp)
jmp 0x2887
movq 0x8(%rsp), %rdi
movq 0x178(%rsp), %rsi
callq 0x2060
movq %rax, (%rsp)
jmp 0x289f
movq (%rsp), %rdi
leaq 0x475a(%rip), %rsi      # 0x7004
callq 0x2180
jmp 0x28b1
movl $0x0, 0x184(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x3460
movl 0x184(%rsp), %eax
addq $0x188, %rsp            # imm = 0x188
retq
movq 0xd8(%rsp), %rdi
callq 0x2230
nopw %cs:(%rax,%rax)