// File: f18m[P]boost-intrusive-pool/tests/performance_tests.cpp
// Function: void main_benchmark_loop<memorypool::boost_intrusive_pool<LargeObject>>(memorypool::boost_intrusive_pool<LargeObject>&, BenchPattern_t, unsigned long, unsigned long&, unsigned long&)
static void main_benchmark_loop(
    PoolUnderTest& pool, BenchPattern_t pattern, size_t num_elements, size_t& num_freed, size_t& max_active)
{
    num_freed = 0, max_active = 0;

    switch (pattern) {
    case BENCH_PATTERN_CONTINUOUS_ALLOCATION: {
        std::vector<HLargeObject> helper_container;
        helper_container.reserve(num_elements); // this results in a single malloc that will not alter the benchmark!
        for (unsigned int i = 0; i < num_elements; i++) {
            HLargeObject myLargeObject = pool.allocate_through_init();
            assert(myLargeObject);

            // simulate a very light processing of the allocated item:
            myLargeObject->write(10, myLargeObject->read(10) + 2);
            myLargeObject->write(20, myLargeObject->read(20) + 2);
            helper_container.push_back(myLargeObject); // hold a reference otherwise the item will get deallocated!

            max_active = std::max(max_active, helper_container.size());
        }

        helper_container.clear();
    } break;

    case BENCH_PATTERN_MIXED_ALLOC_FREE: {
        std::unordered_map<int, HLargeObject> helper_container;
        helper_container.reserve(num_elements / 10);

        for (unsigned int i = 0; i < num_elements; i++) {
            HLargeObject myLargeObject = pool.allocate_through_init();
            assert(myLargeObject);

            // simulate a very light processing of the allocated item:
            myLargeObject->write(10, myLargeObject->read(10) + 2);
            myLargeObject->write(20, myLargeObject->read(20) + 2);

            if ((i % 33) == 0) {
                // we suddenly realize that we don't really need the just-allocated item... release it immediately
                // (it's enough to simply _not_ store it)
            } else {
                helper_container[i] = myLargeObject;

                // returns to the factory a few items in pseudo-random order
                if ((i % 7) == 0 || (i % 31) == 0 || (i % 40) == 0 || (i % 53) == 0) {
                    size_t value_to_release = i - 1;

                    auto it = helper_container.find(value_to_release);
                    if (it != helper_container.end()) {
                        // erasing the smart pointer from the std::map will trigger its return to the memory pool:
                        helper_container.erase(value_to_release);
                        num_freed++;
                    }
                }

                max_active = std::max(max_active, helper_container.size());
            }
        }
    } break;
    }
}

