// File: /workspace/github_cpp_makefile_star2_O2/shreyas-gopalakrishna[P]Concurrent-Skip-list/benchmark.cpp
// Function: main
int main(int argc, char *argv[]){

    static struct option long_options[] = {
        {"name", no_argument, NULL, 'n'},
        {"benchmark", required_argument, NULL, 'b'},
        {"help", no_argument, NULL, 'h'},
        {0, 0, 0, 0}
    };

    //Variables for options
    bool name = false;
    string benchmark = "";
    bool help = false;

    while (true) {
        int option_index = 0;
        int flag_char = getopt_long(argc, argv, "i:t:", long_options, &option_index);
        if (flag_char == -1) {
          break;
        }

        switch (flag_char) {
            case 'n':
                name = true;
                break;
            case 'b':
                benchmark = std::string(optarg);
                break;
            case 'h':
                help = true;
                break;
            case 't':
                num_threads = stoi(optarg);
                break;
            case 'i':
                max_number = stoi(optarg);
                break;
            case '?':
                break;
            default:
                exit(EXIT_FAILURE);
        }
    }

    if(name){
        cout << "\nShreyas Gopalakrishna\n";
    }

    if(help){
        show_usage();
    }

	if(argc > 2){
	    if(benchmark == "" || max_number <= 0 || num_threads < 1 ){
	        show_usage();
	    }else{

	        if(benchmark == "insert"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                insert_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }
	        else if (benchmark == "delete"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                insert_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                delete_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else if (benchmark == "search"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                insert_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                search_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else if (benchmark == "range"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                insert_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                range_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }
            else if (benchmark == "all_operations"){
                generate_input(max_number);
                skiplist = SkipList(numbers_insert.size(), 0.5);
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                all_operations_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else if (benchmark == "high_contention"){
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                high_contention_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else if (benchmark == "low_contention"){
                clock_gettime(CLOCK_MONOTONIC,&start_time);
                low_contention_benchmark();
                clock_gettime(CLOCK_MONOTONIC,&end_time);
	        }else{
	            cout << "Invalid benchmark type \n";
	            show_usage();
	        }
            show_elapsed_time();
	    }
    }else{
        show_usage();
    }
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rsi, %r14
movl %edi, %ebx
leaq 0x2c65(%rip), %rsi      # 0x6055
leaq 0x38(%rsp), %rdi
leaq 0x8(%rsp), %r12
movq %r12, %rdx
callq 0x3ab6
movq $0x0, 0x30(%rsp)
leaq 0x30a7(%rip), %r13      # 0x64b9
leaq 0x6da7(%rip), %rbp      # 0xa1c0
leaq 0x4(%rsp), %r15
movq $0x0, 0x28(%rsp)
andl $0x0, 0x4(%rsp)
movl %ebx, %edi
movq %r14, %rsi
movq %r13, %rdx
movq %rbp, %rcx
movq %r15, %r8
callq 0x22f0
cmpl $0x3f, %eax
je 0x3427
cmpl $0x62, %eax
je 0x34c7
cmpl $0x68, %eax
je 0x3504
cmpl $0x69, %eax
je 0x3498
cmpl $0x6e, %eax
je 0x34f8
cmpl $0x74, %eax
jne 0x3510
movq 0x6b48(%rip), %rax      # 0x9fb8
movq (%rax), %rsi
movq %r12, %rdi
leaq 0x3(%rsp), %rdx
callq 0x3ab6
movq %r12, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x3af1
cltq
movq %rax, 0x6d1a(%rip)      # 0xa1b0
jmp 0x34eb
movq 0x6b19(%rip), %rax      # 0x9fb8
movq (%rax), %rsi
movq %r12, %rdi
leaq 0x3(%rsp), %rdx
callq 0x3ab6
movq %r12, %rdi
xorl %esi, %esi
pushq $0xa
popq %rdx
callq 0x3af1
cltq
movq %rax, 0x6cf3(%rip)      # 0xa1b8
jmp 0x34eb
movq 0x6aea(%rip), %rax      # 0x9fb8
movq (%rax), %rsi
movq %r12, %rdi
leaq 0x3(%rsp), %rdx
callq 0x3ab6
leaq 0x38(%rsp), %rdi
movq %r12, %rsi
callq 0x2250
movq %r12, %rdi
callq 0x20d0
jmp 0x3427
movb $0x1, %al
movq %rax, 0x30(%rsp)
jmp 0x3427
movb $0x1, %al
movq %rax, 0x28(%rsp)
jmp 0x3427
cmpl $-0x1, %eax
jne 0x383e
testb $0x1, 0x30(%rsp)
je 0x3533
movq 0x6aa1(%rip), %rdi      # 0x9fc8
leaq 0x2f90(%rip), %rsi      # 0x64be
callq 0x21e0
cmpl $0x3, %ebx
setl %al
orb 0x28(%rsp), %al
testb $0x1, %al
jne 0x3859
leaq 0x2b09(%rip), %rsi      # 0x6055
leaq 0x38(%rsp), %rdi
callq 0x3b0d
testb %al, %al
jne 0x3859
cmpq $0x0, 0x6c52(%rip)      # 0xa1b8
je 0x3859
cmpq $0x0, 0x6c3c(%rip)      # 0xa1b0
je 0x3859
leaq 0x2fc8(%rip), %rsi      # 0x6549
leaq 0x38(%rsp), %rdi
callq 0x3b0d
testb %al, %al
je 0x35eb
movl 0x6c23(%rip), %edi      # 0xa1b8
callq 0x26ae
movq 0x6cf7(%rip), %rsi      # 0xa298
subq 0x6ce8(%rip), %rsi      # 0xa290
shrq $0x2, %rsi
leaq 0x8(%rsp), %rdi
movss 0x2a8f(%rip), %xmm0     # 0x6048
callq 0x4968
leaq 0x8(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x6c93(%rip)     # 0xa260
callq 0x5674
leaq 0x6c97(%rip), %rsi      # 0xa270
pushq $0x1
popq %rdi
callq 0x21d0
callq 0x2975
jmp 0x380f
leaq 0x2ee4(%rip), %rsi      # 0x64d6
leaq 0x38(%rsp), %rdi
callq 0x3b0d
testb %al, %al
je 0x3661
movl 0x6bb2(%rip), %edi      # 0xa1b8
callq 0x26ae
movq 0x6c86(%rip), %rsi      # 0xa298
subq 0x6c77(%rip), %rsi      # 0xa290
shrq $0x2, %rsi
leaq 0x8(%rsp), %rdi
movss 0x2a1e(%rip), %xmm0     # 0x6048
callq 0x4968
leaq 0x8(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x6c22(%rip)     # 0xa260
callq 0x5674
callq 0x2975
leaq 0x6c21(%rip), %rsi      # 0xa270
pushq $0x1
popq %rdi
callq 0x21d0
callq 0x2ad2
jmp 0x380f
leaq 0x2e75(%rip), %rsi      # 0x64dd
leaq 0x38(%rsp), %rdi
callq 0x3b0d
testb %al, %al
je 0x36d7
movl 0x6b3c(%rip), %edi      # 0xa1b8
callq 0x26ae
movq 0x6c10(%rip), %rsi      # 0xa298
subq 0x6c01(%rip), %rsi      # 0xa290
shrq $0x2, %rsi
leaq 0x8(%rsp), %rdi
movss 0x29a8(%rip), %xmm0     # 0x6048
callq 0x4968
leaq 0x8(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x6bac(%rip)     # 0xa260
callq 0x5674
callq 0x2975
leaq 0x6bab(%rip), %rsi      # 0xa270
pushq $0x1
popq %rdi
callq 0x21d0
callq 0x2c2f
jmp 0x380f
leaq 0x2e06(%rip), %rsi      # 0x64e4
leaq 0x38(%rsp), %rdi
callq 0x3b0d
testb %al, %al
je 0x374d
movl 0x6ac6(%rip), %edi      # 0xa1b8
callq 0x26ae
movq 0x6b9a(%rip), %rsi      # 0xa298
subq 0x6b8b(%rip), %rsi      # 0xa290
shrq $0x2, %rsi
leaq 0x8(%rsp), %rdi
movss 0x2932(%rip), %xmm0     # 0x6048
callq 0x4968
leaq 0x8(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x6b36(%rip)     # 0xa260
callq 0x5674
callq 0x2975
leaq 0x6b35(%rip), %rsi      # 0xa270
pushq $0x1
popq %rdi
callq 0x21d0
callq 0x2d8c
jmp 0x380f
leaq 0x2d96(%rip), %rsi      # 0x64ea
leaq 0x38(%rsp), %rdi
callq 0x3b0d
testb %al, %al
je 0x37bb
movl 0x6a50(%rip), %edi      # 0xa1b8
callq 0x26ae
movq 0x6b24(%rip), %rsi      # 0xa298
subq 0x6b15(%rip), %rsi      # 0xa290
shrq $0x2, %rsi
leaq 0x8(%rsp), %rdi
movss 0x28bc(%rip), %xmm0     # 0x6048
callq 0x4968
leaq 0x8(%rsp), %rdi
movups (%rdi), %xmm0
movups %xmm0, 0x6ac0(%rip)     # 0xa260
callq 0x5674
leaq 0x6ac4(%rip), %rsi      # 0xa270
pushq $0x1
popq %rdi
callq 0x21d0
callq 0x2f87
jmp 0x380f
leaq 0x2d37(%rip), %rsi      # 0x64f9
leaq 0x38(%rsp), %rdi
callq 0x3b0d
testb %al, %al
je 0x37e6
leaq 0x6a99(%rip), %rsi      # 0xa270
pushq $0x1
popq %rdi
callq 0x21d0
callq 0x30c6
jmp 0x380f
leaq 0x2d1c(%rip), %rsi      # 0x6509
leaq 0x38(%rsp), %rdi
callq 0x3b0d
testb %al, %al
je 0x3846
leaq 0x6a6e(%rip), %rsi      # 0xa270
pushq $0x1
popq %rdi
callq 0x21d0
callq 0x321a
leaq 0x6a6a(%rip), %rsi      # 0xa280
pushq $0x1
popq %rdi
callq 0x21d0
callq 0x263e
leaq 0x38(%rsp), %rdi
callq 0x20d0
xorl %eax, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x1
popq %rdi
callq 0x2240
movq 0x677b(%rip), %rdi      # 0x9fc8
leaq 0x2cc4(%rip), %rsi      # 0x6518
callq 0x21e0
callq 0x255c
jmp 0x387f
jmp 0x387f
jmp 0x387f
jmp 0x387f
jmp 0x387f
jmp 0x387f
jmp 0x387f
jmp 0x386e
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x20d0
jmp 0x3882
jmp 0x387f
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x20d0
movq %rbx, %rdi
callq 0x2310