// File: flordan[P]ipc_benchmark/posix_mq/consumer.cpp
// Function: main
int main(int argc, char *argv[])
{
    std::cout << "\t\t\t\t\tConsumer running" << std::endl;
    int pid = getpid();
    std::cout << "\t\t\t\t\tConsumer PID " << pid << std::endl;

    mqd_t mq_producer, mq_consumer;

    std::ostringstream os;
    os << "/consumer" << pid;
    const char *consumer_queue_name = os.str().c_str();

    struct mq_attr attr;
    attr.mq_flags = 0;
    attr.mq_maxmsg = MAX_MESSAGES;
    attr.mq_msgsize = MAX_MSG_SIZE;
    attr.mq_curmsgs = 0;
    if ((mq_consumer = mq_open(consumer_queue_name, O_RDONLY | O_CREAT, QUEUE_PERMISSIONS, &attr)) == -1)
    {
        std::cerr << "\t\t\t\t\tCannot open " << consumer_queue_name << std::endl;
        return 1;
    }
    else
    {
        std::cout << "\t\t\t\t\tCreated queue " << consumer_queue_name << std::endl;
    }

    std::cout << "\t\t\t\t\tSynchronizing with producer" << std::endl;
    char producer_queue_name[MSG_BUFFER_SIZE];
    if (mq_receive(mq_consumer, producer_queue_name, MSG_BUFFER_SIZE, NULL) == -1)
    {
        std::cerr << "\t\t\t\t\tCannot read from queue " << consumer_queue_name << std::endl;
        return 1;
    }

    std::cout << "\t\t\t\t\tProducer queue: " << producer_queue_name << std::endl;
    if ((mq_producer = mq_open(producer_queue_name, O_WRONLY)) == -1)
    {
        std::cerr << "\t\t\t\t\tQueue " << producer_queue_name << " not yet open." << std::endl;
        return -1;
    }
    if (mq_send(mq_producer, "ACK", 3 + 1, 0) == -1)
    {
        std::cerr << "\t\t\t\t\tNot able to send message to consumer" << std::endl;
        return 0;
    }
    std::cout << "\t\t\t\t\tSynchronized" << std::endl;
    if (mq_close (mq_producer) == -1) {
        std::cerr << "\t\t\t\t\tNot able to close consumer queue" << std::endl;
        return 1;
    }

    struct timeval st;

    int max = 0;
    int min = 10000000;
    int total = 0;
    char in_buffer[MSG_BUFFER_SIZE];
    for (int i = 0; i < LATENCY_PROBES; i++)
    {
        if (mq_receive(mq_consumer, in_buffer, MSG_BUFFER_SIZE, NULL) == -1)
        {
            std::cerr << "\t\t\t\t\tCannot read from queue " << consumer_queue_name << std::endl;
            return 1;
        }
        gettimeofday(&st, NULL);

        double send;
        std::sscanf(in_buffer, "%lf", &send);
        int send_secs = (int)send;
        int send_usec = ((send - send_secs)*10000000)-1000000;
        send = (double)send_secs+((double)send_usec/(double)1000000);
        double now = (double)st.tv_sec + ((double)st.tv_usec)/(double)1000000;
        double diff = (now - send) * 1000000;
        if (diff < 0)
        {
            diff += 1000000;
        }
        total += diff;
        if (diff > max)
        {
            max = diff;
        }
        if (diff < min)
        {
            min = diff;
        }
    }

    std::cout << "Latency test results" << std::endl;
    std::cout << "Average " << total / LATENCY_PROBES << " us" << std::endl;
    std::cout << "Max time " << max << " us" << std::endl;
    std::cout << "Min time " << min << " us" << std::endl;

    if (mq_close (mq_consumer) == -1) {
        std::cerr << "\t\t\t\t\tNot able to close consumer queue" << std::endl;
        return 1;
    }
    if (mq_unlink (consumer_queue_name) == -1) {
        std::cerr << "\t\t\t\t\tNot able to delete consumer queue" << std::endl;
        return 1;
    }
    
    std::cout << "\t\t\t\t\tFinished" << std::endl;
}