// Assembly:
subq $0x188, %rsp            # imm = 0x188
movq %rdi, 0x180(%rsp)
movl %esi, 0x17c(%rsp)
movq %rdx, 0x170(%rsp)
movq %rcx, 0x168(%rsp)
movq %r8, 0x160(%rsp)
movq 0x168(%rsp), %rax
movq $0x0, (%rax)
movq 0x160(%rsp), %rax
movq $0x0, (%rax)
movl 0x17c(%rsp), %eax
movl %eax, 0xa4(%rsp)
testl %eax, %eax
je 0x3255
jmp 0x3240
movl 0xa4(%rsp), %eax
subl $0x1, %eax
je 0x3497
jmp 0x380d
leaq 0x148(%rsp), %rdi
movq %rdi, 0x98(%rsp)
callq 0x5d90
movq 0x98(%rsp), %rdi
movq 0x170(%rsp), %rsi
callq 0x5da0
jmp 0x3281
movl $0x0, 0x138(%rsp)
movl 0x138(%rsp), %eax
cmpq 0x170(%rsp), %rax
jae 0x3466
movq 0x180(%rsp), %rsi
leaq 0x130(%rsp), %rdi
callq 0x5eb0
jmp 0x32b8
leaq 0x130(%rsp), %rdi
callq 0x5f80
testb $0x1, %al
jne 0x32cb
jmp 0x32cd
jmp 0x3305
leaq 0x7387(%rip), %rdi      # 0xa65b
leaq 0x738e(%rip), %rsi      # 0xa669
movl $0x72, %edx
leaq 0x739e(%rip), %rcx      # 0xa685
callq 0x2120
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0x3485
leaq 0x130(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x5fa0
movq 0x80(%rsp), %rdi
movq %rax, 0x88(%rsp)
callq 0x5fa0
movq %rax, %rdi
movl $0xa, %esi
callq 0x6020
movb %al, 0x97(%rsp)
jmp 0x3345
movq 0x88(%rsp), %rdi
movb 0x97(%rsp), %al
movzbl %al, %eax
addl $0x2, %eax
movsbl %al, %edx
movl $0xa, %esi
callq 0x5ff0
jmp 0x3369
leaq 0x130(%rsp), %rdi
movq %rdi, 0x68(%rsp)
callq 0x5fa0
movq 0x68(%rsp), %rdi
movq %rax, 0x70(%rsp)
callq 0x5fa0
movq %rax, %rdi
movl $0x14, %esi
callq 0x6020
movb %al, 0x7f(%rsp)
jmp 0x339d
movq 0x70(%rsp), %rdi
movb 0x7f(%rsp), %al
movzbl %al, %eax
addl $0x2, %eax
movsbl %al, %edx
movl $0x14, %esi
callq 0x5ff0
jmp 0x33bb
leaq 0x148(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x6040
jmp 0x33d2
movq 0x160(%rsp), %rax
movq %rax, 0x58(%rsp)
leaq 0x148(%rsp), %rdi
callq 0x60f0
movq 0x58(%rsp), %rdi
movq %rax, 0x128(%rsp)
leaq 0x128(%rsp), %rsi
callq 0x60b0
movq %rax, 0x60(%rsp)
jmp 0x340d
movq 0x60(%rsp), %rax
movq (%rax), %rcx
movq 0x160(%rsp), %rax
movq %rcx, (%rax)
leaq 0x130(%rsp), %rdi
callq 0x6110
movl 0x138(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x138(%rsp)
jmp 0x328c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x6110
jmp 0x3485
leaq 0x148(%rsp), %rdi
callq 0x6150
leaq 0x148(%rsp), %rdi
callq 0x6170
jmp 0x380d
leaq 0x148(%rsp), %rdi
callq 0x6170
jmp 0x3815
leaq 0xf0(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x61d0
movq 0x50(%rsp), %rdi
movq 0x170(%rsp), %rax
movabsq $-0x3333333333333333, %rcx # imm = 0xCCCCCCCCCCCCCCCD
mulq %rcx
movq %rdx, %rsi
shrq $0x3, %rsi
callq 0x61e0
jmp 0x34d1
movl $0x0, 0xec(%rsp)
movl 0xec(%rsp), %eax
cmpq 0x170(%rsp), %rax
jae 0x37ef
movq 0x180(%rsp), %rsi
leaq 0xe0(%rsp), %rdi
callq 0x5eb0
jmp 0x3508
leaq 0xe0(%rsp), %rdi
callq 0x5f80
testb $0x1, %al
jne 0x351b
jmp 0x351d
jmp 0x3555
leaq 0x7137(%rip), %rdi      # 0xa65b
leaq 0x713e(%rip), %rsi      # 0xa669
movl $0x85, %edx
leaq 0x714e(%rip), %rcx      # 0xa685
callq 0x2120
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0x37fe
leaq 0xe0(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x5fa0
movq 0x38(%rsp), %rdi
movq %rax, 0x40(%rsp)
callq 0x5fa0
movq %rax, %rdi
movl $0xa, %esi
callq 0x6020
movb %al, 0x4f(%rsp)
jmp 0x3589
movq 0x40(%rsp), %rdi
movb 0x4f(%rsp), %al
movzbl %al, %eax
addl $0x2, %eax
movsbl %al, %edx
movl $0xa, %esi
callq 0x5ff0
jmp 0x35a7
leaq 0xe0(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x5fa0
movq 0x20(%rsp), %rdi
movq %rax, 0x28(%rsp)
callq 0x5fa0
movq %rax, %rdi
movl $0x14, %esi
callq 0x6020
movb %al, 0x37(%rsp)
jmp 0x35db
movq 0x28(%rsp), %rdi
movb 0x37(%rsp), %al
movzbl %al, %eax
addl $0x2, %eax
movsbl %al, %edx
movl $0x14, %esi
callq 0x5ff0
jmp 0x35f9
movl 0xec(%rsp), %eax
movl $0x21, %ecx
xorl %edx, %edx
divl %ecx
cmpl $0x0, %edx
jne 0x3639
jmp 0x37cc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x6110
jmp 0x37fe
movl 0xec(%rsp), %eax
movl %eax, 0xdc(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0xdc(%rsp), %rsi
callq 0x6210
movq %rax, 0x18(%rsp)
jmp 0x3663
movq 0x18(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x6240
jmp 0x3677
movl 0xec(%rsp), %eax
movl $0x7, %ecx
xorl %edx, %edx
divl %ecx
cmpl $0x0, %edx
je 0x36cf
movl 0xec(%rsp), %eax
movl $0x1f, %ecx
xorl %edx, %edx
divl %ecx
cmpl $0x0, %edx
je 0x36cf
movl 0xec(%rsp), %eax
movl $0x28, %ecx
xorl %edx, %edx
divl %ecx
cmpl $0x0, %edx
je 0x36cf
movl 0xec(%rsp), %eax
movl $0x35, %ecx
xorl %edx, %edx
divl %ecx
cmpl $0x0, %edx
jne 0x3780
movl 0xec(%rsp), %eax
decl %eax
movq %rax, 0xd0(%rsp)
movl 0xd0(%rsp), %eax
movl %eax, 0xc4(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0xc4(%rsp), %rsi
callq 0x6290
movq %rax, 0x10(%rsp)
jmp 0x370a
movq 0x10(%rsp), %rax
movq %rax, 0xc8(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x62e0
movq %rax, 0xb8(%rsp)
leaq 0xc8(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x62c0
testb $0x1, %al
jne 0x3747
jmp 0x377e
movl 0xd0(%rsp), %eax
movl %eax, 0xb4(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0xb4(%rsp), %rsi
callq 0x6310
jmp 0x376c
movq 0x168(%rsp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
jmp 0x3780
movq 0x160(%rsp), %rax
movq %rax, (%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x6340
movq (%rsp), %rdi
movq %rax, 0xa8(%rsp)
leaq 0xa8(%rsp), %rsi
callq 0x60b0
movq %rax, 0x8(%rsp)
jmp 0x37b9
movq 0x8(%rsp), %rax
movq (%rax), %rcx
movq 0x160(%rsp), %rax
movq %rcx, (%rax)
leaq 0xe0(%rsp), %rdi
callq 0x6110
movl 0xec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xec(%rsp)
jmp 0x34dc
leaq 0xf0(%rsp), %rdi
callq 0x6350
jmp 0x380d
leaq 0xf0(%rsp), %rdi
callq 0x6350
jmp 0x3815
addq $0x188, %rsp            # imm = 0x188
retq
movq 0x140(%rsp), %rdi
callq 0x2260
nopw %cs:(%rax,%rax)