// File: flordan[P]ipc_benchmark/sysv_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;

    int mq_producer, mq_consumer;
    char *key_path=argv[1];

    key_t msg_queue_key;
    if ((msg_queue_key = ftok (key_path, pid)) == -1) {
        std::cerr << "\t\t\t\t\tCannot get key for file " << key_path <<" and project " << pid << std::endl;
         return 1;
    }
    if ((mq_consumer = msgget (msg_queue_key, IPC_CREAT |0660)) == -1) {
        std::cerr << "\t\t\t\t\tCannot get consumer queue. -"<<errno<<"-" << std::strerror(errno) << std::endl;
        return 1;
    }
    else
    {
        std::cout << "\t\t\t\t\tObtained consumer queue." << std::endl;
    }

    
    std::cout << "\t\t\t\t\tSynchronizing with producer" << std::endl;
    struct message_text in_message;
    std::cout<<"\t\t\t\t\tWaiting for producer message on queue " << mq_consumer <<"."<<std::endl;
    if (msgrcv (mq_consumer,  &in_message, sizeof (struct message_text), 0, 0) == -1) {
            std::cerr << "\t\t\t\t\tCannot read from consumer queue."  << std::endl;
            return 1;
    }
    mq_producer = in_message.reply_to;
    std::cout << "\t\t\t\t\tProducer queue: " << mq_producer << std::endl;
    struct message_text out_message;
    out_message.reply_to = mq_consumer;
    if (msgsnd (mq_producer, &out_message, sizeof (struct message_text), 0) == -1) {
            std::cerr << "\t\t\t\t\tNot able to send message to producer" << std::endl;
            return 1;
    }

    std::cout << "\t\t\t\t\tSynchronized" << std::endl;

    struct timeval st;

    int max = 0;
    int min = 10000000;
    int total = 0;
    for (int i = 0; i < LATENCY_PROBES; i++)
    {
        if (msgrcv (mq_consumer,  &in_message, sizeof (struct message_text), 0, 0) == -1) {
                std::cerr << "\t\t\t\t\tCannot read from consumer queue."  << std::endl;
                return 1;
        }
        gettimeofday(&st, NULL);

        double send;
        std::sscanf(in_message.message, "%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 $0x218, %rsp            # imm = 0x218
movl $0x0, 0x214(%rsp)
movl %edi, 0x210(%rsp)
movq %rsi, 0x208(%rsp)
movq 0x2d58(%rip), %rdi      # 0x3fd0
leaq 0xda1(%rip), %rsi       # 0x2020
callq 0x10a0
movq %rax, %rdi
movq 0x2d32(%rip), %rsi      # 0x3fc0
callq 0x10b0
callq 0x10c0
movl %eax, 0x204(%rsp)
movq 0x2d2a(%rip), %rdi      # 0x3fd0
leaq 0xd89(%rip), %rsi       # 0x2036
callq 0x10a0
movq %rax, %rdi
movl 0x204(%rsp), %esi
callq 0x1100
movq %rax, %rdi
movq 0x2cf5(%rip), %rsi      # 0x3fc0
callq 0x10b0
movq 0x208(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x1f0(%rsp)
movq 0x1f0(%rsp), %rdi
movl 0x204(%rsp), %esi
callq 0x10e0
movl %eax, 0x1ec(%rsp)
cmpl $-0x1, %eax
jne 0x1364
movq 0x2ce5(%rip), %rdi      # 0x3ff0
leaq 0xd37(%rip), %rsi       # 0x2049
callq 0x10a0
movq %rax, %rdi
movq 0x1f0(%rsp), %rsi
callq 0x10a0
movq %rax, %rdi
leaq 0xd36(%rip), %rsi       # 0x2067
callq 0x10a0
movq %rax, %rdi
movl 0x204(%rsp), %esi
callq 0x1100
movq %rax, %rdi
movq 0x2c71(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl $0x1, 0x214(%rsp)
jmp 0x1862
movl 0x1ec(%rsp), %edi
movl $0x3b0, %esi            # imm = 0x3B0
callq 0x1070
movl %eax, 0x1fc(%rsp)
cmpl $-0x1, %eax
jne 0x13f4
movq 0x2c68(%rip), %rdi      # 0x3ff0
leaq 0xce6(%rip), %rsi       # 0x2075
callq 0x10a0
movq %rax, (%rsp)
callq 0x1030
movq (%rsp), %rdi
movl (%rax), %esi
callq 0x1100
movq %rax, %rdi
leaq 0xce3(%rip), %rsi       # 0x2095
callq 0x10a0
movq %rax, 0x8(%rsp)
callq 0x1030
movl (%rax), %edi
callq 0x1050
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x10a0
movq %rax, %rdi
movq 0x2be1(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl $0x1, 0x214(%rsp)
jmp 0x1862
movq 0x2bd5(%rip), %rdi      # 0x3fd0
leaq 0xc95(%rip), %rsi       # 0x2097
callq 0x10a0
movq %rax, %rdi
movq 0x2baf(%rip), %rsi      # 0x3fc0
callq 0x10b0
movq 0x2bb3(%rip), %rdi      # 0x3fd0
leaq 0xc91(%rip), %rsi       # 0x20b5
callq 0x10a0
movq %rax, %rdi
movq 0x2b8d(%rip), %rsi      # 0x3fc0
callq 0x10b0
movq 0x2b91(%rip), %rdi      # 0x3fd0
leaq 0xc90(%rip), %rsi       # 0x20d6
callq 0x10a0
movq %rax, %rdi
movl 0x1fc(%rsp), %esi
callq 0x1100
movq %rax, %rdi
leaq 0xc4f(%rip), %rsi       # 0x20b3
callq 0x10a0
movq %rax, %rdi
movq 0x2b4d(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl 0x1fc(%rsp), %edi
leaq 0x120(%rsp), %rsi
movl $0xcc, %edx
xorl %eax, %eax
movl %eax, %ecx
xorl %r8d, %r8d
callq 0x1040
cmpq $-0x1, %rax
jne 0x14d0
movq 0x2b4b(%rip), %rdi      # 0x3ff0
leaq 0xc56(%rip), %rsi       # 0x2102
callq 0x10a0
movq %rax, %rdi
movq 0x2b05(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl $0x1, 0x214(%rsp)
jmp 0x1862
movl 0x120(%rsp), %eax
movl %eax, 0x200(%rsp)
movq 0x2aeb(%rip), %rdi      # 0x3fd0
leaq 0xc3c(%rip), %rsi       # 0x2128
callq 0x10a0
movq %rax, %rdi
movl 0x200(%rsp), %esi
callq 0x1100
movq %rax, %rdi
movq 0x2ab6(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl 0x1fc(%rsp), %eax
movl %eax, 0x54(%rsp)
movl 0x200(%rsp), %edi
leaq 0x54(%rsp), %rsi
movl $0xcc, %edx
xorl %ecx, %ecx
callq 0x1060
cmpl $-0x1, %eax
jne 0x1569
movq 0x2ab2(%rip), %rdi      # 0x3ff0
leaq 0xbf9(%rip), %rsi       # 0x213e
callq 0x10a0
movq %rax, %rdi
movq 0x2a6c(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl $0x1, 0x214(%rsp)
jmp 0x1862
movq 0x2a60(%rip), %rdi      # 0x3fd0
leaq 0xbf1(%rip), %rsi       # 0x2168
callq 0x10a0
movq %rax, %rdi
movq 0x2a3a(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl $0x0, 0x3c(%rsp)
movl $0x989680, 0x38(%rsp)   # imm = 0x989680
movl $0x0, 0x34(%rsp)
movl $0x0, 0x30(%rsp)
cmpl $0x3e8, 0x30(%rsp)      # imm = 0x3E8
jge 0x175d
movl 0x1fc(%rsp), %edi
leaq 0x120(%rsp), %rsi
movl $0xcc, %edx
xorl %eax, %eax
movl %eax, %ecx
xorl %r8d, %r8d
callq 0x1040
cmpq $-0x1, %rax
jne 0x1611
movq 0x2a0a(%rip), %rdi      # 0x3ff0
leaq 0xb15(%rip), %rsi       # 0x2102
callq 0x10a0
movq %rax, %rdi
movq 0x29c4(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl $0x1, 0x214(%rsp)
jmp 0x1862
leaq 0x40(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x10f0
leaq 0x120(%rsp), %rdi
addq $0x4, %rdi
leaq 0xb48(%rip), %rsi       # 0x217a
leaq 0x28(%rsp), %rdx
movb $0x0, %al
callq 0x1090
cvttsd2si 0x28(%rsp), %eax
movl %eax, 0x24(%rsp)
movsd 0x28(%rsp), %xmm0
cvtsi2sdl 0x24(%rsp), %xmm1
subsd %xmm1, %xmm0
movsd 0x9b0(%rip), %xmm1      # 0x2010
mulsd %xmm1, %xmm0
movsd 0x9ac(%rip), %xmm1      # 0x2018
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x20(%rsp)
cvtsi2sdl 0x24(%rsp), %xmm0
cvtsi2sdl 0x20(%rsp), %xmm1
movsd 0x97c(%rip), %xmm2      # 0x2008
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x28(%rsp)
cvtsi2sdq 0x40(%rsp), %xmm0
cvtsi2sdq 0x48(%rsp), %xmm1
movsd 0x958(%rip), %xmm2      # 0x2008
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x18(%rsp), %xmm0
subsd 0x28(%rsp), %xmm0
movsd 0x936(%rip), %xmm1      # 0x2008
mulsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
xorps %xmm0, %xmm0
ucomisd 0x10(%rsp), %xmm0
jbe 0x16fb
movsd 0x919(%rip), %xmm0      # 0x2008
addsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x10(%rsp), %xmm1
cvtsi2sdl 0x34(%rsp), %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x34(%rsp)
movsd 0x10(%rsp), %xmm0
cvtsi2sdl 0x3c(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x172f
cvttsd2si 0x10(%rsp), %eax
movl %eax, 0x3c(%rsp)
movsd 0x10(%rsp), %xmm1
cvtsi2sdl 0x38(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x174b
cvttsd2si 0x10(%rsp), %eax
movl %eax, 0x38(%rsp)
jmp 0x174d
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x15ab
movq 0x286c(%rip), %rdi      # 0x3fd0
leaq 0xa13(%rip), %rsi       # 0x217e
callq 0x10a0
movq %rax, %rdi
movq 0x2846(%rip), %rsi      # 0x3fc0
callq 0x10b0
movq 0x284a(%rip), %rdi      # 0x3fd0
leaq 0xa06(%rip), %rsi       # 0x2193
callq 0x10a0
movq %rax, %rdi
movl 0x34(%rsp), %eax
movl $0x3e8, %ecx            # imm = 0x3E8
cltd
idivl %ecx
movl %eax, %esi
callq 0x1100
movq %rax, %rdi
leaq 0x9ea(%rip), %rsi       # 0x219c
callq 0x10a0
movq %rax, %rdi
movq 0x27ff(%rip), %rsi      # 0x3fc0
callq 0x10b0
movq 0x2803(%rip), %rdi      # 0x3fd0
leaq 0x9cc(%rip), %rsi       # 0x21a0
callq 0x10a0
movq %rax, %rdi
movl 0x3c(%rsp), %esi
callq 0x1100
movq %rax, %rdi
leaq 0x9ad(%rip), %rsi       # 0x219c
callq 0x10a0
movq %rax, %rdi
movq 0x27c2(%rip), %rsi      # 0x3fc0
callq 0x10b0
movq 0x27c6(%rip), %rdi      # 0x3fd0
leaq 0x999(%rip), %rsi       # 0x21aa
callq 0x10a0
movq %rax, %rdi
movl 0x38(%rsp), %esi
callq 0x1100
movq %rax, %rdi
leaq 0x970(%rip), %rsi       # 0x219c
callq 0x10a0
movq %rax, %rdi
movq 0x2785(%rip), %rsi      # 0x3fc0
callq 0x10b0
movq 0x2789(%rip), %rdi      # 0x3fd0
leaq 0x966(%rip), %rsi       # 0x21b4
callq 0x10a0
movq %rax, %rdi
movq 0x2763(%rip), %rsi      # 0x3fc0
callq 0x10b0
movl 0x214(%rsp), %eax
addq $0x218, %rsp            # imm = 0x218
retq