// Assembly:
subq $0x5b8, %rsp            # imm = 0x5B8
movl $0x0, 0x5b4(%rsp)
movl %edi, 0x5b0(%rsp)
movq %rsi, 0x5a8(%rsp)
movq 0x2d08(%rip), %rdi      # 0x3fd0
movq %rdi, 0x118(%rsp)
leaq 0xd49(%rip), %rsi       # 0x2020
callq 0x10b0
movq %rax, %rdi
movq 0x2cda(%rip), %rsi      # 0x3fc0
movq %rsi, 0x120(%rsp)
callq 0x10d0
callq 0x1100
movq 0x118(%rsp), %rdi
movl %eax, 0x5a4(%rsp)
leaq 0xd28(%rip), %rsi       # 0x2036
callq 0x10b0
movq %rax, %rdi
movl 0x5a4(%rsp), %esi
callq 0x1140
movq 0x120(%rsp), %rsi
movq %rax, %rdi
callq 0x10d0
leaq 0x420(%rsp), %rdi
movq %rdi, 0x128(%rsp)
callq 0x10f0
movq 0x128(%rsp), %rdi
leaq 0xcf3(%rip), %rsi       # 0x2049
callq 0x10b0
movq %rax, 0x130(%rsp)
jmp 0x1365
movq 0x130(%rsp), %rdi
movl 0x5a4(%rsp), %esi
callq 0x1140
jmp 0x137b
leaq 0x3e8(%rsp), %rdi
leaq 0x420(%rsp), %rsi
callq 0x10c0
jmp 0x1392
leaq 0x3e8(%rsp), %rdi
callq 0x1050
movq %rax, 0x110(%rsp)
leaq 0x3e8(%rsp), %rdi
callq 0x1070
movq 0x110(%rsp), %rax
movq %rax, 0x408(%rsp)
movq $0x0, 0x3a8(%rsp)
movq $0xa, 0x3b0(%rsp)
movq $0x100, 0x3b8(%rsp) # imm = 0x100
movq $0x0, 0x3c0(%rsp)
movq 0x408(%rsp), %rdi
movl $0x40, %esi
movl $0x1b0, %edx            # imm = 0x1B0
leaq 0x3a8(%rsp), %rcx
movb $0x0, %al
callq 0x1060
movl %eax, 0x59c(%rsp)
cmpl $-0x1, %eax
jne 0x14b8
movq 0x2bc4(%rip), %rdi      # 0x3ff0
leaq 0xc20(%rip), %rsi       # 0x2053
callq 0x10b0
movq %rax, 0x108(%rsp)
jmp 0x1442
movq 0x108(%rsp), %rdi
movq 0x408(%rsp), %rsi
callq 0x10b0
movq %rax, 0x100(%rsp)
jmp 0x1461
movq 0x100(%rsp), %rdi
movq 0x2b50(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1477
movl $0x1, 0x5b4(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1caf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x418(%rsp)
movl %eax, 0x414(%rsp)
leaq 0x420(%rsp), %rdi
callq 0x1030
jmp 0x1ccb
movq 0x2b11(%rip), %rdi      # 0x3fd0
leaq 0xb9f(%rip), %rsi       # 0x2065
callq 0x10b0
movq %rax, 0xf8(%rsp)
jmp 0x14d5
movq 0xf8(%rsp), %rdi
movq 0x408(%rsp), %rsi
callq 0x10b0
movq %rax, 0xf0(%rsp)
jmp 0x14f4
movq 0xf0(%rsp), %rdi
movq 0x2abd(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x150a
jmp 0x150c
movq 0x2abd(%rip), %rdi      # 0x3fd0
leaq 0xb5f(%rip), %rsi       # 0x2079
callq 0x10b0
movq %rax, 0xe8(%rsp)
jmp 0x1529
movq 0xe8(%rsp), %rdi
movq 0x2a88(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x153f
movl 0x59c(%rsp), %edi
xorl %eax, %eax
movl %eax, %ecx
leaq 0x290(%rsp), %rsi
movl $0x10a, %edx            # imm = 0x10A
callq 0x1040
movq %rax, 0xe0(%rsp)
jmp 0x1566
movq 0xe0(%rsp), %rax
cmpq $-0x1, %rax
jne 0x15e1
movq 0x2a75(%rip), %rdi      # 0x3ff0
leaq 0xb18(%rip), %rsi       # 0x209a
callq 0x10b0
movq %rax, 0xd8(%rsp)
jmp 0x1591
movq 0xd8(%rsp), %rdi
movq 0x408(%rsp), %rsi
callq 0x10b0
movq %rax, 0xd0(%rsp)
jmp 0x15b0
movq 0xd0(%rsp), %rdi
movq 0x2a01(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x15c6
movl $0x1, 0x5b4(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1caf
movq 0x29e8(%rip), %rdi      # 0x3fd0
leaq 0xac8(%rip), %rsi       # 0x20b7
callq 0x10b0
movq %rax, 0xc8(%rsp)
jmp 0x15fe
movq 0xc8(%rsp), %rdi
leaq 0x290(%rsp), %rsi
callq 0x10b0
movq %rax, 0xc0(%rsp)
jmp 0x161d
movq 0xc0(%rsp), %rdi
movq 0x2994(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1633
leaq 0x290(%rsp), %rdi
movl $0x1, %esi
movb $0x0, %al
callq 0x1060
movl %eax, 0x5a0(%rsp)
cmpl $-0x1, %eax
jne 0x16e2
movq 0x2992(%rip), %rdi      # 0x3ff0
leaq 0xa68(%rip), %rsi       # 0x20cd
callq 0x10b0
movq %rax, 0xb8(%rsp)
jmp 0x1674
movq 0xb8(%rsp), %rdi
leaq 0x290(%rsp), %rsi
callq 0x10b0
movq %rax, 0xb0(%rsp)
jmp 0x1693
movq 0xb0(%rsp), %rdi
leaq 0xa37(%rip), %rsi       # 0x20d9
callq 0x10b0
movq %rax, 0xa8(%rsp)
jmp 0x16b1
movq 0xa8(%rsp), %rdi
movq 0x2900(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x16c7
movl $0xffffffff, 0x5b4(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x3a4(%rsp)
jmp 0x1caf
movl 0x5a0(%rsp), %edi
leaq 0x9f8(%rip), %rsi       # 0x20e8
movl $0x4, %edx
xorl %ecx, %ecx
callq 0x10e0
movl %eax, 0xa4(%rsp)
jmp 0x1705
movl 0xa4(%rsp), %eax
cmpl $-0x1, %eax
jne 0x175f
movq 0x28d8(%rip), %rdi      # 0x3ff0
leaq 0x9cd(%rip), %rsi       # 0x20ec
callq 0x10b0
movq %rax, 0x98(%rsp)
jmp 0x172e
movq 0x98(%rsp), %rdi
movq 0x2883(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1744
movl $0x0, 0x5b4(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1caf
movq 0x286a(%rip), %rdi      # 0x3fd0
leaq 0x9a9(%rip), %rsi       # 0x2116
callq 0x10b0
movq %rax, 0x90(%rsp)
jmp 0x177c
movq 0x90(%rsp), %rdi
movq 0x2835(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1792
movl 0x5a0(%rsp), %edi
callq 0x1110
cmpl $-0x1, %eax
jne 0x17f1
movq 0x2846(%rip), %rdi      # 0x3ff0
leaq 0x977(%rip), %rsi       # 0x2128
callq 0x10b0
movq %rax, 0x88(%rsp)
jmp 0x17c0
movq 0x88(%rsp), %rdi
movq 0x27f1(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x17d6
movl $0x1, 0x5b4(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1caf
movl $0x0, 0x27c(%rsp)
movl $0x989680, 0x278(%rsp) # imm = 0x989680
movl $0x0, 0x274(%rsp)
movl $0x0, 0x15c(%rsp)
cmpl $0x3e8, 0x15c(%rsp) # imm = 0x3E8
jge 0x1a6c
movl 0x59c(%rsp), %edi
xorl %eax, %eax
movl %eax, %ecx
leaq 0x160(%rsp), %rsi
movl $0x10a, %edx            # imm = 0x10A
callq 0x1040
movq %rax, 0x80(%rsp)
jmp 0x1855
movq 0x80(%rsp), %rax
cmpq $-0x1, %rax
jne 0x18c4
movq 0x2786(%rip), %rdi      # 0x3ff0
leaq 0x829(%rip), %rsi       # 0x209a
callq 0x10b0
movq %rax, 0x78(%rsp)
jmp 0x187d
movq 0x78(%rsp), %rdi
movq 0x408(%rsp), %rsi
callq 0x10b0
movq %rax, 0x70(%rsp)
jmp 0x1896
movq 0x70(%rsp), %rdi
movq 0x271e(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x18a9
movl $0x1, 0x5b4(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1caf
leaq 0x280(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1130
leaq 0x160(%rsp), %rdi
leaq 0x86a(%rip), %rsi       # 0x214e
leaq 0x150(%rsp), %rdx
movb $0x0, %al
callq 0x10a0
cvttsd2si 0x150(%rsp), %eax
movl %eax, 0x14c(%rsp)
movsd 0x150(%rsp), %xmm0
cvtsi2sdl 0x14c(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd 0x6ef(%rip), %xmm1      # 0x2010
mulsd %xmm1, %xmm0
movsd 0x6eb(%rip), %xmm1      # 0x2018
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x148(%rsp)
cvtsi2sdl 0x14c(%rsp), %xmm0
cvtsi2sdl 0x148(%rsp), %xmm1
movsd 0x6b2(%rip), %xmm2      # 0x2008
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x150(%rsp)
cvtsi2sdq 0x280(%rsp), %xmm0
cvtsi2sdq 0x288(%rsp), %xmm1
movsd 0x685(%rip), %xmm2      # 0x2008
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x140(%rsp)
movsd 0x140(%rsp), %xmm0
subsd 0x150(%rsp), %xmm0
movsd 0x65a(%rip), %xmm1      # 0x2008
mulsd %xmm1, %xmm0
movsd %xmm0, 0x138(%rsp)
xorps %xmm0, %xmm0
ucomisd 0x138(%rsp), %xmm0
jbe 0x19e3
movsd 0x637(%rip), %xmm0      # 0x2008
addsd 0x138(%rsp), %xmm0
movsd %xmm0, 0x138(%rsp)
movsd 0x138(%rsp), %xmm1
cvtsi2sdl 0x274(%rsp), %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x274(%rsp)
movsd 0x138(%rsp), %xmm0
cvtsi2sdl 0x27c(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x1a2c
cvttsd2si 0x138(%rsp), %eax
movl %eax, 0x27c(%rsp)
movsd 0x138(%rsp), %xmm1
cvtsi2sdl 0x278(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1a54
cvttsd2si 0x138(%rsp), %eax
movl %eax, 0x278(%rsp)
jmp 0x1a56
movl 0x15c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x15c(%rsp)
jmp 0x181d
movq 0x255d(%rip), %rdi      # 0x3fd0
leaq 0x6d8(%rip), %rsi       # 0x2152
callq 0x10b0
movq %rax, 0x68(%rsp)
jmp 0x1a86
movq 0x68(%rsp), %rdi
movq 0x252e(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1a99
movq 0x2530(%rip), %rdi      # 0x3fd0
leaq 0x6c0(%rip), %rsi       # 0x2167
callq 0x10b0
movq %rax, 0x60(%rsp)
jmp 0x1ab3
movq 0x60(%rsp), %rdi
movslq 0x274(%rsp), %rax
imulq $0x10624dd3, %rax, %rcx # imm = 0x10624DD3
movq %rcx, %rax
shrq $0x3f, %rax
sarq $0x26, %rcx
movl %ecx, %esi
addl %eax, %esi
callq 0x1140
movq %rax, 0x58(%rsp)
jmp 0x1ae2
movq 0x58(%rsp), %rdi
leaq 0x682(%rip), %rsi       # 0x2170
callq 0x10b0
movq %rax, 0x50(%rsp)
jmp 0x1afa
movq 0x50(%rsp), %rdi
movq 0x24ba(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1b0d
movq 0x24bc(%rip), %rdi      # 0x3fd0
leaq 0x659(%rip), %rsi       # 0x2174
callq 0x10b0
movq %rax, 0x48(%rsp)
jmp 0x1b27
movq 0x48(%rsp), %rdi
movl 0x27c(%rsp), %esi
callq 0x1140
movq %rax, 0x40(%rsp)
jmp 0x1b3f
movq 0x40(%rsp), %rdi
leaq 0x625(%rip), %rsi       # 0x2170
callq 0x10b0
movq %rax, 0x38(%rsp)
jmp 0x1b57
movq 0x38(%rsp), %rdi
movq 0x245d(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1b6a
movq 0x245f(%rip), %rdi      # 0x3fd0
leaq 0x606(%rip), %rsi       # 0x217e
callq 0x10b0
movq %rax, 0x30(%rsp)
jmp 0x1b84
movq 0x30(%rsp), %rdi
movl 0x278(%rsp), %esi
callq 0x1140
movq %rax, 0x28(%rsp)
jmp 0x1b9c
movq 0x28(%rsp), %rdi
leaq 0x5c8(%rip), %rsi       # 0x2170
callq 0x10b0
movq %rax, 0x20(%rsp)
jmp 0x1bb4
movq 0x20(%rsp), %rdi
movq 0x2400(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1bc7
movl 0x59c(%rsp), %edi
callq 0x1110
cmpl $-0x1, %eax
jne 0x1c20
movq 0x2411(%rip), %rdi      # 0x3ff0
leaq 0x542(%rip), %rsi       # 0x2128
callq 0x10b0
movq %rax, 0x18(%rsp)
jmp 0x1bf2
movq 0x18(%rsp), %rdi
movq 0x23c2(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1c05
movl $0x1, 0x5b4(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1caf
movq 0x408(%rsp), %rdi
callq 0x1080
cmpl $-0x1, %eax
jne 0x1c77
movq 0x23b7(%rip), %rdi      # 0x3ff0
leaq 0x548(%rip), %rsi       # 0x2188
callq 0x10b0
movq %rax, 0x10(%rsp)
jmp 0x1c4c
movq 0x10(%rsp), %rdi
movq 0x2368(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1c5f
movl $0x1, 0x5b4(%rsp)
movl $0x1, 0x3a4(%rsp)
jmp 0x1caf
movq 0x2352(%rip), %rdi      # 0x3fd0
leaq 0x52a(%rip), %rsi       # 0x21af
callq 0x10b0
movq %rax, 0x8(%rsp)
jmp 0x1c91
movq 0x8(%rsp), %rdi
movq 0x2323(%rip), %rsi      # 0x3fc0
callq 0x10d0
jmp 0x1ca4
movl $0x0, 0x3a4(%rsp)
leaq 0x420(%rsp), %rdi
callq 0x1030
movl 0x5b4(%rsp), %eax
addq $0x5b8, %rsp            # imm = 0x5B8
retq
movq 0x418(%rsp), %rdi
callq 0x1150